text:
Converting code for driver IC IL0373 to SSD1680
I'm working on epaper display, and writing code in Segger embedded studio for nRF52840DK.
Below is code for Driver IC IL0373 epaper display, has no response on paper display as it have driver IC SSD1680 here
Below paper.c
#include "paper.h"
#include <string.h>

#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_drv_spi.h"

#define PAPER_RST_PIN 13
#define PAPER_DC_PIN  14

#define PAPER_SPI_INSTANCE 0
#define PAPER_SPI_SS_PIN   29
#define PAPER_SPI_MOSI_PIN 4
#define PAPER_SPI_SCK_PIN  3

#define PAPER_BYTE_WIDTH ((PAPER_PIXEL_WIDTH % 8 == 0) ? PAPER_PIXEL_WIDTH / 8 : PAPER_PIXEL_WIDTH / 8 + 1)
#define PAPER_BYTE_HEIGHT PAPER_PIXEL_HEIGHT
#define PAPER_BUFLEN PAPER_BYTE_WIDTH * PAPER_BYTE_HEIGHT

#define PAPER_CMD_PWR  0x01
#define PAPER_CMD_BTST 0x06
#define PAPER_CMD_PON  0x04
#define PAPER_CMD_PSR  0x00
#define PAPER_CMD_PLL  0x30
#define PAPER_CMD_TRES 0x61
#define PAPER_CMD_VDCD 0x82
#define PAPER_CMD_VCOM 0x50
#define PAPER_CMD_LUT_VCDC 0x20
#define PAPER_CMD_LUT_WW 0x21
#define PAPER_CMD_LUT_BW 0x22
#define PAPER_CMD_LUT_WB 0x23
#define PAPER_CMD_LUT_BB 0x24
#define PAPER_CMD_DISP 0x12

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(PAPER_SPI_INSTANCE);

static uint8_t paper_cmd_pwr[] = {
  PAPER_CMD_PWR,
  0x03, 0x00, 0x2b, 0x2b, 0x03,
};

static uint8_t paper_cmd_btst[] = {
  PAPER_CMD_BTST,
  0x17, 0x17, 0x17,
};

static uint8_t paper_cmd_pon[] = {
  PAPER_CMD_PON,
};

static uint8_t paper_cmd_psr[] = {
  PAPER_CMD_PSR,
  0xbf, 0x0d,
};

static uint8_t paper_cmd_pll[] = {
  PAPER_CMD_PLL,
  0x3a,
};

static uint8_t paper_cmd_tres[] = {
  PAPER_CMD_TRES,
  PAPER_PIXEL_WIDTH,
  (PAPER_PIXEL_HEIGHT >> 8) & 0xff,
  PAPER_PIXEL_HEIGHT & 0xff,
};

static uint8_t paper_cmd_vdcd[] = {
  PAPER_CMD_VDCD,
  0x28,
};

static uint8_t paper_cmd_vcom[] = {
  PAPER_CMD_VCOM,
  0x97
};

static uint8_t paper_cmd_lut_vcdc[] = {
  PAPER_CMD_LUT_VCDC,
  0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00,
};

static uint8_t paper_cmd_lut_ww[] = {
  PAPER_CMD_LUT_WW,
  0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
  0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_bw[] = {
  PAPER_CMD_LUT_BW,
  0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,
  0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
  0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_wb[] = {
  PAPER_CMD_LUT_WB,
  0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_bb[] = {
  PAPER_CMD_LUT_BB,
  0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_disp[] = {
  PAPER_CMD_DISP,
};

static uint8_t paper_buffer[PAPER_BUFLEN];
static uint8_t paper_prev_buffer[PAPER_BUFLEN];

static void paper_begin_command(void) {
  nrf_gpio_pin_clear(PAPER_DC_PIN);
}

static void paper_begin_data(void) {
  nrf_gpio_pin_set(PAPER_DC_PIN);
}

static ret_code_t paper_tx_cmd(uint8_t *cmd, uint8_t length) {
  ret_code_t ret;

  paper_begin_command();
  ret = nrf_drv_spi_transfer(&spi, cmd, 1, NULL, 0);
  if (ret != NRF_SUCCESS) return ret;

  if (length - 1 > 0) {
    paper_begin_data();
    ret = nrf_drv_spi_transfer(&spi, cmd + 1, length - 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  return ret;
}

static void paper_reset(void) {
  nrf_gpio_pin_clear(PAPER_RST_PIN);
  nrf_delay_ms(200);
  nrf_gpio_pin_set(PAPER_RST_PIN);
  nrf_delay_ms(200);
}

static ret_code_t paper_tx_lut(void) {
  ret_code_t ret;

  ret = paper_tx_cmd(paper_cmd_vcom, sizeof(paper_cmd_vcom));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_vcdc, sizeof(paper_cmd_lut_vcdc));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_ww, sizeof(paper_cmd_lut_ww));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_bw, sizeof(paper_cmd_lut_bw));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_wb, sizeof(paper_cmd_lut_wb));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_bb, sizeof(paper_cmd_lut_bb));
  if (ret != NRF_SUCCESS) return ret;

  return ret;
}

static ret_code_t _paper_display(void) {
  ret_code_t ret;

  /*
   * TODO transfer chunks of 256 bytes rather than calling nrf_drv_spi_transfer
   * for each byte.
   */

  uint8_t command[1];

  command[0] = 0x10;
  ret = paper_tx_cmd(command, 1);
  if (ret != NRF_SUCCESS) return ret;

  paper_begin_data();
  for (int i = 0; i < PAPER_BUFLEN; i++) {
    ret = nrf_drv_spi_transfer(&spi, paper_prev_buffer + i, 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  nrf_delay_ms(10);

  /*
   * TODO i'm not yet sure about the purpose of sending the previous buffer too.
   * just sending 0x00s works pretty good. when sending the actual previous
   * image buffer, it looks like sections that have not changed become kinda
   * dirty / greyish (which could be useful because one can use three colors).
   */

  // memcpy(paper_prev_buffer, paper_buffer, PAPER_BUFLEN);

  command[0] = 0x13;
  ret = paper_tx_cmd(command, 1);
  if (ret != NRF_SUCCESS) return ret;

  paper_begin_data();
  for (int i = 0; i < PAPER_BUFLEN; i++) {
    ret = nrf_drv_spi_transfer(&spi, paper_buffer + i, 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  nrf_delay_ms(10);

  ret = paper_tx_lut();
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_disp, sizeof(paper_cmd_disp));
  if (ret != NRF_SUCCESS) return ret;

  nrf_delay_ms(100); // TODO use busy pin rather than arbitrary delays

  return ret;
}

ret_code_t paper_init(void) {
  ret_code_t ret;

  nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
  spi_config.ss_pin   = PAPER_SPI_SS_PIN;
  spi_config.mosi_pin = PAPER_SPI_MOSI_PIN;
  spi_config.sck_pin  = PAPER_SPI_SCK_PIN;

  ret = nrf_drv_spi_init(&spi, &spi_config, NULL, NULL);
  if (ret != NRF_SUCCESS) return ret;

  nrf_gpio_cfg_output(PAPER_RST_PIN);
  nrf_gpio_cfg_output(PAPER_DC_PIN);

  paper_reset();

  ret = paper_tx_cmd(paper_cmd_pwr, sizeof(paper_cmd_pwr));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_btst, sizeof(paper_cmd_btst));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_pon, sizeof(paper_cmd_pon));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_psr, sizeof(paper_cmd_psr));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_pll, sizeof(paper_cmd_pll));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_tres, sizeof(paper_cmd_tres));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_vdcd, sizeof(paper_cmd_vdcd));
  if (ret != NRF_SUCCESS) return ret;

  memset(paper_buffer, 0xff, PAPER_BUFLEN);
  memset(paper_prev_buffer, 0x00, PAPER_BUFLEN);

  return ret;
}

void paper_uninit(void) {
  // TODO uninit spi and free buffers
}

void paper_pixel_draw(uint16_t x, uint16_t y, uint32_t color) {
  ASSERT(x < PAPER_PIXEL_WIDTH);
  ASSERT(y < PAPER_PIXEL_HEIGHT);

  int bitn = y * PAPER_PIXEL_WIDTH + x;
  int byten = bitn / 8;
  bitn = 8 - bitn % 8 - 1;

  if (color == 0) paper_buffer[byten] |= 1UL << (bitn);
  else paper_buffer[byten] &= ~(1UL << (bitn));
}

void paper_rect_draw(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
  ASSERT(x + width < PAPER_PIXEL_WIDTH);
  ASSERT(y + height < PAPER_PIXEL_HEIGHT);

  for (uint16_t _x = x; _x < x + width; _x++)
    for (uint16_t _y = y; _y < y + height; _y++)
      paper_pixel_draw(_x, _y, color);
}

void paper_display(void) {
  APP_ERROR_CHECK(_paper_display());
}

void paper_rotation_set(nrf_lcd_rotation_t rotation) {
  UNUSED_PARAMETER(rotation);

  // TODO
}

void paper_display_invert(bool invert) {
  UNUSED_PARAMETER(invert);

  // TODO
}

The e-paper display I have are with SSD1680 IC, here
In Adafruit Library I found the following parameters
For SSD1680, here
#define SSD1680_DRIVER_CONTROL 0x01
#define SSD1680_GATE_VOLTAGE 0x03
#define SSD1680_SOURCE_VOLTAGE 0x04
#define SSD1680_PROGOTP_INITIAL 0x08
#define SSD1680_PROGREG_INITIAL 0x09
#define SSD1680_READREG_INITIAL 0x0A
#define SSD1680_BOOST_SOFTSTART 0x0C
#define SSD1680_DEEP_SLEEP 0x10
#define SSD1680_DATA_MODE 0x11
#define SSD1680_SW_RESET 0x12
#define SSD1680_TEMP_CONTROL 0x18
#define SSD1680_TEMP_WRITE 0x1A
#define SSD1680_MASTER_ACTIVATE 0x20
#define SSD1680_DISP_CTRL1 0x21
#define SSD1680_DISP_CTRL2 0x22
#define SSD1680_WRITE_RAM1 0x24
#define SSD1680_WRITE_RAM2 0x26
#define SSD1680_WRITE_VCOM 0x2C
#define SSD1680_READ_OTP 0x2D
#define SSD1680_READ_STATUS 0x2F
#define SSD1680_WRITE_LUT 0x32
#define SSD1680_WRITE_BORDER 0x3C
#define SSD1680_SET_RAMXPOS 0x44
#define SSD1680_SET_RAMYPOS 0x45
#define SSD1680_SET_RAMXCOUNT 0x4E
#define SSD1680_SET_RAMYCOUNT 0x4F

For IL0373, here
#define IL0373_PANEL_SETTING 0x00
#define IL0373_POWER_SETTING 0x01
#define IL0373_POWER_OFF 0x02
#define IL0373_POWER_OFF_SEQUENCE 0x03
#define IL0373_POWER_ON 0x04
#define IL0373_POWER_ON_MEASURE 0x05
#define IL0373_BOOSTER_SOFT_START 0x06
#define IL0373_DEEP_SLEEP 0x07
#define IL0373_DTM1 0x10
#define IL0373_DATA_STOP 0x11
#define IL0373_DISPLAY_REFRESH 0x12
#define IL0373_DTM2 0x13
#define IL0373_PDTM1 0x14
#define IL0373_PDTM2 0x15
#define IL0373_PDRF 0x16
#define IL0373_LUT1 0x20
#define IL0373_LUTWW 0x21
#define IL0373_LUTBW 0x22
#define IL0373_LUTWB 0x23
#define IL0373_LUTBB 0x24
#define IL0373_PLL 0x30
#define IL0373_CDI 0x50
#define IL0373_RESOLUTION 0x61
#define IL0373_VCM_DC_SETTING 0x82
#define IL0373_PARTIAL_WINDOW 0x90
#define IL0373_PARTIAL_ENTER 0x91
#define IL0373_PARTIAL_EXIT 0x92

I need help with how to convert the use of IL0373 in paper.c to SSD1680, or is it even possible to do so?


text:
Configure CA to connect to server with Ethernet
I'm using Ethernet module ENC28J60 with ESP32 on Arduino IDE.
I could establish a secure connection using WifiClientSecure.h
here code
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>

const char* ssid = "wifi";
const char* password = "1234567890";

const char* serverName = "https://myserver.com/v1";

const char* userName = "admin";
const char* pass = "pass";

unsigned long previous;

const char* rootCACertificate =
  "-----BEGIN CERTIFICATE-----\n"
  ...
  "-----END CERTIFICATE-----\n";

void setup() {
  Serial.begin(115200);
  Serial.println();

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print('.');
    delay(1000);
  }

  Serial.println(WiFi.localIP());

}

void loop() {
  if ((WiFi.status() == WL_CONNECTED))
  {
    WiFiClientSecure client;

    client.setCACert(rootCACertificate);
    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");
    if (https.begin(client, serverName))
    {
      https.setAuthorization(userName, pass);
      https.addHeader("Content-Type", "application/json");
      ...
      https.end();

    }
  }
  else
  {
    Serial.printf("Unable to connect to wifi\n");
  }
  Serial.println();
  Serial.println("Waiting 60sec before the next round...");
  delay(60000);
}

But there is no support for Ethernet.
Could anyone suggest a way to connect to server with EthernetENC or any other Library?

if you use ethernet module supported by the esp32, you can use the code you have. https://github.com/espressif/arduino-esp32/tree/master/libraries/Ethernet/examples

@Juraj So I just need to change Ethernet Module to Ethernet Hardware TCP/IP W5500 Ethernet Network Module? How to configure CA?

you will use the same code as with WiFi. only at the low level it will go through the W5500

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Difference between (*(volatile unsigned int *) and (volatile unsigned int)?
I have been watching tutorials on STM32 bare metal programming. I couldn't understand the  purpose of the below code
 #define RCC_AHB1EN_R (*(volatile unsigned int *)(RCC_BASE + AHB1EN_R_OFFSET))

and why it's different from
#define RCC_AHB1EN_R (volatile unsigned int)(RCC_BASE + AHB1EN_R_OFFSET))

I understand (volatile unsigned int *) is used to typecast any data, so it code will get its address value, not the data itself, then adding (*) will pick the data value of the address. I know why volatile is used to tell not to optimize this code for this data.
That's my basic knowledge of pointers, if I wasn't right till now please correct me.
So my question are

Why and what's the purpose of typecasting the data to address(pointer) and then use its value?

Why not we directly use the value itself (of course with volatile typecasting) like

#define RCC_AHB1EN_R (volatile unsigned int)(RCC_BASE + AHB1EN_R_OFFSET))

If we can use whichever we can, are there any benefits of one over the other?

Judging from the context, RCC_BASE seems to be a preprocessor macro
that expands to the base address of some peripheral called “RCC”, and
AHB1EN_R_OFFSET a similar macro for the offset of the AHB1EN_R I/O
register relative to this base address. Then,
RCC_BASE + AHB1EN_R_OFFSET

is the memory-mapped address of the register. This address is just a
number. If you cast it to volatile unsigned int, you still get the
same number. If you want to access the I/O register, you have to tell
the compiler that this number is actually an address (i.e. the numeric
value of a pointer), and then access the memory bus at that address
(i.e. dereference the pointer):

(volatile unsigned int *) converts the numeric value to a pointer
(because of the *), that points to a volatile unsigned int

the * at the front of the macro dereferences the pointer and thus
performs the actual access to the I/O register.

Okay, please tell me if I get this right. (*(volatile unsigned int *)(RCC_BASE + AHB1EN_R_OFFSET)) will make (RCC_BASE + AHB1EN_R_OFFSET) consider as address and get value at this address as there is * before it.
But what I understand from the use of volatile is telling the compiler not to optimize the value of the variable. I got confused with volatile with a pointer. So, even in this case volatile is given for the value stored at that address, not the address value itself?

@JustdoinGodswork: Indeed. A declaration such as TYPE * volatile p; would make p a volatile pointer, whereas volatile TYPE *p; makes p a pointer to volatile data. The cast we see here matches the later declaration.

In the first line, RCC_AHB1EN_R is a pointer to location.
you got that from the casting.
#define RCC_AHB1EN_R (*(volatile unsigned int *)(RCC_BASE + AHB1EN_R_OFFSET))
In the second line, RCC_AHB1EN_R holds a base address which is an integer.
#define RCC_AHB1EN_R (volatile unsigned int)(RCC_BASE + AHB1EN_R_OFFSET))
hope this give you clarity?

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Conversion from `const char* datac="0x21,0x10,0xfa,0x7a,0xff";` to `uint8_t datat[]={0x21, 0x10, 0xfa, 0x7a, 0xff}`
The below reading data from API:
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "****";
const char* pass = "****";

void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, pass);
  Serial.print("COnnecting");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.print("\nIP Address");
  Serial.println(WiFi.localIP());
}

void loop() {
  const char* root_0_id ;
  const char* root_0_Title ;
  if (WiFi.status() == WL_CONNECTED)
  {
    long rnd = random(1, 3);
    HTTPClient client;

    client.begin("https://6336d6c365d1e8ef267481aa.mockapi.io/api/bitmap/images?id=1");
    int httpCode = client.GET();

    if (httpCode > 0) {
      String payload = client.getString();
      Serial.println("\nstatuscode: " + String(httpCode));
      if (payload == "[]")
        Serial.println("\nNOT FOUND");
      else
      {

        DynamicJsonDocument doc(49152);
        DeserializationError error = deserializeJson(doc, payload);
        if (error) {
          Serial.print("deserializeJson() failed: ");
          Serial.println(error.c_str());
          return;
        }

        root_0_id = doc[0]["id"]; // "41"
        root_0_Title = doc[0]["Bitmap"];

        Serial.print("\n\nData : ");
        Serial.println(root_0_Title);

        Serial.println(sizeof(root_0_Title));
        client.end();
        dataReceived = 1;
        delay(10000);

      }

    }
    else {
      Serial.println("Error on HTTP request");
    }
  }
}

I need help with parsing the const char* root_0_Title="0x21,0x10,0xfa,0x7a,0xff", to uint8_t[5]={0x21, 0x10, 0xfa, 0x7a, 0xff}?

almost the same question on SO with answer using standard library https://stackoverflow.com/questions/73969744/how-to-convert-const-char-root-0-title-0x21-0x32-i-0x0f-0x00-to-uint8-t-d

@Juraj I have tried it but I thought it was for probably C not Arduino C that's why its not compiling for ESP32. Also, it's a bit higher level for me to make changes. I wanted to know the for ESP32 perspective. But if you saying it should work with ESP32 too? I'll delete this question

you can use strtok (string tokenizer) and strtol (string to long) C functions.
  int count = 0;
  uint8_t bytes[MAX_SIZE];
  char* tok = strtok(root_0_Title, ",");
  while (tok != NULL) {
    bytes[count++] = strtol(tok, NULL, 16);
    tok = strtok(NULL, ",");
  }

const char* root_0_Title causing error as char * strtok ( char * str, const char * delimiters );

remove const from const char* root_0_Title ;


text:
How does a callback function get revoke itself eg. Connect function get revoked when there is new connection
Further to my previous question here
Can anyone help me understand how the callback function gets revoked itself? The connect function, disconnect function.
BLE custom UUID code source here
Another example is BLEUART which have callback functions:
/*********************************************************************
 This is an example for our nRF52 based Bluefruit LE modules

 Pick one up today in the adafruit shop!

 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 All text above, and the splash screen below must be included in
 any redistribution
*********************************************************************/

/*
 * This sketch demonstrate the central API(). A additional bluefruit
 * that has bleuart as peripheral is required for the demo.
 */
#include <bluefruit.h>

BLEClientBas  clientBas;  // battery client
BLEClientDis  clientDis;  // device information client
BLEClientUart clientUart; // bleuart client

void setup()
{
  Serial.begin(115200);
//  while ( !Serial ) delay(10);   // for nrf52840 with native usb

  Serial.println("Bluefruit52 Central BLEUART Example");
  Serial.println("-----------------------------------\n");

  // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
  // SRAM usage required by SoftDevice will increase dramatically with number of connections
  Bluefruit.begin(0, 1);

  Bluefruit.setName("Bluefruit52 Central");

  // Configure Battery client
  clientBas.begin();

  // Configure DIS client
  clientDis.begin();

  // Init BLE Central Uart Serivce
  clientUart.begin();
  clientUart.setRxCallback(bleuart_rx_callback);

  // Increase Blink rate to different from PrPh advertising mode
  Bluefruit.setConnLedInterval(250);

  // Callbacks for Central
  Bluefruit.Central.setConnectCallback(connect_callback);
  Bluefruit.Central.setDisconnectCallback(disconnect_callback);

  /* Start Central Scanning
   * - Enable auto scan if disconnected
   * - Interval = 100 ms, window = 80 ms
   * - Don't use active scan
   * - Start(timeout) with timeout = 0 will scan forever (until connected)
   */
  Bluefruit.Scanner.setRxCallback(scan_callback);
  Bluefruit.Scanner.restartOnDisconnect(true);
  Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
  Bluefruit.Scanner.useActiveScan(false);
  Bluefruit.Scanner.start(0);                   // // 0 = Don't stop scanning after n seconds
}

/**
 * Callback invoked when scanner pick up an advertising data
 * @param report Structural advertising data
 */
void scan_callback(ble_gap_evt_adv_report_t* report)
{
  // Check if advertising contain BleUart service
  if ( Bluefruit.Scanner.checkReportForService(report, clientUart) )
  {
    Serial.print("BLE UART service detected. Connecting ... ");

    // Connect to device with bleuart service in advertising
    Bluefruit.Central.connect(report);
  }else
  {
    // For Softdevice v6: after received a report, scanner will be paused
    // We need to call Scanner resume() to continue scanning
    Bluefruit.Scanner.resume();
  }
}

/**
 * Callback invoked when an connection is established
 * @param conn_handle
 */
void connect_callback(uint16_t conn_handle)
{
  Serial.println("Connected");

  Serial.print("Dicovering Device Information ... ");
  if ( clientDis.discover(conn_handle) )
  {
    Serial.println("Found it");
    char buffer[32+1];

    // read and print out Manufacturer
    memset(buffer, 0, sizeof(buffer));
    if ( clientDis.getManufacturer(buffer, sizeof(buffer)) )
    {
      Serial.print("Manufacturer: ");
      Serial.println(buffer);
    }

    // read and print out Model Number
    memset(buffer, 0, sizeof(buffer));
    if ( clientDis.getModel(buffer, sizeof(buffer)) )
    {
      Serial.print("Model: ");
      Serial.println(buffer);
    }

    Serial.println();
  }else
  {
    Serial.println("Found NONE");
  }

  Serial.print("Dicovering Battery ... ");
  if ( clientBas.discover(conn_handle) )
  {
    Serial.println("Found it");
    Serial.print("Battery level: ");
    Serial.print(clientBas.read());
    Serial.println("%");
  }else
  {
    Serial.println("Found NONE");
  }

  Serial.print("Discovering BLE Uart Service ... ");
  if ( clientUart.discover(conn_handle) )
  {
    Serial.println("Found it");

    Serial.println("Enable TXD's notify");
    clientUart.enableTXD();

    Serial.println("Ready to receive from peripheral");
  }else
  {
    Serial.println("Found NONE");

    // disconnect since we couldn't find bleuart service
    Bluefruit.disconnect(conn_handle);
  }
}

/**
 * Callback invoked when a connection is dropped
 * @param conn_handle
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

/**
 * Callback invoked when uart received data
 * @param uart_svc Reference object to the service where the data
 * arrived. In this example it is clientUart
 */
void bleuart_rx_callback(BLEClientUart& uart_svc)
{
  Serial.print("[RX]: ");

  while ( uart_svc.available() )
  {
    Serial.print( (char) uart_svc.read() );
  }

  Serial.println();
}

void loop()
{
  if ( Bluefruit.Central.connected() )
  {
    // Not discovered yet
    if ( clientUart.discovered() )
    {
      // Discovered means in working state
      // Get Serial input and send to Peripheral
      if ( Serial.available() )
      {
        delay(2); // delay a bit for all characters to arrive

        char str[20+1] = { 0 };
        Serial.readBytes(str, 20);

        clientUart.print( str );
      }
    }
  }
}

The following helps set the callback functions:
clientUart.setRxCallback(bleuart_rx_callback);
...
Bluefruit.Central.setConnectCallback(connect_callback);
...
Bluefruit.Central.setDisconnectCallback(disconnect_callback);

Tracing back the libraries I found :
void BLEPeriph::setConnectCallback( ble_connect_callback_t fp )
{
  _connect_cb = fp;
}

void BLEPeriph::setDisconnectCallback( ble_disconnect_callback_t fp )
{
  _disconnect_cb = fp;
}

But I can't understand how this initializes the calling of the connect or disconnect function while getting a new connection or break in connection respectively.

All a callback function assignment does is link an internal pointer to the function that you provide.
Any time the callback is needed to be called the code just uses the pointer that your function has been assigned to.
Thus _connect_cb and connect_callback() are one and the same thing. Any time connect_callback() would be expected to be used _connect_cb() is used instead.
It is, in effect, just creating an internal alias to your code then using that alias to call your code when it needs to.

Okay I got the pointer assigning part clear and _connect_cb have assigned value of the function connect_callback(). But the one more thing I need to clarify is where did I call _connect_cb in my main code?
When there is new connection it get revoke itself. So I want to know is it defined somewhere in the library?

You don't call anything. That's the whole point of a callback - it's the library that calls it. Somewhere in the library there will be a call to _connect_cb().

@JustdoinGodswork, you call BLE functions in loop(). any of them can call the callback

Okay got it, I'll try searching the connect_cb() in the libraries.


text:
text section exceeds available space in board
When I compile this code it gives the error mentioned above.
I saw online a way to resolve this: Serial.println(F("..."));
For fixed string literal I changed it but still didn't work.
I'm compiling this for ESP32 board.
#include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"
#include <DHT.h>
#include <SimpleTimer.h>

const char *service_name = "PROV_SmartHome";
const char *pop = "1234";

// define the Chip Id
uint32_t espChipId = 5;

// define the Node Name
char nodeName[] = "ESP32_Smarthome";

// define the Device Names
char deviceName_1[] = "Switch1";
char deviceName_2[] = "Switch2";
char deviceName_3[] = "Switch3";
char deviceName_4[] = "Switch4";

// define the GPIO connected with Relays and switches
static uint8_t RelayPin1 = 23;  //D23
static uint8_t RelayPin2 = 22;  //D22
static uint8_t RelayPin3 = 21;  //D21
static uint8_t RelayPin4 = 19;  //D19

static uint8_t SwitchPin1 = 13;  //D13
static uint8_t SwitchPin2 = 12;  //D12
static uint8_t SwitchPin3 = 14;  //D14
static uint8_t SwitchPin4 = 27;  //D27

static uint8_t wifiLed      = 2;   //D2
static uint8_t gpio_reset   = 0;
static uint8_t DHTPIN       = 18; // D18  pin connected with DHT
static uint8_t LDR_PIN      = 39; // VN  pin connected with LDR

/* Variable for reading pin status*/
// Relay State
bool toggleState_1 = LOW; //Define integer to remember the toggle state for relay 1
bool toggleState_2 = LOW; //Define integer to remember the toggle state for relay 2
bool toggleState_3 = LOW; //Define integer to remember the toggle state for relay 3
bool toggleState_4 = LOW; //Define integer to remember the toggle state for relay 4

// Switch State
bool SwitchState_1 = LOW;
bool SwitchState_2 = LOW;
bool SwitchState_3 = LOW;
bool SwitchState_4 = LOW;

float temperature1 = 0;
float humidity1   = 0;
float ldrVal  = 0;

DHT dht(DHTPIN, DHT11);  //For DHT 11
//DHT dht(DHTPIN, DHT22);  //For DHT 22

SimpleTimer Timer;

//The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
static Switch my_switch1(deviceName_1, &RelayPin1);
static Switch my_switch2(deviceName_2, &RelayPin2);
static Switch my_switch3(deviceName_3, &RelayPin3);
static Switch my_switch4(deviceName_4, &RelayPin4);
static TemperatureSensor temperature("Temperature");
static TemperatureSensor humidity("Humidity");
static TemperatureSensor ldr("LDR");

void sysProvEvent(arduino_event_t *sys_event)
{
  switch (sys_event->event_id) {
    case ARDUINO_EVENT_PROV_START:
#if CONFIG_IDF_TARGET_ESP32
      Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
      printQR(service_name, pop, "ble");
#else
      Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
      printQR(service_name, pop, "softap");
#endif
      break;
    case ARDUINO_EVENT_WIFI_STA_CONNECTED:
      Serial.printf("\nConnected to Wi-Fi!\n");
      digitalWrite(wifiLed, true);
      break;
  }
}

void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx)
{
  const char *device_name = device->getDeviceName();
  const char *param_name = param->getParamName();

  if (strcmp(device_name, deviceName_1) == 0) {

    Serial.printf("Lightbulb = %s\n", val.val.b ? "true" : "false");

    if (strcmp(param_name, "Power") == 0) {
      Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
      toggleState_1 = val.val.b;
      (toggleState_1 == false) ? digitalWrite(RelayPin1, HIGH) : digitalWrite(RelayPin1, LOW);
      param->updateAndReport(val);
    }

  } else if (strcmp(device_name, deviceName_2) == 0) {

    Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

    if (strcmp(param_name, "Power") == 0) {
      Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
      toggleState_2 = val.val.b;
      (toggleState_2 == false) ? digitalWrite(RelayPin2, HIGH) : digitalWrite(RelayPin2, LOW);
      param->updateAndReport(val);
    }

  } else if (strcmp(device_name, deviceName_3) == 0) {

    Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

    if (strcmp(param_name, "Power") == 0) {
      Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
      toggleState_3 = val.val.b;
      (toggleState_3 == false) ? digitalWrite(RelayPin3, HIGH) : digitalWrite(RelayPin3, LOW);
      param->updateAndReport(val);
    }

  } else if (strcmp(device_name, deviceName_4) == 0) {

    Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

    if (strcmp(param_name, "Power") == 0) {
      Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
      toggleState_4 = val.val.b;
      (toggleState_4 == false) ? digitalWrite(RelayPin4, HIGH) : digitalWrite(RelayPin4, LOW);
      param->updateAndReport(val);
    }

  }
}

void readSensor() {

  ldrVal = map(analogRead(LDR_PIN), 400, 4200, 0, 100);
  Serial.print("LDR - "); Serial.println(ldrVal);
  float h = dht.readHumidity();
  float t = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  else {
    humidity1 = h;
    temperature1 = t;
    Serial.print("Temperature - "); Serial.println(t);
    Serial.print("Humidity - "); Serial.println(h);
  }
}

void sendSensor()
{
  readSensor();
  temperature.updateAndReportParam("Temperature", temperature1);
  humidity.updateAndReportParam("Temperature", humidity1);
  ldr.updateAndReportParam("Temperature", ldrVal);
}

void manual_control()
{
  if (digitalRead(SwitchPin1) == LOW && SwitchState_1 == LOW) {
    digitalWrite(RelayPin1, LOW);
    toggleState_1 = 1;
    SwitchState_1 = HIGH;
    my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_1);
    Serial.println("Switch-1 on");
  }
  if (digitalRead(SwitchPin1) == HIGH && SwitchState_1 == HIGH) {
    digitalWrite(RelayPin1, HIGH);
    toggleState_1 = 0;
    SwitchState_1 = LOW;
    my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_1);
    Serial.println("Switch-1 off");
  }
  if (digitalRead(SwitchPin2) == LOW && SwitchState_2 == LOW) {
    digitalWrite(RelayPin2, LOW);
    toggleState_2 = 1;
    SwitchState_2 = HIGH;
    my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_2);
    Serial.println("Switch-2 on");
  }
  if (digitalRead(SwitchPin2) == HIGH && SwitchState_2 == HIGH) {
    digitalWrite(RelayPin2, HIGH);
    toggleState_2 = 0;
    SwitchState_2 = LOW;
    my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_2);
    Serial.println("Switch-2 off");
  }
  if (digitalRead(SwitchPin3) == LOW && SwitchState_3 == LOW) {
    digitalWrite(RelayPin3, LOW);
    toggleState_3 = 1;
    SwitchState_3 = HIGH;
    my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_3);
    Serial.println("Switch-3 on");
  }
  if (digitalRead(SwitchPin3) == HIGH && SwitchState_3 == HIGH) {
    digitalWrite(RelayPin3, HIGH);
    toggleState_3 = 0;
    SwitchState_3 = LOW;
    my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_3);
    Serial.println("Switch-3 off");
  }
  if (digitalRead(SwitchPin4) == LOW && SwitchState_4 == LOW) {
    digitalWrite(RelayPin4, LOW);
    toggleState_4 = 1;
    SwitchState_4 = HIGH;
    my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_4);
    Serial.println("Switch-4 on");
  }
  if (digitalRead(SwitchPin4) == HIGH && SwitchState_4 == HIGH) {
    digitalWrite(RelayPin4, HIGH);
    toggleState_4 = 0;
    SwitchState_4 = LOW;
    my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_4);
    Serial.println("Switch-4 off");
  }
}

void setup()
{

  Serial.begin(115200);

  // Set the Relays GPIOs as output mode
  pinMode(RelayPin1, OUTPUT);
  pinMode(RelayPin2, OUTPUT);
  pinMode(RelayPin3, OUTPUT);
  pinMode(RelayPin4, OUTPUT);
  pinMode(wifiLed, OUTPUT);

  // Configure the input GPIOs
  pinMode(SwitchPin1, INPUT_PULLUP);
  pinMode(SwitchPin2, INPUT_PULLUP);
  pinMode(SwitchPin3, INPUT_PULLUP);
  pinMode(SwitchPin4, INPUT_PULLUP);
  pinMode(gpio_reset, INPUT);

  // Write to the GPIOs the default state on booting
  digitalWrite(RelayPin1, !toggleState_1);
  digitalWrite(RelayPin2, !toggleState_2);
  digitalWrite(RelayPin3, !toggleState_3);
  digitalWrite(RelayPin4, !toggleState_4);
  digitalWrite(wifiLed, LOW);
  dht.begin();    // Enabling DHT sensor

  Node my_node;
  my_node = RMaker.initNode(nodeName);

  //Standard switch device
  my_switch1.addCb(write_callback);
  my_switch2.addCb(write_callback);
  my_switch3.addCb(write_callback);
  my_switch4.addCb(write_callback);

  //Add switch device to the node
  my_node.addDevice(my_switch1);
  my_node.addDevice(my_switch2);
  my_node.addDevice(my_switch3);
  my_node.addDevice(my_switch4);
  my_node.addDevice(temperature);
  my_node.addDevice(humidity);
  my_node.addDevice(ldr);

  Timer.setInterval(2000);

  //This is optional
  RMaker.enableOTA(OTA_USING_PARAMS);
  //If you want to enable scheduling, set time zone for your region using setTimeZone().
  //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html
  // RMaker.setTimeZone("Asia/Shanghai");
  // Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone
  RMaker.enableTZService();
  RMaker.enableSchedule();

  //Service Name
  for (int i = 0; i < 17; i = i + 8) {
    espChipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
  }

  Serial.printf("\nChip ID:  %d Service Name: %s\n", espChipId, service_name);

  Serial.printf("\nStarting ESP-RainMaker\n");
  RMaker.start();

  WiFi.onEvent(sysProvEvent);
#if CONFIG_IDF_TARGET_ESP32
  WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
#else
  WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
#endif

  my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
  my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
  my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
  my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
}

void loop()
{
  // Read GPIO0 (external button to reset device
  if (digitalRead(gpio_reset) == LOW) { //Push button pressed
    Serial.printf("Reset Button Pressed!\n");
    // Key debounce handling
    delay(100);
    int startTime = millis();
    while (digitalRead(gpio_reset) == LOW) delay(50);
    int endTime = millis();

    if ((endTime - startTime) > 10000) {
      // If key pressed for more than 10secs, reset all
      Serial.printf("Reset to factory.\n");
      RMakerFactoryReset(2);
    } else if ((endTime - startTime) > 3000) {
      Serial.printf("Reset Wi-Fi.\n");
      // If key pressed for more than 3secs, but less than 10, reset Wi-Fi
      RMakerWiFiReset(2);
    }
  }
  delay(100);

  if (WiFi.status() != WL_CONNECTED)
  {
    //Serial.println("WiFi Not Connected");
    digitalWrite(wifiLed, false);
  }
  else
  {
    //Serial.println("WiFi Connected");
    digitalWrite(wifiLed, true);
    if (Timer.isReady()) {
      //Serial.println("Sending Sensor Data");
      sendSensor();
      Timer.reset();      // Reset a second timer
    }
  }
  manual_control();
}

ESP32 Board details here :

Are you exceeding program space/flash or RAM? By how much? Have you checked how much space the libraries use?

@chrisl I don't know how can I check it. I'll look into it.

When you compile a sketch in the Arduino IDE it will output the amount of used program memory and how much RAM is used by global variables. That gives you a good hint.

Where is all this text you mentioned? This tiny code should easily fit into the ESP's flash (if you're using F(...))... what flash size does your ESP have? Maybe you can get around it using a different partition scheme.

Just how large is the compiled program? Could you include the last lines of the compiler output in your question? The tip from @SimSon is also a good one. If you don't need a file system or OTA, you could select a partition scheme that maximizes available code space, like "Huge APP" or  one of the "No OTA" schemes.

esp32 toolchain uses string literals from flash automatically. the F macro does nothing

Maybe I've missed something, but the flash area is partitioned between usable app (roughly sketch code) space and usable filesystem space. I don't see any indication in your question that you're using a filesystem at all.
Keeping your current settings except for switching the partition setting to "Huge APP (3MB No OTA/1MB SPIFFS)" resulted in:
Sketch uses 1790473 bytes (56%) of program storage space. Maximum is 3145728 bytes.
Global variables use 53260 bytes (16%) of dynamic memory, leaving 274420 bytes for local variables. Maximum is 327680 bytes.

I'm not even sure "Huge APP" makes the most sense. Only that 3MB is larger than 1.2MB and larger than your current 1.8(ish)MB build apparently needs. It says "no-OTA" but you don't seem to be using that either. So, this seems like something you can do irrespective of whatever contributions you can trim from the text segment by tweaking your code.

Partition to Rainmaker I did, its working fine now

You are programming for an embedded processor with limited memory.  Both program space and random access memory (RAM).  Every letter you put in quotes takes up a byte of memory. If you are only over the limit by a little consider abbreviating your text.  For example consider changing strings like:

"Provisioning Started with name"

... to something along the lines of ...

"Prov name"

If by a lot then consider changing your code.  Many times you quote similar text. For example consider changing the following code:
// define the Device Names
char deviceName_1[] = "Switch1";
char deviceName_2[] = "Switch2";
char deviceName_3[] = "Switch3";
char deviceName_4[] = "Switch4";
...
//The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
static Switch my_switch1(deviceName_1, &RelayPin1);
static Switch my_switch2(deviceName_2, &RelayPin2);
static Switch my_switch3(deviceName_3, &RelayPin3);
static Switch my_switch4(deviceName_4, &RelayPin4);

... to something along the lines of ...
//The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
String stringOne = "Switch";
String stringTwo = "1"
static Switch my_switch1(stringOne + stringTwo, &RelayPin1);
stringTwo = "2"
static Switch my_switch2(stringOne + stringTwo, &RelayPin2);
stringTwo = "3"
static Switch my_switch3(stringOne + stringTwo, &RelayPin3);
stringTwo = "4"
static Switch my_switch4(stringOne + stringTwo, &RelayPin4);

... the point here is to avoid using up program and random access memory with repeated strings.

If any find a problem in the above code or have insight into a more efficient approach please post.  I'll be more than happy to edit the answer to make it better.

I'll implement these from now on.

You could use enums to replace all the char strings (which take a lot of memory space) into integers behind the scene.
enum deviceNames {Switch1, Switch2, Switch3, Switch4};
deviceNames deviceName; //define variable of type deviceNames

for comparison you can use:
if (deviceName == Switch1); //Switch1 equals 0 for the compiler, Stich2 equals 1 etc etc.

Frist however, you should have a look at the functions getDeviceName() and getParamName(). Could you post them? Would need to see if you can make these changes there aswell.
Since you are getting the variable device_name from there, again as a string. Enums would do no good without additional changes to the functions.
*Also I noticed you still didn't use Serial.print(F());
Read up on storing strings and variables into PROGMEM if you're interested.
*EDIT:
As user Juraj noted in the comments: "the esp32 toolchain uses string literals from flash automatically. the F macro does nothing".
Perhaps you can benefit form newlib nano formatting for printf? I'm not sure as I don't know what difference it makes on your esp32 version. You'll have to check out.

Note that F() is meant to save RAM (data section), not flash (text section).

Yes, as of yet we don't know which of those two memory spaces is exceeded.

esp32 toolchain uses string literals from flash automatically. the F macro does nothing

The title of the question says which of those two memory spaces is exceeded.

@Juraj Aha, that I didn't know. Thanks for noting that.


text:
SPI read while writing?
I'm working on a driver for an SPI device that returns some data (device status) while the command byte is still being written.  Is there a way to read this status data using standard Arduino APIs or do I need to bit-bang to access it?
Here's what the SPI signals look like:

The 6 bits in red are the ones I'm interested in reading.

For context, the device in question is a Microchip MCP3561 ADC (MCP3X6X series).  It has a bug (erratum 2) where the new-data-ready flag (/DR_STATUS) is not always set correctly.  Part of the work-around involves reading the status bits mentioned above.

The SPI.transfer() method is designed to send a byte through
the SPI port and, at the same time receive an incoming byte.
Usage pattern:
uint8_t byte_to_send = ...;
uint8_t received_byte = SPI.transfer(byte_to_send);

Turns out the bug was elsewhere in my code.  This works fine.  Thanks!


text:
Two Servo motors don't work as required (Arduino Mega 2560)
Can anyone help me with the following codes? I have attached sensors to detect either plastic or metal materials. If the sensor detected a metal, the first servo will rotate at least 90 degrees. If not, it will not rotate. If its a plastic material, the other servo will do the same. Kindly consider the following codes.
// Include Libraries
#include "Arduino.h"
#include "Button.h"
// Pin Definitions
#define REFLECTIVEIR_PIN_COLL  A1
#define REFLECTIVEIR_PIN_COLL_M  A3
// object initialization
Button ReflectiveIR(REFLECTIVEIR_PIN_COLL);
Button ReflectiveIR_M(REFLECTIVEIR_PIN_COLL_M);
// define vars for testing menu
const int timeout = 10000;       //define timeout of 10 sec
char menuOption = 0;
long time0;

#include <Servo.h>
#define redpin 2
#define bluepin 3
#define greenpin 4
#define redpin_M 5
#define bluepin_M 6
#define greenpin_M 7
int metalsensor = A0;
int metalsensor_M = A2;
int plasticsensor = A4;
//int anothersensor = A2;

Servo myservo;  // create servo object to control a servo
Servo myservo_M;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 165;    // variable to store the servo position
int pos_M = 158;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo_M.attach(10);  // attaches the servo on pin 9 to the servo object
  pinMode(redpin, OUTPUT);
  pinMode(bluepin, OUTPUT);
  pinMode(greenpin, OUTPUT);
  //metal sensor
  pinMode(redpin_M, OUTPUT);
  pinMode(bluepin_M, OUTPUT);
  pinMode(greenpin_M, OUTPUT);

  pinMode(metalsensor, INPUT_PULLUP);
  pinMode(metalsensor_M, INPUT_PULLUP);
  pinMode(plasticsensor, INPUT_PULLUP);
  //  pinMode(anothersensor, INPUT_PULLUP);
  Serial.begin(9600);
  analogWrite(redpin, 255);
  analogWrite(bluepin, 255);
  analogWrite(greenpin, 255);
  analogWrite(redpin_M, 255);
  analogWrite(bluepin_M, 255);
  analogWrite(greenpin_M, 255);
  //ReflectiveIR.init();
  //ReflectiveIR_M.init();
}

void loop() {

  int sensor_read_m = digitalRead(metalsensor);
  int sensor_read_mm = digitalRead(metalsensor_M);
  int sensor_read = digitalRead(plasticsensor);
  Serial.println("metal sensor");
  Serial.println(sensor_read_m);
  Serial.println(sensor_read_mm);
  Serial.println("plastic sensor");
  Serial.println(sensor_read);

  bool ReflectiveIR_Val = ReflectiveIR.read();
  bool ReflectiveIR_Val_M = ReflectiveIR_M.read();
  //Plastic bin
  if ((sensor_read == 0) && (sensor_read_m != 1)) {
    for (pos = 160; pos >= 90; pos -= 1) { // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(1);                       // waits 15ms for the servo to reach the position
    }
    analogWrite(redpin, 255);
    analogWrite(bluepin, 0);
    analogWrite(greenpin, 255);
    delay(2500);
    for (pos = 90; pos <= 160; pos += 1) { // goes from 180 degrees to 0 degrees
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(1);                       // waits 15ms for the servo to reach the position

    }
    analogWrite(redpin, 0);
    analogWrite(bluepin, 0);
    analogWrite(greenpin, 0);

  }

  else if (ReflectiveIR_Val == 1) { //checking the volume of the trash
    analogWrite(redpin, 0);
    analogWrite(bluepin, 255);
    analogWrite(greenpin, 255);

  }

  else {
    // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    // waits 15ms for the servo to reach the position

    analogWrite(redpin, 255);
    analogWrite(bluepin, 255);
    analogWrite(greenpin, 255);

  }

  //metal sensor

  if (sensor_read_mm == 1) {
    for (pos_M = 160; pos_M >= 90; pos_M -= 1) { // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      myservo_M.write(pos_M);              // tell servo to go to position in variable 'pos'
      delay(1);                       // waits 15ms for the servo to reach the position
    }
    analogWrite(redpin_M, 255);
    analogWrite(bluepin_M, 0);
    analogWrite(greenpin_M, 255);
    delay(2500);
    for (pos_M = 90; pos_M <= 160; pos_M += 1) { // goes from 180 degrees to 0 degrees
      myservo_M.write(pos_M);              // tell servo to go to position in variable 'pos'
      delay(1);                       // waits 15ms for the servo to reach the position

    }
    analogWrite(redpin_M, 0);
    analogWrite(bluepin_M, 0);
    analogWrite(greenpin_M, 0);

  }

  else if (ReflectiveIR_Val_M == 1) {
    analogWrite(redpin_M, 0);
    analogWrite(bluepin_M, 255);
    analogWrite(greenpin_M, 255);

  }

  else {
    // goes from 180 degrees to 0 degrees
    myservo_M.write(pos_M);              // tell servo to go to position in variable 'pos'
    // waits 15ms for the servo to reach the position

    analogWrite(redpin_M, 255);
    analogWrite(bluepin_M, 255);
    analogWrite(greenpin_M, 255);

  }

}

Thank you for the help.

The servo don't respond to any type of material (plastic or metal). Can you help me solve this? Thank you in advance.

You're absolutely right. I can't figure out how it would work using the sensors that will make the servo response. Can you help me find the correct codes to make it work? Thank you.

your code right now is read sensor ... if metal then flash LEDs and move servo   .... do instead at beginning of loop() read sensor ... if metal then set flag  (metal=true) .... further down in loop() if metal then move servo .... if metal then flash leds   ..... that way everything is separated and you can easily print debugging info about the state of flags

Thanks. I would try to change the codes according to what you suggest. I'll get back later for updates.

start with the detect code .... forget about servos and leds .... well maybe use the led to indicate detection of material and another led to indicate type of material

I really can't figure out which of the codes I will change or modify. It would be greatly appreciated If you don't mind changing it for me. I am new to this. Some codes were taken from online sources. I understand what you mean but I find it hard for me to figure out which specifically I will change. Thanks for the help.

start by commenting out all code in loop() except the first 8 lines .... see what values get printed for each of the materials that you want to detect .... slow down the loop() by including delay 200; before end of loop()

The detection creates loops continuously even nothing is detected. The servo for metal sensor rotates back and forth. I really don't know how to change the codes to make it right. Could you please fix it for me? I am new to Arduino coding.

you are the only one who can figure out if the sensors are working and what data values the sensors produce ... it is not possible to write the code to do something without knowing what the inputs are

Thanks for the help. I really appreciate it. But, anyway, I will try to find it out how to make it work the way it is suppose to.

like i said before, get the detection code working first ..... if you cannot differentiate between metal and plastic, then it is pointless to write code for the servos .... good luck with your project


text:
First time working with arduino, need help adapting project from UNO to NANO
This is my first time working with an arduino and I'm having some issues when trying to copy a program I found online on my Nano.
Basically, my project consists in a pulse sensor that sends the pulse information to the arduino and then to the hc-05 Bluetooth module so my phone can receive this information in real-time.
On my nano: D2 receives the output of the sensor, D8 and D9 are connected to pins RX/RT on HC05 and D13 has a LED connected to it.
Now here's the thing, I really don't know much about this and the code I found uses different pins from the ones I'm using.
The LED keeps blinking and isn't synchronized with the sensor output, when the led blinks I receive a response in the Bluetooth serial app but I would like to synchronize the heart sensor with the led so than I can receive the pulses on my phone. I've been trying to solve this but I still can't find a solution.
Full code can be found at
https://www.instructables.com/id/Pulse-Sensor-With-Bluetooth-and-Arduino/
Here's part of my code
//bluetooth
#include <SoftwareSerial.h>// import the serial library

SoftwareSerial Genotronex(8, 9); // RX, TX
int ledpin=13; // led on D13 will show blink on / off
int BluetoothData; // the data given from Computer

//  Variables
int pulsePin = 2;                 // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13;                // pin to blink led at each beat
int fadePin = 5;                  // pin to do fancy classy fading blink at each beat
int fadeRate = 0;                 // used to fade LED on with PWM on fadePin

// Volatile Variables, used in the interrupt service routine!
volatile int BPM;                   // int that holds raw Analog in 0. updated every 2mS
volatile int Signal;                // holds the incoming raw data
volatile int IBI = 600;             // int that holds the time interval between beats! Must be seeded!
volatile boolean Pulse = false;     // "True" when User's live heartbeat is detected. "False" when not a "live beat".
volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

// Regards Serial OutPut  -- Set This Up to your needs
static boolean serialVisual = true;   // Set to 'false' by Default.  Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse

void setup(){
  pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!
  pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!
  Serial.begin(115200);             // we agree to talk fast!
  interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS
   // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE,
   // AND APPLY THAT VOLTAGE TO THE A-REF PIN
//   analogReference(EXTERNAL);
Genotronex.begin(9600);
  Genotronex.println("Bluetooth On please press 1 or 0 blink LED ..");
  pinMode(ledpin,OUTPUT);
}

//  Where the Magic Happens
void loop(){

    serialOutput() ;

  if (QS == true){     //  A Heartbeat Was Found
                       // BPM and IBI have been Determined
                       // Quantified Self "QS" true when arduino finds a heartbeat
        digitalWrite(blinkPin,HIGH);     // Blink LED, we got a beat.
        fadeRate = 255;         // Makes the LED Fade Effect Happen
                                // Set 'fadeRate' Variable to 255 to fade LED with pulse
        serialOutputWhenBeatHappens();   // A Beat Happened, Output that to serial.
        QS = false;                      // reset the Quantified Self flag for next time
       }
      else {

      digitalWrite(blinkPin,LOW);            // There is not beat, turn off pin 13 LED
      }

   ledFadeToBeat();                      // Makes the LED Fade Effect Happen
  if (Genotronex.available()){
BluetoothData=Genotronex.read();
   if(BluetoothData=='1'){   // if number 1 pressed ....
   digitalWrite(ledpin,1);
   Genotronex.println("LED  On D12 ON ! ");
   }
  if (BluetoothData=='0'){// if number 0 pressed ....
  digitalWrite(ledpin,0);
   Genotronex.println("LED  On D12 Off ! ");
  }
}
  delay(20);                             //  take a break
}```

why do you believe that synchonizing an LED with the sensor will actually send the pulses to the phone?

Because everytime the led blinks I receive it as a pulse on the phone

to port a sketch from Uno to Nano do: nothing

@Ricardo, the pulse transmit action causes the LED to flash, not the other way around .... what you want to do is for the pulse to be transmitted every time the sensor gets triggered ... the LED is irrelevant

I don't understand your problem. What should the LED do in relation to what? Also: Can you post the complete code. There are missing some function implementations, that might be important for whatever you want.

@chrisl the led on D13 should blink everytime the arduino receives a pulse from D2.  The complete code is in the link, I don't know how to post multiple tabs here. Basically I'm having trouble with changing the pins in the code to use it on my nano, everything should remain the same.

@jsotola Yes, you're right

@juraj all I need to do is change the pins from the original program so it works with my arduino nano, I know that's super easy, but I'm stuck

The original code uses PIN A0 to receive the output from the sensor, I'm using D2. I replaced the 0 for a 2 in the variable pulsePin, but still the arduino wont receive the pulse information, in my phone I get random pulses but they're not coming from the sensor.

you can't use pin 2. the sketch uses analogRead which works only on A pins. if you changed it to 2, then it is A2. why did you change the pin?

@juraj I changed it to pin A0 and it worked fine!! I still would like to know how to change it from A0 to D2. I really have no idea and already switched analogRead to digitalRead but it didn't work, also, thank you :)

for analogRead the pin have to be analog. I don't know why analogRead is used here

First: There is no need to change pin assingments, when changing from Uno to Nano. They use the same microcontroller and have the same pins.
You have set pulsePin to 2, which corresponds to pin D2. But the pulse sensor gives you an analog signal. D2 is not capable of measuring analog voltages, it can only measure digital voltages. Meaning you need to use one of the analog pins, A0 to A7, so use one of these pins in the declaration of pulsePin.
The reason for this is, that the microcontroller uses an extra peripheral device included in it for measuring analog voltages: the ADC (Analog to Digital Converter). It can only be connected to a limited number of pins (internally via a multiplexer). That also means, that you can only measure the analog voltage at one pin at a time.


text:
how to fix mirrored text on 3.2 inch IPS TFT LCD Display ILI9481 480X320 36 Pins for Arduino Mega2560
i am working on a project on my arduino mega2560. I want to show reading of the sensors on the TFT display, the problem is the text displayed on the screen is mirrored. Since i am very new to arduino i don't know how to fix the problem. I have check a few videos on youtube but nothing helped. I am using the example from the UTFT library arduino (AVR) => UTFT_DEMO_480x320

Can you please provide a link to the library you used (for example to the corresponding github page)? I looked at the UTFT library, that I can find in my library manager, but that does not have any 480x320 demo, so I suspect, that you are using a different library. Also please show your code

http://www.rinkydinkelectronics.com/library.php?id=51

The orientation of the display is controlled by the "Set Address Mode" command (0x36) at line 42 of the ILI9481 driver.
The current value is 0x0A which is 00001010 in binary.  According to the datasheet (8.2.25) bit 6 is "Column Address Order", and that is set to "Left to Right" currently.
Turning that bit on should reverse the column order for the display.
So changing those two lines of code to:
LCD_Write_COM(0x36);
LCD_Write_DATA(0x4A);

should have the desired effect.

i have tried this but still no luck its the same

There should be a change, even if it's a wrong change. So either the IDE caching the compiled code and not realizing that there's a change it needs to recompile for (probably, given the nature of that library), or it's not using the ILI9491 driver.

i have made changes as you suggested, also restarted the IDE i dont know why it isn't detecting any change, is there anything that i am missing?

Are you sure you changed it in the right file? There's lots of files all named the same in that library.

i have modified this file "\Arduino\libraries\UTFT\tft_drivers\ili9481\initlcd"

At times like this I like to add #error foo somewhere in the file in question and see if compilation then fails with a message of error: foo.

i have checked and its gives error while compiling which means it's compiling the latest changes, but the display is still mirrored, maybe there is something else that needs changing. your help will be highly appreciated, and thanks for what you have done until now.

There are other values that you can try. For example 0x4A, which changes the column address order.

0x4A works, now the text is not mirrored Thanks a lot. Can you please update your answer above and change 0x08 to 0x4A so that i can mark it answered.

Had this same problem with everything mirrored/backward.  Not sure you're still trying, but for any others with this issue, here's how I addressed it..
If using the UTFT library from RinkyDink electronics, open up their initlcd.h file.  In the section for Memory Access Control (lines 85-86 in version I have), change the write to:
LCD_Write_DATA(0x08);
Bit 0 controls vertical flip, Bit 1 controls horizontal flip.

I had the problem of a mirrored display. none of the solutions above worked. I found that the Line in the source code had the wrong driver defined.
change the line in the source code (file name "UTFT_Demo_480x320"
line# 32 to this: UTFT myGLCD(CTE40, 38, 39, 40, 41);
The new part is 'CTE40'. This works with the ILI9486.
You can find all of the different chip numbers in the file "UTFT.h'


text:
Scroll Left to Right on MAX7219 Display
For scrolling from left to right (Arabic letters) I need a function to print words/sentences on the MAX7219 display. [By setpixel(x, y) function]
I did a lot of searching and my efforts failed. I found the following example but I couldn't change it. By default this example scrolls from right to left. (I need scroll from left to right.)
#include <LEDMatrixDriver.hpp>
const uint8_t LEDMATRIX_CS_PIN = 9;

// Number of 8x8 segments you are connecting
const int LEDMATRIX_SEGMENTS = 4;
const int LEDMATRIX_WIDTH    = LEDMATRIX_SEGMENTS * 8;

// The LEDMatrixDriver class instance
LEDMatrixDriver lmd(LEDMATRIX_SEGMENTS, LEDMATRIX_CS_PIN);

// Marquee text
char text[] = "** LED MATRIX DEMO! ** (1234567890) ++ \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" ++ <$%/=?'.@,> --";

// Marquee speed (lower nubmers = faster)
const int ANIM_DELAY = 30;

void setup() {
  // init the display
  lmd.setEnabled(true);
  lmd.setIntensity(2);   // 0 = low, 10 = high
}

int x=0, y=0;   // start top left

// This is the font definition. You can use http://gurgleapps.com/tools/matrix to create your own font or sprites.
// If you like the font feel free to use it. I created it myself and donate it to the public domain.
byte font[95][8] = { {0,0,0,0,0,0,0,0}, // SPACE
                     {0x10,0x18,0x18,0x18,0x18,0x00,0x18,0x18}, // EXCL
                     {0x28,0x28,0x08,0x00,0x00,0x00,0x00,0x00}, // QUOT
                     {0x00,0x0a,0x7f,0x14,0x28,0xfe,0x50,0x00}, // #
                     {0x10,0x38,0x54,0x70,0x1c,0x54,0x38,0x10}, // $
                     {0x00,0x60,0x66,0x08,0x10,0x66,0x06,0x00}, // %
                     {0,0,0,0,0,0,0,0}, // &
                     {0x00,0x10,0x18,0x18,0x08,0x00,0x00,0x00}, // '
                     {0x02,0x04,0x08,0x08,0x08,0x08,0x08,0x04}, // (
                     {0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20}, // )
                     {0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10}, // *
                     {0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08}, // +
                     {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08}, // COMMA
                     {0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00}, // -
                     {0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06}, // DOT
                     {0x00,0x04,0x04,0x08,0x10,0x20,0x40,0x40}, // /
                     {0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x38}, // 0
                     {0x04,0x0c,0x14,0x24,0x04,0x04,0x04,0x04}, // 1
                     {0x00,0x30,0x48,0x04,0x04,0x38,0x40,0x7c}, // 2
                     {0x00,0x38,0x04,0x04,0x18,0x04,0x44,0x38}, // 3
                     {0x00,0x04,0x0c,0x14,0x24,0x7e,0x04,0x04}, // 4
                     {0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x38}, // 5
                     {0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38}, // 6
                     {0x00,0x7c,0x04,0x04,0x08,0x08,0x10,0x10}, // 7
                     {0x00,0x3c,0x44,0x44,0x38,0x44,0x44,0x78}, // 8
                     {0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x78}, // 9
                     {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
                     {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08}, // ;
                     {0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10}, // <
                     {0x00,0x00,0x7e,0x00,0x00,0xfc,0x00,0x00}, // =
                     {0x00,0x08,0x04,0x02,0x01,0x02,0x04,0x08}, // >
                     {0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10}, // ?
                     {0x00,0x30,0x48,0xba,0xba,0x84,0x78,0x00}, // @
                     {0x00,0x1c,0x22,0x42,0x42,0x7e,0x42,0x42}, // A
                     {0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x7c}, // B
                     {0x00,0x3c,0x44,0x40,0x40,0x40,0x44,0x7c}, // C
                     {0x00,0x7c,0x42,0x42,0x42,0x42,0x44,0x78}, // D
                     {0x00,0x78,0x40,0x40,0x70,0x40,0x40,0x7c}, // E
                     {0x00,0x7c,0x40,0x40,0x78,0x40,0x40,0x40}, // F
                     {0x00,0x3c,0x40,0x40,0x5c,0x44,0x44,0x78}, // G
                     {0x00,0x42,0x42,0x42,0x7e,0x42,0x42,0x42}, // H
                     {0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x7e}, // I
                     {0x00,0x7e,0x02,0x02,0x02,0x02,0x04,0x38}, // J
                     {0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44}, // K
                     {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c}, // L
                     {0x00,0x82,0xc6,0xaa,0x92,0x82,0x82,0x82}, // M
                     {0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42}, // N
                     {0x00,0x3c,0x42,0x42,0x42,0x42,0x44,0x38}, // O
                     {0x00,0x78,0x44,0x44,0x48,0x70,0x40,0x40}, // P
                     {0x00,0x3c,0x42,0x42,0x52,0x4a,0x44,0x3a}, // Q
                     {0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44}, // R
                     {0x00,0x38,0x40,0x40,0x38,0x04,0x04,0x78}, // S
                     {0x00,0x7e,0x90,0x10,0x10,0x10,0x10,0x10}, // T
                     {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e}, // U
                     {0x00,0x42,0x42,0x42,0x42,0x44,0x28,0x10}, // V
                     {0x80,0x82,0x82,0x92,0x92,0x92,0x94,0x78}, // W
                     {0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42}, // X
                     {0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10}, // Y
                     {0x00,0x7c,0x04,0x08,0x7c,0x20,0x40,0xfe}, // Z
                      // (the font does not contain any lower case letters. you can add your own.)
                  };    // {}, //

void loop()
{
    // Draw the text to the current position
    int len = strlen(text);
    drawString(text, len, x, 0);
    // In case you wonder why we don't have to call lmd.clear() in every loop: The font has a opaque (black) background...

    // Toggle display of the new framebuffer
    lmd.display();

    // Wait to let the human read the display
    delay(ANIM_DELAY);

    // Advance to next coordinate
    if( --x < len * -8 ) {
        x = LEDMATRIX_WIDTH;
    }
}

/**
 * This function draws a string of the given length to the given position.
 */
void drawString(char* text, int len, int x, int y )
{
  for( int idx = 0; idx < len; idx ++ )
  {
    int c = text[idx] - 32;

    // stop if char is outside visible area
    if( x + idx * 8  > LEDMATRIX_WIDTH )
      return;

    // only draw if char is visible
    if( 8 + x + idx * 8 > 0 )
      drawSprite( font[c], x + idx * 8, y, 8, 8 );
  }
}

/**
 * This draws a sprite to the given position using the width and height supplied (usually 8x8)
 */
void drawSprite( byte* sprite, int x, int y, int width, int height )
{
  // The mask is used to get the column bit from the sprite row
  byte mask = B10000000;

  for( int iy = 0; iy < height; iy++ )
  {
    for( int ix = 0; ix < width; ix++ )
    {
      lmd.setPixel(x + ix, y + iy, (bool)(sprite[iy] & mask ));

      // shift the mask by one pixel to the right
      mask = mask >> 1;
    }

    // reset column mask
    mask = B10000000;
  }

What exactly is your problem? The scrolling from left to right, the printing from right to left or printing arabic letters?

@chrisl Change example above and scroll from left to right.

To scroll in the opposite direction, change this if statement:
if( --x < len * -8 ) {
    x = LEDMATRIX_WIDTH;
}

to this:
if( ++x > LEDMATRIX_WIDTH+len*8 ){
    x = 0;
}

x (the start position of the text) is now incremented instead of decremented, until the whole text (consisting of len*8 pixels in x direction) is out of the display, where it then gets reset to zero.
This assumes, that the printing of the arabic letters is done from right to left (You might want to implement this, when working with arabic text). The function in the example prints always from left to right, so you need to use this code:
if( ++x > LEDMATRIX_WIDTH ){
    x = -len*8;
}

since in this case the text will not be visible in the moment, that the position is over the matrix width.

Thanks @chrisl, I modified the code as you said (if statement), But no text is displayed, Please see the video, In the first phase I want to scroll the same English text variable from left to right.

Ok, I corrected an error in the last code bit, that you need to use. Of course the text position needs to be reset to the corresponding negative value, so that the right end of the text will scroll into the display. Sorry for that error.

Thanks @chrisl, Everything is okay.

You can use the MD Parola library which has a setting to change the direction.
PA_SCROLL_RIGHT or PA_SCROLL_LEFT.

Thanks @tavis , I'll test. Of course, I need a library that has setpixel(x, y) function.


text:
Arduino nano digital I/O overload
Is it possible to kill arduino nano with overload?
I wanted to drive a relay with arduino, and I used a BC547 to switch 12V for the relay.
But in the relay there was a diode, which sorted out the circuit (thats why I drawed in the wrong orientation)
I know it was a mistake to not use current limiting resistor on Base of the transistor.
Is it possible that this shorted circuit made too much current on the transistor base which killed my arduino?
I made this circuit:

Shouldn't the diode across the relay be the other way round? Like this, it shortcuts the relay, but what it should do, is shortcut the discharge current of the relay.

the backwards diode bypassed the relay ... when the transistor turned on, too much current flowed through the transistor and possibly damaged the transistor, the damaged transistor may have allowed the base voltage to rise to near 12 V

As mentioned, the frewheeling diode at the relay has wrong orientarion. You also must have a base resistor to limit the current the gpio has to source (you control a BJT just like an led). Some hundred ohm should work for the bc547

Short answer is probably.  There is a voltage drop from base to emitter that is about .7 volts.  But something still has to contend with the rest of the energy.  You might try a different Arduino digital output on the chance that the balance of the processor is working as expected.
I say probably because several things might have happened if the transistor actually turned on.  For instance the forward biased (backwards) diode may have allowed so much current to flow through the relay and transistor that the transistor failed first.  Or, if the power supply had a low current rating, it may not have had the capacity to burn anything out.  As you can see, it is difficult to say what exactly happened with out testing each part individually.

The transistor turned on, and something is blown out, i think the transistor but I'am not sure.
But the arduino is not working anymore, i can't write code on it, and the code on it doesn't do anything. When i power it, the power LED turns on. And I also can't see any damage on the arduino.

Disconnect everything from the Arduino then try to program it.  Burned out parts can fail open or shorted.  If it sill does not program and the Atmel processor is in a socket consider buying a new pre-programmed-with-the-Arduino-boot-loader processor.  Or a normal Atmel processor and program the Arduino boot loader your self.  Finally, consider starting over with a new Arduino.

I tried almos everything, there is no way to change the Atmel IC. The only way would be to buy a new one, but its sadly more than a week in shipping. I just wanted to know where i made a mistake which lead to damage the arduino. Thnak You for your help!

I applaud you wanting to learn. But perhaps for the first go you might consider buying a pre-made Arduino compatible relay board with built in drivers and even an optical isolator for added protection.  Also, when just starting out, there is no shame in copying an existing working project like this one.


text:
Interrupting a servo sweep with a force sensor
this is my first time dealing with arduinos and I have a school assignment. I have a servo and a force sensor. When "1" (a character, not an integer) is typed in the serial monitor, the servo needs to rotate 180 degrees but can be interrupted when the force sensor sends a value over let's say 300. And when "0" is typed in, the servo goes back to its initial position.
I have been trying really hard figuring this out.
I basically need to exit a loop when the analog value exceeds 300.
here's my code:
#include <Servo.h>
Servo myservo;

int initpos; //initial position of the servo before the sweep (this doesn't change)
int angle; //used to store the servo angle value (this changes)
char code; //the value entered in the serial monitor
int force; //value of the analog force sensor

void setup()
{
  initpos = 10;
  Serial.begin(9600);
  myservo.attach(4);

  myservo.write(170); // makes the servo sweep(absolutelly useless for my project but I left it there)
  delay(500);         //
  myservo.write(10);  //
  delay(500);         //

  code = Serial.read();

}

void loop()
{

  if(Serial.available())
  {

    angle = initpos;
    force = analogRead(A1);
    Serial.println(force);

    for(angle = 0; angle < 180; angle += 1)
    {
      if (code == "1" and force <= 300)
      {
        angle += 1;
        Serial.print(code);
        myservo.write(angle);
      }

      else if(code == "0")
      {
        myservo.write(initpos);
      }
    }

  }
}

any help is deeply appreciated and if there is already a topic on this please redirect me to it

ask yourself this when is code in  setup() executed?   and  when is code in  loop() executed?

I've written this code without access to a compiler,
so there might be errors. Use it as an idea how to solve the quest. Hopefully the comments are helpful. Don't hesitate to ask if you do not understand or correct me if you see an error.
#include <Servo.h>

Servo myservo;

// end positions of the servo
// declared as constant values
const int minPos = 10;
const int maxPos = 180;

int servoAngle;

int force;
char code;

void setup()
{
  Serial.begin(9600);

  myservo.attach(4);
  // move the servo to minPos
  // or whatever you want/need
  servoAngle = minPos;
  myservo.write( servoAngle );

  // PPK: keep code as simple as possible -> sweep removed

  // PPK: removed - this makes no sense here
  // code = Serial.read();
}

void loop()
{
  // PPK: here you check if data is available (I added "> 0")
  if( Serial.available() > 0 )
  {
    // PPK: but you did not read the data
    // Let's do it
    char newCode = Serial.read();
    If ( newCode == '0' || newCode == '1' )
    {
      // only "0" and "1" are valid codes
      code = newCode;
    }
  }

  if ( code == '0' && servoAngle > minPos )
  {
    servoAngle--;
    myservo.write( servoAngle );
  }
  else if ( code == '1' && servoAngle < maxPos )
  {
    force = analogRead( A1 );
    Serial.println( force );
    if ( force > 300 )
    {
      servoAngle--;

      // PPK: the next line is only necessary if you want the
      // servo to go towards the min position
      // if a force > 300 is detected
      // remove the line if you wish to
      // hold the servo at the position where
      // the force exceeds 300
      code = '0':
    }
    else
    {
      servoAngle++;
    }
    myservo.write( servoAngle );
  }
  // a little delay to slow down the servo
  // remove it if you want
  delay( 10 );
}

EDIT
If you intend to stop the servo if force > 300, you can add a flag that indicates the exceptional state.
#include <Servo.h>

Servo myservo;

const int minPos = 10;
const int maxPos = 180;

int servoAngle;

int force;
char code;
int flagServoStopped = 0;

void setup()
{
  Serial.begin(9600);

  myservo.attach(4);
  servoAngle = minPos;
  myservo.write( servoAngle );
}

void loop()
{
  if( Serial.available() > 0 )
  {
    char newCode = Serial.read();
    If ( newCode == '0' || newCode == '1' )
    {
      code = newCode;
    }
  }

  if ( flagServoStopped == 1 && code == '1' )
  {
    // The servo is frozen as long as the stop flag is set and
    // you have not entered a '0'.
    // leave the loop
    return;
  }

  // in case `code = '0'`, reset the flag if it is set.
  flagServoStopped = 0;

  if ( code == '0' && servoAngle > minPos )
  {
    servoAngle--;
    myservo.write( servoAngle );
  }
  else if ( code == '1' && servoAngle < maxPos )
  {
    force = analogRead( A1 );
    Serial.println( force );
    if ( force > 300 )
    {
      flagServoStopped = 1;
    }
    else
    {
      servoAngle++;
      myservo.write( servoAngle );
    }
  }
  delay( 10 );
}

Hi thanks for your help this is great! (idk if you saw my previous comment it was missleading). Unfortunately the servo is expected to stop when force > 300 and wait for 0

@Kiz0 I've changed the code according to your last comment.

Thank you for your help! This works perfectly and has saved me hours in my project! :)


text:
Get a specific item from comma separated text
I use bluetooth (works like serial monitor).
Let me say i send a text to my hc-05 (same as sending to serial monitor)
My current code is displaying text from serial monitor/HC-05 TO LCD
#include <LiquidCrystal.h>

LiquidCrystal lcd(4, 6, 10, 11, 12, 13);
String readString;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  while(Serial.available()){
    delay(50);
    char c=Serial.read();
    readString+=c;
  }
  if(readString.length()>0){
    Serial.println(readString);
      lcd.clear();
      lcd.print(readString);
    readString="";
  }
}

from serial monitor i type `a,b,c,d`

now my goal is to just get the a and display in lcd

or

in other words i want to get the value of a b c d in the text that is CSV to list or array and get value for index 1,2,3,4

OR

split string by delimiter

so how can i do it
details-ARUINO UNO

i searched in stack exchange Arduino but i dint get answer so i posted but when i searched in stack over flow i got link this is my final code
String part01;
String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  String part01 = getValue("523;524;525",';',1);
  Serial.println(part01);

}

Use the strtok function.
From Geeks for geeks (https://www.geeksforgeeks.org/strtok-strtok_r-functions-c-examples/):
arguments:

str: The string which is to be split
delim: The character on the basis of which the split will be done Return value

The function performs one split and returns a pointer to the token split up. A null pointer is returned if the string cannot be split.

Note that to use strtok() you would first have to migrate away from using String, which is a good thing in any case.

but the example is for c++ can you provide the example for Arduino

@hifitech Even though the Arduino/C++ string can be used, it's not a good idea because of the very low SRAM the Arduino Uno has. I assume with a default function and plenty of examples to be found on internet of using strtok it would not be a big problem to find a solution.


text:
pH code of Arduino SEN0169 refuses to output
Good day everyone!
I'm making my research project a hydroponics sensor that collects air and water temperature, humidity, conductivity, and pH, then sends it through a sim900a GSM module. However, when testing it out, the pH part of the code does not work. When I removed the part of the code that collects pH, the device worked as intended. I got the code from the manufacturer's website, but I'm not sure what to change to make it work. Thank you very much!
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <GravityTDS.h>

#define ONE_WIRE_BUS 5
#define DHTPIN 7
#define DHTTYPE DHT11
#define TdsSensorPin A1

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial mySerial(9, 10);
GravityTDS gravityTds;

#define SensorPin A0            //pH meter Analog output to Arduino Analog Input 0
#define Offset 0.00            //deviation compensate
#define LED 13
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth  40    //times of collection
int pHArray[ArrayLenth];   //Store the average value of the sensor feedback
int pHArrayIndex=0;

char msg;
char call;

void setup()
{
  mySerial.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  Serial.println("GSM SIM900A BEGIN");
  Serial.println("Enter character for control option:");
  Serial.println("h : to disconnect a call");
  Serial.println("i : to receive a call");
  Serial.println("s : to send information");
  Serial.println("c : to make a call");
  Serial.println("e : to redial");
  Serial.println();
  delay(100);

  dht.begin();

  sensors.begin();

  gravityTds.setPin(A1);
  gravityTds.setAref(5.0);
  gravityTds.setAdcRange(1024);
  gravityTds.begin();

  pinMode(LED,OUTPUT);
}

void loop()
{

  if (Serial.available()>0)
   switch(Serial.read())
  {
    case 's':
      SendMessage();
      break;
    case 'c':
      MakeCall();
      break;
    case 'h':
      HangupCall();
      break;
    case 'e':
      RedialCall();
      break;
    case 'i':
      ReceiveCall();
      break;
  }
 if (mySerial.available()>0)
 Serial.write(mySerial.read());
}

void SendMessage()
{

  int h = dht.readHumidity();
  float t = dht.readTemperature();
  float tdsValue = 0;
  float temperature = t;
  gravityTds.setTemperature(temperature);
  gravityTds.update();
  tdsValue = gravityTds.getTdsValue();

  sensors.requestTemperatures();

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+639494145111\"\r"); // Replace x with mobile number
  mySerial.print(h);// The SMS text you want to send
  mySerial.print("% humidity, ");
  mySerial.print(t);
  mySerial.print(" degrees Celsius air temperature, ");
  mySerial.print(sensors.getTempCByIndex(0));
  mySerial.print(" degrees Celsius water temperature, ");
  mySerial.print(tdsValue,0);
  mySerial.println(" ppm, ");

  static unsigned long samplingTime = millis();
  static unsigned long printTime = millis();
  static float pHValue,voltage;
  if(millis()-samplingTime > samplingInterval)
  {
      pHArray[pHArrayIndex++]=analogRead(SensorPin);
      if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
      voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
      pHValue = 3.5*voltage+Offset;
      samplingTime=millis();
  }
  if(millis() - printTime > printInterval)   //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
  {
    mySerial.print(pHValue,2);
    mySerial.print(" pH value");
        digitalWrite(LED,digitalRead(LED)^1);
        printTime=millis();
  }
}
double avergearray(int* arr, int number){
  int i;
  int max,min;
  double avg;
  long amount=0;
  if(number<=0){
    Serial.println("Error number for the array to avraging!/n");
    return 0;
  }
  if(number<5){   //less than 5, calculated directly statistics
    for(i=0;i<number;i++){
      amount+=arr[i];
    }
    avg = amount/number;
    return avg;
  }else{
    if(arr[0]<arr[1]){
      min = arr[0];max=arr[1];
    }
    else{
      min=arr[1];max=arr[0];
    }
    for(i=2;i<number;i++){
      if(arr[i]<min){
        amount+=min;        //arr<min
        min=arr[i];
      }else {
        if(arr[i]>max){
          amount+=max;    //arr>max
          max=arr[i];
        }else{
          amount+=arr[i]; //min<=arr<=max
        }
      }//if
    }//for
    avg = (double)amount/(number-2);
  }//if
  return avg;
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}

void ReceiveMessage()
{
  mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to recieve a live SMS
  delay(1000);
  if (mySerial.available()>0)
  {
    msg=mySerial.read();
    Serial.print(msg);
  }
}

void MakeCall()
{
  mySerial.println("ATD+639494145111;"); // ATDxxxxxxxxxx; -- watch out here for semicolon at the end!!
  Serial.println("Calling  "); // print response over serial port
  delay(1000);
}

void HangupCall()
{
  mySerial.println("ATH");
  Serial.println("Hangup Call");
  delay(1000);
}

void ReceiveCall()
{
  mySerial.println("ATA");
  delay(1000);
  {
    call=mySerial.read();
    Serial.print(call);
  }
}

void RedialCall()
{
  mySerial.println("ATDL");
  Serial.println("Redialing");
  delay(1000);
}

start by running only the pH code ... remove everything else ... if the pH code does not run on its own, then it won't run as a part of a larger program either

The pH program works on its own, so it's only when I incorporate it like this that the pH value doesn't output

how do you know that the pH part of the program does not work? ... you have no debugging code that prints information to Serial

I used just the pH code in another sketch and it outputs the pH there.

that means nothing really ... it could just as easily be the GSM code ... you don't know if that part of code even runs


text:
Delay function executes too quickly
I'm making a hydroponics system that collects data and sends it to the user through a SIM module. The problem is that while I want it to happen only once every 15 minutes and for the pump to operate for 30 seconds only, yet the device seems to do everything 10 times as quickly, if not even faster. Is there any way to fix this without multiplying everything by 10?
#include <SoftwareSerial.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <GravityTDS.h>
#include <Servo.h>

#define ONE_WIRE_BUS 5
#define DHTPIN 7
#define DHTTYPE DHT11
#define TdsSensorPin A1
#define PUMPPIN 11

SoftwareSerial mySerial(9, 10);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);
GravityTDS gravityTds;
Servo myservo;

char msg;
char call;

void setup()
{

  dht.begin();

  sensors.begin();

  gravityTds.setPin(A1);
  gravityTds.setAref(5.0);
  gravityTds.setAdcRange(1024);
  gravityTds.begin();

  myservo.attach(PUMPPIN);
}

void loop()
{
  const unsigned long SECOND = 1000;
  const unsigned long MINUTE = 60*SECOND;
  const unsigned long HOUR = 60*MINUTE;

  delay(30*SECOND);
  int h = dht.readHumidity();
  float t = dht.readTemperature();
  float tdsValue = 0;
  float temperature = t;
  gravityTds.setTemperature(temperature);
  gravityTds.update();
  tdsValue = gravityTds.getTdsValue();

  sensors.requestTemperatures();

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+************\"\r"); // Replace x with mobile number
  mySerial.print(h);// The SMS text you want to send
  mySerial.print("% humidity, ");
  mySerial.print(t);
  mySerial.print(" degrees Celsius air temperature, ");
  mySerial.print(sensors.getTempCByIndex(0));
  mySerial.print(" degrees Celsius water temperature, ");
  mySerial.print(tdsValue,0);
  mySerial.print(" ppm");

  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  myservo.write(0);   //Clockwise maximum speed rotation
    delay(30*SECOND);
  myservo.write(90);
  delay(15*MINUTE);

}```

Can you please verify the problem with the blink example, while nothing is connected to the Arduino? Just to narrow down the problem more. Maybe the fuses of your Mega are configured the wrong way. If the same problem happens with the blink sketch you could try using another Arduino to burn the bootloader via ISP. That also sets the fuses.

I wouldn't use delay with so long values. Check the current time using millis() instead. This will also allow you to keep the board responding (i.e. to button presses).

An unrecommended method it to change long SECOND = 1000; to long SECOND = 10000;

@Gil, how should it work?

Each "SECOND" will be 10X longer. Remember when you are in delay the computer can do nothing else.

@Gil, are you serious? do you understand the cause of the problem in the question?

He stated things are happening about 10X what he wanted, he asked for the easiest way and did not want to change the code which would be the best. I also stated that was unrecommended. What did I miss, he originally stated he did not want to change his code, this was the simplest way I saw at the time.  What did I miss?

you missed that 15*MINUTE is calculated as int and overflows so the result is a much shorter delay


text:
How to send and receive data from serial using analog pins?
I have L293D shield connected to my arduino UNO and it fills nearly all the digital pins including TX(1) and RX(0) pins.
I know this function, but as far as I know, it works for digital pins.
SoftwareSerial NAME(Rx,Tx);

How can I set 2 analog pins as Tx and Rx? I will use them for HC-06.

The analog pins also have all the functionality of general purpose input/output (GPIO) pins (the same as digital pins 0 - 13). You can just declare it as SoftwareSerial mySerial(A0, A1).

BTW, read the caveats on Arduino Reference when using the analog pins as GPIO.

Is the shield really using all these pins, or is it just covering them up?


text:
DC Motor doesn't turn and a beep sound is made, also there is a burning smell
I was trying to drive a single dc motor with L293D Shield and Arduino Uno
#include <AFMotor.h>
#include <SoftwareSerial.h>

AF_DCMotor motorLeft(3);
AF_DCMotor motorRight(2);

unsigned char opMode = 0;

void setup()
{

}

void loop()
{
motorLeft.setSpeed(30);
motorLeft.run(FORWARD);
delay(5000);
motorLeft.setSpeed(0);
motorLeft.run(RELEASE);
delay(5000);
}

When I turned the power on, a beep sound was made continously. As I was trying to figure out where the sound comes from, I smelled something burning and turned the power off.
I am giving 6V (Four 1.5V  batteries in series) as external power. Burning smell doesn't come from batteries, that's for sure.
The smell comes from arduino or shield or both. But I think it is the the left LM293D driver.
What did I do wrong? Any idea?

Please show a schematic, or at least a wiring diagram. This doesn't sound like a code problem.

@JRobert The shield is not supported by fritzing so it is a little bit hard for me to create a schematic. But it is pretty simple. 6V is connected to EXT_PWR of the shield (Of course there is a switch in between), and DC motors are wired to M2 and M3. The polarity doesn't matter here as far as I know. There is nothing else. I have checked the polarity of the battery via multimeter. It is correct.

What happens if you power up the system with the motor(s) disconnected? With motor(s) connected but 6v disconnected? You need to partition the system some way until you can narrow down the source of the short-circuit. Obviously, keep the powered-on time as short as you can to limit any (more ):  damage while you're testing.

I did two things: I increased PWM from 30 to 255 and I took the PWRJMP jumper out. Now my card works totally fine. However, now I have to get power from both USB and batteries. Since I am trying to build a robot at the end, it is a problem. I am afraid to try with the PWRJMP on.

Alright, I finally realized that RPM value was too low. It has to be at least 150 for my case.