body:
**Code Snippet:**

    String a;

    const int red_led_pin = 13;

    void setup()
    {
      Serial.begin(115200);
      Serial.println("Hello, ESP32-S2!");
      pinMode(red_led_pin, OUTPUT);
    }

    void loop() {

        while (Serial.available())
        {
            a = Serial.readString();// read the incoming data as string
            Serial.print(" First: ");
            Serial.println(a);

            if (a.equals("on"))
            {
              Serial.println("LED ON");
              digitalWrite(red_led_pin, HIGH);

            }

            else  if (a == "off" || a == "OFF")
            {
              Serial.println("LED OFF");
              digitalWrite(red_led_pin, LOW);
            }

            Serial.print("Second: ");
            Serial.println(a);
        }
    }

**`Serial.print` out:**

[![enter image description here][1]][1]

**Circuitry:**

[![enter image description here][2]][2]

**Issue:**

The code can't capture the `on` string or any other string (`on`, `off` or `OFF`) that I pass. However it does pick it up and `Serial.print` it.

What is going wrong?

**Things I have tried:**

I have tried as a comparison:
 - `if (a.equals("on")){<>}`
 - `if (a == "on")){<>}`
 - `if (a.equalsIgnoreCase("on")){<>}`

**Due Diligence / Prior Research:**

 - [[ Documentation ] String Comparison Operators][3]
 - [[ Documentation ] String()][4]
 - [[ Forum ] Compare characters (or string) in “if” function][5]

  [1]: https://i.stack.imgur.com/kJPdF.png
  [2]: https://i.stack.imgur.com/x3e3r.png
  [3]: https://docs.arduino.cc/built-in-examples/strings/StringComparisonOperators
  [4]: https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
  [5]: https://forum.arduino.cc/t/compare-characters-or-string-in-if-function/692192/20

title: if statement with string comparison

Answers: 1

body:
Your problem is the line ending. The Serial Monitor has an option to send a line ending after the data, that you input. This line ending can be different depending on this setting, though mostly in the Arduino world a simple newline character `'\n'` is used.

This line ending will be in your string, when using `Serial.readString()`, so the string is not equal to `"on"`, but to something like `"on\n"`.

You can solve this issue by two ways:

- Set the Serial Monitor to no line ending.
- Or better: Use something like `Serial.readStringUntil()` and pass the line ending character to it as parameter (for example `Serial.readStringUntil('\n')`). This will read from the Serial interface until the specified character is reached. The specified character will be discarded and you are left with only the data, which you can then do comparisons on. This also has the advantage, that your code will react much faster, since it doesn't wait for 1s for new data (as long as you actually send the needed line ending).


body:
I have a mystery I was unable to solve and would greatly appreciate it if anyone could shed some light on this.

I have a servo DSS-M15S 270 which I managed to run perfectly fine with Arduino Uno (code below). I need only 2 cables for this - output & ground. The power cable is connected to batteries and the analog is irrelevant (although I managed to connect it as well just fine).

Same exact code on an ESP8266 NodeMCU fails to run the servo. I validated the right GPIO with a different sensor (PIR) that worked fine with the ESP, but the motor wouldn't work - it slightly jitters after a few minutes but nothing works. I already tried changing between different GPIOs and seeing different reactions but still nothing.

Eventually, I connected a new ESP32 with the same code and it almost worked! the servo works during the calibration function but ANY attempt to move it again OUTSIDE the calibration function fails. so I cancelled the calibration function and the servo works perfectly fine now with the ESP32 ! I have no idea how or what is happening.. if anyone could help me get it to work on ESP8266, that would be amazing.
Based on all those tests I reckon it's related to the different servo libraries of the chips somehow.

[https://youtube.com/shorts/fZlu8wdeRGQ][1]

In this second video I just return the cables back to the Arduino and everything works again (same code, same connection pins) -
[https://youtube.com/shorts/Jvr1oZV1AKI][2]

```
#include <Servo.h>

Servo myservo;

// Control and feedback pins
byte servoPin = 4;
int feedbackPin = A0;

// Calibration values
int minDegrees;
int maxDegrees;
int minFeedback;
int maxFeedback;
int tolerance = 2;  // max feedback measurement error

void calibrate(Servo servo, int analogPin, int minPos, int maxPos) {
    // Move to the minimum position and record the feedback value
    servo.write(minPos);
    minDegrees = minPos;
    delay(2000);  // make sure it has time to get there and settle
    minFeedback = analogRead(analogPin);

    // Move to the maximum position and record the feedback value
    servo.write(maxPos);
    maxDegrees = maxPos;
    delay(2000);  // make sure it has time to get there and settle
    maxFeedback = analogRead(analogPin);
}

int getPos(int analogPin) {
    return abs(map(analogRead(analogPin), minFeedback, maxFeedback, minDegrees, maxDegrees));
}

void ServoSetup() {
    Serial.println("Setting output");
    pinMode(servoPin, OUTPUT);

    Serial.println("Attaching");
    myservo.attach(servoPin);

    Serial.println("Calibrating");
    calibrate(myservo, feedbackPin, 0, 270);
}

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

void loop() {
    Serial.println(analogRead(A0));
    myservo.write(270);
    Serial.println("270");
    delay(2000);
    Serial.println(analogRead(A0));
    myservo.write(0);
    Serial.println("0");
    delay(2000);
}

```

The final code is basically like the above but without the calibration and different pins for the ESP32

Any ideas on what's happening here and how to make this work with ESP8266 would be great

Thanks,
Shay

  [1]: https://youtube.com/shorts/fZlu8wdeRGQ
  [2]: https://youtube.com/shorts/Jvr1oZV1AKI

title: ESP & Servo not communicating well

Answers: 0


body:
I've bought an ESP32 board [from here][1] and a 3.5" TFT Screen [from here][2]. The ESP32 board has an UNO type layout so I thought it would work with the screen which is designed to  plug in and play with Arduino UNOs.

However upon plugging the board and shield together (they fit perfectly, each pin goes in a corresponding slot), loading one of the example scripts (provided on the 3.5" Screen .rar download on the page), set Arduino to use ESP32 Development Board on COM3 (my usual settings for the ESP32) and uploading the code I just get a white screen on the TFT.

Is there some accommodation that I have to make because my board is not an UNO but instead a ESP32, i.e. is the pin layout different so maybe I'll need to wire this manually?

I've included the pin out diagrams below:

[![TFT shield pinout][3]][3]
[![TFT shield pinout instructions][4]][4]
[![ESP32 pinout][5]][5]

  [1]: https://www.az-delivery.de/en/products/esp32-d1-r32-board
  [2]: https://uk.banggood.com/3_5-Inch-TFT-Color-Display-Screen-Module-320-X-480-Support-UNO-Mega2560-Geekcreit-for-Arduino-products-that-work-with-official-Arduino-boards-p-1022298.html?cur_warehouse=CN
  [3]: https://i.stack.imgur.com/xrIlU.png
  [4]: https://i.stack.imgur.com/sF7Qv.png
  [5]: https://i.stack.imgur.com/dVviQ.jpg

**Arduino Sketch Code:**
```

#include <MCUFRIEND_kbv.h>
#include <Adafruit_GFX.h>    // Core graphics library

// wiring with UNO or Mega2560:
//--------------POWER Pins--------------------------------
//   5V  connects to DC 5V
//   GND connects to Ground
//   3V3 do not need to connect(NC)
//--------------LCD Display Pins--------------------------
//   LCD_RD   connects to Analog pin A0
//   LCD_WR   connects to Analog pin A1
//   LCD_RS   connects to Analog pin A2
//   LCD_CS   connects to Analog pin A3
//   LCD_RST  connects to Analog pin A4
//   LCD_D0   connects to digital pin 8
//   LCD_D1   connects to digital pin 9
//   LCD_D2   connects to digital pin 2
//   LCD_D3   connects to digital pin 3
//   LCD_D4   connects to digital pin 4
//   LCD_D5   connects to digital pin 5
//   LCD_D6   connects to digital pin 6
//   LCD_D7   connects to digital pin 7
//--------------SD-card fuction Pins ----------------------
//This Connection Only for UNO, Do not support Mega2560
//because they use different Hardware-SPI Pins
//SD_SS    connects to digital pin 10
//SD_DI    connects to digital pin 11
//SD_DO    connects to digital pin 12
//SD_SCK   connects to digital pin 13

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define LCD_CS A3   // Chip Select goes to Analog 3
#define LCD_CD A2  // Command/Data goes to Analog 2
#define LCD_WR A1  // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

// Assign human-readable names to some common 16-bit color values:
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

MCUFRIEND_kbv tft;

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(BLACK);
  tft.fillScreen(RED);
  tft.fillScreen(GREEN);
  tft.fillScreen(BLUE);
  tft.fillScreen(BLACK);
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}

unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();

  tft.fillScreen(BLACK);

  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing

  tft.fillScreen(BLACK);

  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  tft.fillScreen(BLACK);

  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  tft.fillScreen(BLACK);

  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);

  return micros() - start;
}

unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();

  tft.fillScreen(BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);

  return micros() - start;
}

unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;

  tft.fillScreen(BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }

  return micros() - start;
}

unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
  }

  return t;
}

unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;

  tft.fillScreen(BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;

  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;

  tft.fillScreen(BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(0, 0, i));
  }

  return micros() - start;
}

unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;

  tft.fillScreen(BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i, i));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i, i, 0));
  }

  return t;
}

unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
  }

  return micros() - start;
}

unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
  }

  return micros() - start;
}
void setup(void) {
   Serial.begin(9600);
  Serial.println(F("TFT LCD test"));

  tft.reset();

  uint16_t identifier = tft.readID();
  if(identifier == 0x9325) {
    Serial.println(F("Found ILI9325 LCD driver"));
  } else if(identifier == 0x9328) {
    Serial.println(F("Found ILI9328 LCD driver"));
  } else if(identifier == 0x4535) {
    Serial.println(F("Found LGDP4535 LCD driver"));
  }else if(identifier == 0x7575) {
    Serial.println(F("Found HX8347G LCD driver"));
  } else if(identifier == 0x9595) {
    Serial.println(F("Found HX8347-I LCD driver"));
  } else if(identifier == 0x4747) {
    Serial.println(F("Found HX8347-D LCD driver"));
  } else if(identifier == 0x8347) {
    Serial.println(F("Found HX8347-A LCD driver"));
  }else if(identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  }else if(identifier == 0x7783) {
    Serial.println(F("Found ST7781 LCD driver"));
  }else if(identifier == 0x8230) {
    Serial.println(F("Found UC8230 LCD driver"));
  }else if(identifier == 0x8357) {
    Serial.println(F("Found HX8357D LCD driver"));
  } else if(identifier==0x0101){
      identifier=0x9341;
      Serial.println(F("Found 0x9341 LCD driver"));
  }else if(identifier==0x7793){
       Serial.println(F("Found ST7793 LCD driver"));
  }else if(identifier==0xB509){
       Serial.println(F("Found R61509 LCD driver"));
  }else if(identifier==0x9486){
       Serial.println(F("Found ILI9486 LCD driver"));
  }else if(identifier==0x9488){
       Serial.println(F("Found ILI9488 LCD driver"));
  }else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
    Serial.println(F("  #define USE_ADAFRUIT_SHIELD_PINOUT"));
    Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
    Serial.println(F("If using the breakout board, it should NOT be #defined!"));
    Serial.println(F("Also if using the breakout, double-check that all wiring"));
    Serial.println(F("matches the tutorial."));
    identifier=0x9486;
  }
  tft.begin(identifier);

  Serial.println(F("Benchmark                Time (microseconds)"));

  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);

  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);

  Serial.print(F("Lines                    "));
  Serial.println(testLines(CYAN));
  delay(500);

  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(RED, BLUE));
  delay(500);

  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(GREEN));
  delay(500);

  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(YELLOW, MAGENTA));
  delay(500);

  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, MAGENTA));

  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, WHITE));
  delay(500);

  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);

  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);

  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);

  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);

  Serial.println(F("Done!"));
}

void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(2000);
  }
}
```

title: How do I interface my ESP32 board with my 3.5" TFT Screen

Answers: 0


body:
I am experimenting with creating my own Arduino libraries. Unfortunately, while the program compiles, the end result does not work.

For purposes of experimentation, I have broken down the library in two parts. One that will handle blinking by controlling the `LED_BUILDIN` pin and one that will talk to the serial input.

Thus two `.h` and two `.cpp` files. Plus there is another file for the configuration that handles preprocessor directives that the library reads.

This is the code:

FILE 1

    //header_config.h
    #ifndef MY_CONFIGURATION
    #define MY_CONFIGURATION

    #include <Arduino.h>

    #define SERIAL_DEBUG
    #define LED_BLINK

    #include <led_functions.h>
    #include <serial_functions.h>

    void my_setup()
    {
      my_setup_led();
    }

    void my_loop()
    {
        led_blinker();
        serial_transmit("Hello");
    }

    #endif

FILE 2

    //led_functions.h
    #ifndef MY_LED_LIBRARY
    #define MY_LED_LIBRARY

      #include <Arduino.h>
      #include "header_config.h"
      #include "serial_functions.h"

      extern void led_blinker();
      extern void my_setup_led();

    #endif

FILE 3

    //led_functions.cpp
    void led_blinker()
    {
      #ifdef LED_BLINK
      digitalWrite(LED_BUILTIN, HIGH);
      serial_transmit("LED ON");
      delay(1000);
      digitalWrite(LED_BUILTIN, LOW);
      serial_transmit("LED OFF");
      delay(1000);
      #endif
    }

    void my_setup_led()
    {
    #ifdef LED_BLINK
    pinMode(LED_BUILTIN, OUTPUT);
    #endif
    }

FILE 4

    //serial_functions.h
    #ifndef MY_SERIAL_LIBRARY
    #define MY_SERIAL_LIBRARY

      #include <Arduino.h>
      #include "header_config.h"

      #ifdef SERIAL_DEBUG
      #include <SoftwareSerial.h>
      #define rxPin 2
      #define txPin 3
      SoftwareSerial mySerial(rxPin, txPin);
      #endif

      extern void serial_transmit(char*);

    #endif

FILE 5

    //serial_functions.cpp
    void serial_transmit(char *str)
    {
      #ifdef SERIAL_DEBUG
      //mySerial.begin(9600);
      //mySerial.println(str);
      //mySerial.end();
      Serial.begin(9600);
      Serial.println(str);
      Serial.end();
      #endif
    }

Please note that while the serial code creates a `SoftwareSerial` object (in `serial_functions.h`), I do not use that (in `serial_functions.cpp`) and instead I make use of hardware Serial. The reason is debugging, so that I can see communication on the PC. I left the `SoftwareSerial` object inside, because that is what I ultimately want.

Finally, outside the library, in it's separate folder, is the `.ino` file that makes use of this library.

    #include <header_config.h>
    #include <led_functions.h>
    #include <serial_functions.h>

    void setup()
    {
      my_setup();
    }

    void loop()
    {
      my_loop();
    }

As I said, the program compiles fine, but it does not work in the real world. Neither the blinking, nor the serial communication.

title: Unable to get my created library to work - while it compiles

Answers: 1

body:
Your cpp files don't include the header_config.h file, so they don't have SERIAL_DEBUG and LED_BLINK defined.

The content of included file replaces the include directive so if you now include header_config.h into both cpp, there will be 3 functions named my_setup() and 3 functions named my_loop() and the linker will complain. So you can't put functions definitions into an include file. And for the same reason you can't have variable definitions in .h file so the SoftwareSerial instance will cause problems too if used.


body:
Hello i have a question for you. I have 6 St7735s screen 0.96 ınch. I connect them to my Raspberry pi pico. I want to show them some text but they are showing at the same time. First screen start working and shows "Screen 1 Test" and then its close. After that second screen start working and show "Screen 2 Test" and its close again and it goes to last screen and it show "Screen 6 test" and not closing. But the rest of it stay close. I use same connection for GND - VCC - SCL - SDA - RES - DC pins. Only Cs pin is diffrent. Any advice for me?

The code that i used :

    #include <Adafruit_GFX.h>
    #include <Adafruit_ST7735.h>
    #include <SPI.h>

    #define TFT_CS1 2
    #define TFT_CS2 3
    #define TFT_CS3 4
    #define TFT_CS4 5
    #define TFT_CS5 14
    #define TFT_CS6 15
    #define TFT_DC 9
    #define TFT_RST 7

    Adafruit_ST7735 tfts[] = {
      Adafruit_ST7735(TFT_CS1, TFT_DC, TFT_RST),
      Adafruit_ST7735(TFT_CS2, TFT_DC, TFT_RST),
      Adafruit_ST7735(TFT_CS3, TFT_DC, TFT_RST),
      Adafruit_ST7735(TFT_CS4, TFT_DC, TFT_RST),
      Adafruit_ST7735(TFT_CS5, TFT_DC, TFT_RST),
      Adafruit_ST7735(TFT_CS6, TFT_DC, TFT_RST)
    };

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

      for(int i = 0; i < 6; i++){
        tfts[i].initR(INITR_MINI160x80);
        tfts[i].setRotation(3);
        tfts[i].fillScreen(ST7735_BLACK);
        tfts[i].setTextColor(ST7735_WHITE);
        tfts[i].setTextSize(2);
      }
    }

    void loop() {
      for(int i = 0; i < 6; i++){
        tfts[i].setCursor(0, 0);
        tfts[i].println("Screen " + String(i+1) + " test");
        delay(1000);
      }
    }

title: 6 ST7735 screens not working at same time with Pico

Answers: 0


body:
I use the TinyPICO microcontroller with ESP32 and I program it using the Arduino IDE. I recently got a new error on my Serial Monitor:

    E (113) esp_core_dump_�^X.K�ɕ�dump data check failed:
    Calculated checksum='453aefca'
    Image checksum='ffffffff'`

This error also occurs with the examples provided by the Arduino IDE for the TinyPICO like 'TinyPICO_Funky_LED.ino', so the error must be on the TinyPICO or must have something to do with the serial connection.

Also it is worth mentioning that this error didn't occur yesterday with the exact same computer and microcontroller. All the programs work fine but this error always comes in my Serial monitor. My guess is that I somehow accidentally wrote something on the TinyPICO which would create this error but I am not sure.

Do you have any idea on what could be the cause of this error and how I could fix it (or ignore it) ?

title: Dump data check failed on a TinyPICO using ESP32

Answers: 0


body:
I have an Arduino (with environmental sensors doing measurements) connected to the Internet via ethernet. Can it be hacked? Can someone access it via Internet and upload his own C/C++ code? If, yes how can I prevent this?

**Update (03/03/2023):** One final thought: Supposing that I have secured USB plug and nobody can access it. However, I am using the Serial interface of the Arduino MEGA 2560. So, Serial_1 is continuously reading. Can someone with ***physical access*** to the Arduino inject malicious code via the Serial_1 so that can alter the code inside my Arduino and have access to information?

title: How to prevent an Arduino connected to the Internet from being hacked?

Answers: 1

body:
This depends on what you consider "hacked".

Do you care about someone reading the data, or changing it on its way to the target? Or do you provide endpoints to trigger something in your project from the internet, that only you should be able to do? Then you need to think about authentication and encryption. Though I guess that this data will be published either way, so that is not a big problem. But you should write down every endpoint, that you expose to the internet, and every request you are making. Then decide what level of security you need them to have individually. Exposed endpoints can easily be found and you have to decide yourself, if it is OK for others to use them.

If you mean getting into the device and executing malicious code from there: IOT devices are often vulnerable because of two reasons. They often have an OS (like a small linux OS), that is badly secured (often using standard password). And they often get updates via the internet. If someone can hijack the update process, malicious code might be delivered. An Arduino doesn't have an OS, so that isn't a problem. And hijacking the update process won't be possible, if you don't provide the possibility to update through the network. This makes updating your code a bit more complicated (since you need to connect the Arduino via USB or similar to program it), but more secure. That way no one (not even you) can inject malicious code into your project without physical access to the Arduino. To take up Jurajs comment: Updating through network is normally done by the Ethernet bootloader or the ArduinoOTA library (Over The Air updates). If you are not using those or similar projects, then you will be safe in that regard.

---

With strangers having physical access to the device it is a different story. To reprogram the Arduino one would need access to Serial (RX0 and TX0) and a possibility to reset the Arduino (either Reset pin or a way for power cycling it), or access to the ISP pins and the reset pin.

If you can secure the Arduino itself from physical access and only expose the Serial1 interface and ground/5V, then you will be safe, since the bootloader is only listening on Serial (RX0 and TX0). But keep in mind, that someone might still break into your project with brute force - depending on how you secured it physically. At that point nothing can stop them from overwriting your code. Only you can assess how big the chance for that is and how bad it would be.

Another point: If someone manages to break into your project, he can read out the program and push it through a deassembler. That doesn't give them the C++ code - they are not seeing C++ code, only assembler, and no meaningful variable names - but if they are determined enough they can read out credentials, that you might have hard coded or saved in EEPROM. Though especially for environmental sensors I would say the chance is very low, that someone would go to such lengths. If you think the danger to be big enough for some inconvenience, you can have a look at code protection (protecting the program memory from being read), though that still doesn't completely block reprogramming.

All in all: Preventing physical access is a big step in security. You yourself need to assess how much security you really need for your project.


body:
I am working with pH sensor (https://wiki.seeedstudio.com/Grove-PH-Sensor-kit/ ) and arduino. The board provided with sensor is not having any potentiometer to set the voltage value when dipped in known buffer solution. I have read that when BNC connector is short then voltage value should be 2.5 V. But when I do the same voltage comes out to be 1.9 V. Also sensor gives wrong readings when put in known buffer solutions of 4.0pH, 7.0pH and 9.2 pH. I am not getting how to calibrate the sensor without having potentiometer on board.
I have already done as per mentioned on website (in link given above).

title: Calibration of pH sensor

Answers: 1

body:
You probably need to do that in software. That is supported by step 7 in the chapter Software on your linked site.

In step 4 we see the proposed demo code, which contains the calculation of pH based on the read voltage:

    pHValue = -19.18518519 * voltage + Offset;

The first number is probably `k`, so the calculation is

    pHValue = k * voltage + Offset;

For the calibration you need to find the values for `k` and `Offset`. This is done with 2 buffer solutions with known pH. Step 7 shows the formulas for calculating these values based on the known pH values (removed the dollar signs):

    k= (PH2-PH1)/(V2-V1)
    Offset=[(PH2+PH1)-k*(V1+V2)]/2

And they even provide a link to an Excel sheet, which helps you with the calculation: [https://files.seeedstudio.com/wiki/Grove-PH_Sensor_kit/Calibration_for_k&offset.xlsx][1]

Here is an image of that sheet:

[![Excel sheet with offset calculation][2]][2]

In column B behind PH1 and PH2 you can input the known pH values for your buffer solutions. In column E behind V1 and V2 you can input the resulting sensor voltages (! voltages, not wrongly calculated pH values) for each solution. Then you will get your values of `k` and `Offset` in the cells B4 and B5.

Input those values into the calculation for `phValue` in the code and you should get correct values.

  [1]: https://files.seeedstudio.com/wiki/Grove-PH_Sensor_kit/Calibration_for_k&offset.xlsx
  [2]: https://i.stack.imgur.com/4DL5g.png


body:
OK, I have a little hardware issue I need to fix in software for the time being.  I say, "For the time being," because I already have the PC Boards printed, and I need to make do for this run of boards.  (So sue me for not bread boarding first.)  I THOUGHT the little buzzers I purchased sounded off on a DC input, but I was wrong.  I used the nearest pin to the buzzer to activate it, which is D14.  The next run of boards I will use A6 instead, but  until then I will need to output a square wave of about 2731 Hz on D14 of an ATTiny88.  The straightforward approach would seem to be something like:

```
bool buzzer(bool x) {
  if (x) {
    return true;
  }
  return false;
}
bool PinVal = false;
void loop() {
  <some code here>
  buzzerVal = buzzer(true | false);
  <some code here>
  if (buzzerVal && micros()76 > 365) {
    PinVal = !PinVal;
    digitalWrite`(14,PinVal);
    }
  while (micros()76 > 365);
}
```
Is there a smarter, more efficient way?  If so, I might consider not even changing the board layout.  Pin 14 has an alternate function of register PB7.  It occurs to me it might be more efficient to write directly to PB7, rather than using the digitalWrite function, which presumably has more overhead.  Yes? No?  Any other ideas?

title: I goofed: I used a digital output rather than an analog output

Answers: 0


body:
I am suddenly getting an error every time I try to compile code in the IDE, even though every one of the sketches previously compiled just fine:

```
Arduino: 1.8.13 (Windows 7), Board: "MH-ET LIVE Tiny88(16.0MHz)"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\lrhorer\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\lrhorer\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\lrhorer\Documents\Arduino\libraries -fqbn=mhetlive:avr:MHETtiny88 -ide-version=10813 -build-path C:\Users\lrhorer\AppData\Local\Temp\arduino_build_609285 -warnings=all -build-cache C:\Users\lrhorer\AppData\Local\Temp\arduino_cache_521731 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.micronucleus.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.micronucleus-2.0a4.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.avr-gcc.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -prefs=runtime.tools.avr-gcc-4.8.1-arduino5.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -verbose C:\Users\lrhorer\Documents\Arduino\sketch_feb27a\sketch_feb27a.ino

C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\lrhorer\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\lrhorer\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\lrhorer\Documents\Arduino\libraries -fqbn=mhetlive:avr:MHETtiny88 -ide-version=10813 -build-path C:\Users\lrhorer\AppData\Local\Temp\arduino_build_609285 -warnings=all -build-cache C:\Users\lrhorer\AppData\Local\Temp\arduino_cache_521731 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.micronucleus.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.micronucleus-2.0a4.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.avr-gcc.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -prefs=runtime.tools.avr-gcc-4.8.1-arduino5.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -verbose C:\Users\lrhorer\Documents\Arduino\sketch_feb27a\sketch_feb27a.ino

Using board 'MHETtiny88' from platform in folder: C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\hardware\avr\1.0.0

Using core 'tiny88' from platform in folder: C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\hardware\avr\1.0.0

Detecting libraries used...

"C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\4.8.1-arduino5/bin/avr-g++" -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -w -x c++ -E -CC -mmcu=attiny88 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_DIGISPARKPRO -DARDUINO_ARCH_AVR "-IC:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\mhetlive\\hardware\\avr\\1.0.0\\cores\\tiny88" "-IC:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\mhetlive\\hardware\\avr\\1.0.0\\variants\\tiny88" "C:\\Users\\lrhorer\\AppData\\Local\\Temp\\arduino_build_609285\\sketch\\sketch_feb27a.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE

exec: "C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\4.8.1-arduino5/bin/avr-g++": file does not exist

Error compiling for board MH-ET LIVE Tiny88(16.0MHz).

```
The file indeed does not exist in that location.  What now?

Update:
Under the ATTinyCore compiler the missing file name is the same, but the directory is different:
```
exec: "C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++": file does not exist
```
The latest version of the DigiStump compiler does not even have the MH-ET Live Tiny88 board compiler included.

I can get the code to compile under Linux, but I am having trouble uploading the binary to the board.  How can I take the binary code and upload it to the ATTiny88 board under either Linux or Windows 7?

Update:
I found three files quarantined by my anti-virus.  I restored the files, and now avr-g++.exe seems to be back where it belongs, and the compiler no longer claims the file is missing.  Now, however, it s complaining about not finding the stdlib.h library called from the Arduino.h library.

Update:
After I removed three files apparently related to the IDE from quarantine by my virus scanner, I deleted everything, and re-installed the IDE.  Now it compiles without error, but I cannot upload to the board in either Windows or Linux.  Of course I tried more than once to reinstall the Windows USB drivers, and they install without error, but the virtual device does not show up like it is supposed to, and the upload processor times out.

title: Sudden Error: File does not exist

Answers: 1

body: Deleting / uninstalling the entire IDE and completely reinstalling allowed the code to compile, so I am closing this question.  It will not upload, so I will open another question.


body: I have a device programmable via an 8 bit digital parallel bus. I would like an Arduino to translate from a parallel 4 bit output of an existing device to 8 bit by intentionally reducing the resuloution. Unfortunately, I can't just use the most significant bits as I want to change the step size. The idea is to use an Arduino that ready the 4 digital input bits and then computs the necessary 8 bit output which it output to the 8 bit bus. However, this need to be as fast as 1 us. Is this possible with an Arduino? If so which board would you recommend? I guess I can't use the digitalWrite command as this will be too slow though. Any suggestions?

title: Fast digital IO

Answers: 1

body:
You can do this with an Uno, provided it has nothing else to do. I would
program it low-level, skipping the Arduino core since, as you said,
`digitalWrite()` would be too slow for this application.

Here is my proposed approach: read the 4-bit input from one port, use a
look-up table to translate it to an 8-bit output, and write that output
to another port. I would use PORTD (pins 0–7) for the output, as it is
the only full 8-bit port on the Uno, then the first bits of PORTB (pins
8–11) for the input:

```c++
/* Translation look-up table (dummy example). */
const uint8_t lut[16] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
};

int main() {
    DDRB = 0x00;  // set port B as input
    DDRD = 0xff;  // set port D as output
    for (;;) {
        uint8_t input = PINB & 0x0f;  // grab the lowest 4 bits
        PORTD = lut[input];  // set the output
    }
}
```

I compiled and disassembled this code to count the CPU cycles: the main
loop takes 10 cycles per iteration. Given that the Uno is clocked
at 16 MHz, this is one update of the output every 0.625 µs.

**Edit**: This is a straightforward approach. At the cost of some extra
complexity, it could be optimized down to 7 cycles per iteration
(0.438 µs), or even 6 cycles (0.375 µs) in assembly.


body:
I want to communicate between Jetson nano and arduino nano through serial.

I wrote a simple script to test functionality but I receive strange data

here is the arduino code

```
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println("work fine");
  delay(10000);
}

```
and this is the python code run on jetson nano
```
import serial
import time

arduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

while True:
  try:
     data = arduino.readline()
     if data:
        print(data)
        print('Hi Arduino')
  except:
     arduino.close

```

the output is

```
b'\x17\x0f\t\x0b\x01\x06\t\x0e\x15\r\n'
Hi Arduino
```

if tried different baud rates but nothing change.

when is use serial monitor on windows it works fine.

title: USB serial communication arduino nano and jetson nano

Answers: 2

body:
[This stackoverflow question/answer][1] implies that .readline() needs to be converted to a string.

    import serial
    ser = serial.Serial("COM11", 9600)
    while True:
         cc=str(ser.readline())
         print(cc[2:][:-5])

I agree w/one of the comments to that answer that it might be better written as:

    import serial
    ser = serial.Serial("COM11", 9600)
    while True:
         cc=str(ser.readline())
         cc=cc.decode("utf-8")
         print(cc)

  [1]: https://stackoverflow.com/questions/16077912/python-serial-how-to-use-the-read-or-readline-function-to-read-more-than-1-char

body:
I also belive its to do with the following line,

     data = arduino.readline()

Try the following,

    while True:

    try:
         arduino.flushInput() // Clear buffer

         data = arduino.readline()

         // decode the bytes into str format, 'utf-8' arg should work
         data.decode('utf-8')

         // strip the \r\t in the str output
         data.strip()
         if data:
            print(data)
            print('Hi Arduino')
      except:
         arduino.close

See if this resolves your problem.

Note: I used an ESP32 and python script with the above-mentioned changes and it worked for me.

Also, as mentioned in the comment section some of the information might be missing in the output `'b'\x17\x0f\t\x0b\x01\x06\t\x0e\x15\r\n'` this is not something reproducible for me. Just for reference my byte string output without the modifications was `b'work fine\r\n'` not `'b'\x17\x0f\t\x0b\x01\x06\t\x0e\x15\r\n'`
 - double-check Arduino write speed,
 - double-check python serial connection baud rate,
 - include the py script correction

see if this helps resolve your problem.


body:
I have an ATMega324PA and I want to power down and only wake on CAN receive (working on int 0 successfully), on a schedule, on pcints on 6 digital inputs, and on serial receive - either serial0 or serial1.
I have read Nick Gammon's forum post and have tried to adapt his code to my 324. It will go into sleep, wake on a digital input but then stays awake. I've obviously got something wrong. Also I'm not clear on how to wake on serial. This is some basic test code, the CAN code is not included.

    #include <avr/sleep.h>  // Sleep Modes
    #include <avr/power.h>  // Power management
    #include <avr/wdt.h>    // Watchdog timer

    const byte LED1 = 18;  // pin DO1
    const byte DI1 = 28;   // pin DI1 / PCINT4
    const byte DI2 = 29;   // pin DI2 / PCINT5
    const byte DI3 = 30;   // pin DI3 / PCINT6
    const byte DI4 = 31;   // pin DI4 / PCINT7
    const byte DI5 = 22;   // pin DI5 / PCINT22
    const byte DI6 = 23;   // pin DI6 / PCINT23

    ISR(PCINT0_vect) {
      PCICR = 0;
    }
    ISR(PCINT1_vect) {
      PCICR = 0;
    }
    ISR(PCINT2_vect) {
      PCICR = 0;
    }
    // watchdog interrupt
    ISR(WDT_vect) {
      wdt_disable();  // disable watchdog
    }  // end of WDT_vect

    // sleep bit patterns for WDTCSR
    enum {
      WDT_16_MS = 0b000000,
      WDT_32_MS = 0b000001,
      WDT_64_MS = 0b000010,
      WDT_128_MS = 0b000011,
      WDT_256_MS = 0b000100,
      WDT_512_MS = 0b000101,
      WDT_1_SEC = 0b000110,
      WDT_2_SEC = 0b000111,
      WDT_4_SEC = 0b100000,
      WDT_8_SEC = 0b100001,
    };  // end of WDT intervals enum

    void resetWatchdog() {
      // clear various "reset" flags
      MCUSR = 0;
      // allow changes, disable reset, clear existing interrupt
      WDTCSR = bit(WDCE) | bit(WDE) | bit(WDIF);
      // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
      WDTCSR = bit(WDIE) | WDT_8_SEC;  // set WDIE, and 8 seconds delay
      // pat the dog
      wdt_reset();
    }  // end of resetWatchdog

    void setup() {

      // disable JTAG for pins 18 to 21
      MCUCR |= (1 << JTD);
      MCUCR |= (1 << JTD);

      resetWatchdog();  // do this first in case WDT fires

      pinMode(LED1, OUTPUT);
      pinMode(DI1, INPUT_PULLUP);
      pinMode(DI2, INPUT_PULLUP);
      pinMode(DI3, INPUT_PULLUP);
      pinMode(DI4, INPUT_PULLUP);
      pinMode(DI5, INPUT);
      pinMode(DI6, INPUT);

      // pin change interrupt masks
      PCMSK2 |= bit(PCINT22);  // pin 22
      PCMSK2 |= bit(PCINT23);  // pin 23
      PCMSK0 |= bit(PCINT4);   // pin Din1
      PCMSK0 |= bit(PCINT5);   // pin Din2
      PCMSK0 |= bit(PCINT6);   // pin Din3
      PCMSK0 |= bit(PCINT7);   // pin Din4

      // clear any outstanding interrupts
      PCIFR |= bit(PCIF0) | bit(PCIF1) | bit(PCIF2);
      // enable pin change interrupts
      PCICR |= bit(PCIE0) | bit(PCIE1) | bit(PCIE2);

    }  // end of setup

    void loop() {
      digitalWrite(LED1, HIGH);
      delay(500);
      digitalWrite(LED1, LOW);
      delay(500);

      goToSleep();
    }  // end of loop

    void goToSleep() {
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      ADCSRA = 0;           // turn off ADC
      power_all_disable();  // power off ADC, Timer 0 and 1, serial interface
      noInterrupts();       // timed sequence coming up
      resetWatchdog();      // get watchdog ready
      sleep_enable();       // ready to sleep
      interrupts();         // interrupts are required now
      sleep_cpu();          // sleep
      sleep_disable();      // precaution
      power_all_enable();   // power everything back on
    }  // end of goToSleep

title: Power saving and pc interrupts on ATMega324PA

Answers: 0


body:
Hello i wrote this sketch that upload a temperature reading of a DHT22 sensor to a phpMyAdmin server in localHost, the sketch work fine, the data been upload every 5 min to the server than ESP go t sleep, but every time the code has been executed i have the printout in the console of this error which i don't understand what mean.

```
[  1937][E][WiFiClient.cpp:517] flush(): fail on fd 48, errno: 11, "No more processes"

```

here below my sketch:
the sketch include the timer every 5 min to wakeup esp read the temperature and post to the server.

```
#include <Arduino.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>

// FOR T sensor
#define TsensorPin 4
#define DHTTYPE DHT22
DHT dht(TsensorPin, DHTTYPE);
String sensorName = "DHT22";
String sensorLocation = "Casa1";
float h;
float t;
float f;
float hif;
float hic;

// for wifi connection
const char* ssid     = "Captain Spiko";
const char* password = "123456789d";

// server data
const char* serverName = "http://192.168.50.158/esp_web/post_esp.php";
String apiKeyValue = "123456789";

// for awake and sleep
#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  300
RTC_DATA_ATTR int bootCount = 0;

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void readTemperature(){

  h = dht.readHumidity();
  t = dht.readTemperature();
  f = dht.readTemperature(true); // in F

  // Compute heat index in Fahrenheit (the default)
  hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

void activateSleep(){
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush();
  esp_deep_sleep_start();
}

bool setupWifi(){
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  if (WiFi.status() == WL_CONNECTED){
    return true;
  } else {
    return false;
  }

}

void postData(){
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
    http.begin(client, serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
                          + "&location=" + sensorLocation + "&value1=" + String(h)
                          + "&value2=" + String(t) + "&value3=" + String(f) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    int httpResponseCode = http.POST(httpRequestData);
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }else {
    Serial.println("WiFi Disconnected");
  }
}

/// @brief  Set up
void setup() {

  Serial.begin(115200);
  delay(1000);
  ++bootCount; // tiene il conto dei restart
  Serial.println("Boot number: " + String(bootCount));
  print_wakeup_reason();
  if (setupWifi() == true){
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);// set up next wake up after 30 sec
    Serial.println(F("DHTxx test!"));
    dht.begin();
  };

}

/// @brief loop func
void loop() {
  readTemperature();
  postData();
  activateSleep();
}

```

title: WiFiClient.cpp:517 flush(): fail on fd 48, errno: 11, "No more processes" what it mean?

Answers: 3

body:
I think you ran into the issue [described on Github issues for WifiClient](https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915).

A user has loooked into this and found that the error message does not match the problem:

> errno 11 (EAGAIN) happens when you go to read (via BSD recv function) bytes from a stream with MSG_DONTWAIT flag and there are no bytes to be read. The ESP error string "No more processes" is misleading. It's really "No data available, try again later." or maybe "No data to process".

It seems that there's no fix for the package yet as of today, but [another user has posted a derived class that fixes the problem](https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1418051304):

> File wifiFix.h:
>
>     #pragma once
>
>     class WiFiClientFixed : public WiFiClient {
>     public:
>      void flush() override;
>     };
>
> File wifiFix.cpp:
>
>     #include <WiFi.h>
>     #include <lwip/sockets.h>
>     #include "wifiFix.h"
>
>     #define WIFI_CLIENT_FLUSH_BUFFER_SIZE    (1024)
>
>     void WiFiClientFixed::flush() {
>      int res;
>      size_t a = available(), toRead = 0;
>      if (!a) {
>       return;//nothing to flush
>      }
>      auto *buf = (uint8_t *) malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE);
>      if (!buf) {
>       return;//memory error
>      }
>      while (a) {
>       // override broken WiFiClient flush method, ref https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915
>       res = read(buf, min(a, (size_t)WIFI_CLIENT_FLUSH_BUFFER_SIZE));
>       if (res < 0) {
>        log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
>        stop();
>        break;
>       }
>       a -= res;
>      }
>      free(buf);
>     }
>
> File main.cpp:
>
>     #include "wifiFix.h"
>     WiFiClient* wifi = new WiFiClientFixed();
>
> Finally, instead of `http.begin(url);`, use `http.begin(*wifi, url);`

body: In Platformio.ini I changed config to **"platform = espressif32@3.5.0"** from "platform = espressif32". It solved this issue for me

body:
This bug is solved in Espressif Arduino Core 2.0.14 which is out since last month. If you're using PlatformIO add this to your platformio.ini file:

    platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.05/platform-espressif32.zip

This is not from the official PlatformIO branch but from Tasmota, a trusted source in the PlatformIO community. See the github site: https://github.com/tasmota/platform-espressif32


body:
I wanted to make a simple led on/off program using USART interface. When the code doesn't have any functions other than main it runs fine, however Arduino keeps resetting when one is included. At this point I have no clue what could I be doing wrong. Here's the code:

    #include <avr/io.h>
    #include <util/delay.h>

    #define BAUD 19200
    #define BAUDRATE ((F_CPU / 16 / BAUD) - 1)

    // void init()
    // {
    //     // Keeps resetting when uncommented, runs fine when commented
    // }

    int main() {
        // Initialize USART
        UBRR0H = (BAUDRATE >> 8);
        UBRR0L = BAUDRATE;
        UCSR0B = (1 << RXEN0);
        UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
        // Set bit 3 to output and pull it high
        DDRD |= 0b00001000;
        PORTD = 0b00001000;

        char char_arr[128];

        while(1)
        {
            int i;
            // Read USART
            for(i = 0; i < 128; i++){
                loop_until_bit_is_set(UCSR0A, RXC0);
                char c = UDR0;
                if(c == '\r')
                    break;
                char_arr[i] = c;
            }
            // Handle received characters
            for(int j = 0; j < i; j++){
                switch(char_arr[j]){
                    case '1':
                        PORTD = 0b00001000;
                        break;
                    case '0':
                        PORTD = 0b00000000;
                        break;
                }
                _delay_ms(100);
            }
        }
    }

title: Atmega328P constantly restarting when defining a function

Answers: 0


body:
this is the sample code where the user enters A to set the number of times the pet needs to be fed. When I click A on the keypad it asks for the user to set the number. However, the keypad still somehow saves the input of A that is initially pressed. I want the system to ask for another input. How would I clear the memory of the keypad?
Here is the code attached

        /* Hello Wokwi! */
    #include <Keypad.h>
    #include <LiquidCrystal_I2C.h>
    const int ROW_NUM    = 4; // four rows
    const int COLUMN_NUM = 4; // four columns
    char keys[ROW_NUM][COLUMN_NUM] = {
      {'1','2','3', 'A'},
      {'4','5','6', 'B'},
      {'7','8','9', 'C'},
      {'*','0','#', 'D'}
    };
    int col = 0, row =0;
    byte pin_rows[ROW_NUM] = {10,9,8,7};      // connect to the row pinouts of the keypad
    byte pin_column[COLUMN_NUM] = {6,5,4,3}; // connect to the column pinouts of the keypad
    LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows
    Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

    void setup () {

      lcd.init(); // initialize the lcd
      lcd.backlight();
      lcd.setCursor(col,row); // move cursor to   (cursorColumn, 0)
      lcd.print("HI OWNER");
      delay(3000);
    }
    int h1,h2,hf1,min1,min2,minf1;
    int numfed,setnofeed=0;

    void loop() {

      char key = keypad.getKey();
      if(!key){
        displaytime();
      }

      switch(key){
        case 'A':
          lcd.setCursor(col,row);
        lcd.print("SET NO. OF");
        lcd.setCursor(col,1);
        lcd.print("FEEDING TIMES");
        delay(3000);

        lcd.clear();
        lcd.setCursor(col,row);
        lcd.print("MAX 5 MIN 2");
        col=0;
        lcd.setCursor(col,1);
        if (col==0&&setnofeed==0){
          numfed=key-48;
          lcd.print(numfed);
          delay(1000);
          col=1;
        }
        else if(col==1){
        lcd.setCursor(col,1);
        lcd.clear();
        lcd.print("NO. OF FEEDING");
        lcd.setCursor(col,1);
        lcd.print("SET");
        delay(2000);
        setnofeed=1;
        }

        break;

      }

    }
    void displaytime(){

          lcd.setCursor(0,0); // move cursor to   (cursorColumn, 0)
        lcd.print("Time now:");
    }

title: Automatic pet feeder with a simple menu type keypad

Answers: 0


body:
I tried the following code to communicate via SPI with MPU9250 and Mega2560 But I got the following error:
 **Error initializing communication with IMU**

Why I got this error?

```c
/*
* Brian R Taylor
* brian.taylor@bolderflight.com
*
* Copyright (c) 2021 Bolder Flight Systems Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the “Software”), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "mpu9250.h"

/* Mpu9250 object, SPI bus, CS on pin 10 */
bfs::Mpu9250 imu(&SPI, 10);

void setup() {
  /* Serial to display data */
  Serial.begin(115200);
  while(!Serial) {}
  /* Start the SPI bus */
  SPI.begin();
  /* Initialize and configure IMU */
  if (!imu.Begin()) {
    Serial.println("Error initializing communication with IMU");
    while(1) {}
  }
  /* Set the sample rate divider */
  if (!imu.ConfigSrd(19)) {
    Serial.println("Error configured SRD");
    while(1) {}
  }
}

void loop() {
  /* Check if data read */
  if (imu.Read()) {
    Serial.print(imu.new_imu_data());
    Serial.print("\t");
    Serial.print(imu.new_mag_data());
    Serial.print("\t");
    Serial.print(imu.accel_x_mps2());
    Serial.print("\t");
    Serial.print(imu.accel_y_mps2());
    Serial.print("\t");
    Serial.print(imu.accel_z_mps2());
    Serial.print("\t");
    Serial.print(imu.gyro_x_radps());
    Serial.print("\t");
    Serial.print(imu.gyro_y_radps());
    Serial.print("\t");
    Serial.print(imu.gyro_z_radps());
    Serial.print("\t");
    Serial.print(imu.mag_x_ut());
    Serial.print("\t");
    Serial.print(imu.mag_y_ut());
    Serial.print("\t");
    Serial.print(imu.mag_z_ut());
    Serial.print("\t");
    Serial.print(imu.die_temp_c());
    Serial.print("\n");
  }
}
```
Source code:

https://github.com/bolderflight/invensense-imu/blob/main/examples/arduino/mpu9250/spi/spi.ino

Connection:
```none
MPU9250                 Mega 2560
    GND <.............> GND
    3V3 <.............> 3.3V
    SCL <.............> pin 52
    SDA <.............> pin 51
SDC/SA0 <.............> pin 50
    CSB <.............> pin 53
```
This is the sensor ( IMU 10DOF SENSOR MODULE MPU9250 BMP280 ( GY-91 ))
But I only interested on the MODULE MPU9250 readings via SPI

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/tAMKo.jpg

title: Error with Mega2560 via SPI

Answers: 0


body:
When I try to comapre 2 `time_t` values I get unexplained behavour

    time_t t = 12345;
    time_t T = 67890;
    struct tm *tm = localtime(&t);
    struct tm *Tm = localtime(&T);

        char timeStamp[40];
        sprintf(timeStamp, "(1) d-d-d d:d:d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
        Serial.println(timeStamp);
        sprintf(timeStamp, "(2) d-d-d d:d:d", Tm->tm_year + 1900, Tm->tm_mon + 1, Tm->tm_mday, Tm->tm_hour, Tm->tm_min, Tm->tm_sec);
        Serial.println(timeStamp);

I get the exact same date.

When commenting out one of each set, I get the correct answer for each one.

Workaround I did was, but i'm sure there is an elegant way to overcome:

            time_t t = 12345;
            time_t T = 12345;
            struct tm *tm = localtime(&t);
            uint8_t now_month = tm->tm_mon;
            uint8_t now_day = tm->tm_mday;

            struct tm *Tm = localtime(&T);
            uint8_t save_month = Tm->tm_mon;
            uint8_t save_day = Tm->tm_mday;

            if (now_month == save_month && now_day == save_day)
            {
            }

title: localtime - executing one after the other- different time_t, but getting same results

Answers: 1

body:
From [the manual page of `localtime()`][man] (emphasis mine):
> The `asctime()`, `ctime()`, `gmtime()`, and `localtime()` functions
> shall return values in one of two static objects: a broken-down time
> structure and an array of type `char`. **Execution of any of the
> functions may overwrite the information returned in either of these
> objects by any of the other functions.**

As a solution, I suggest you take a copy of the `struct tm` used by
`localtime()` to store its result, rather than keeping a pointer to it:

```c++
struct tm tm = *localtime(&t);
struct tm Tm = *localtime(&T);
```

[man]: https://man7.org/linux/man-pages/man3/localtime.3p.html


body:
Everything in this code seems to work as expected except the subroutine `speedcw` at the bottom. It should change the `time_delay` variable.

```c++
#define ENA 2 //pin 2 on chip
#define in_A 0 //pin 0 on chip IN2
#define in_B 1 //pin 1 on chip IN1
#define in_C 3 //pin 3 on chip AUX
#define in_D 4 //pin 4 on chip AUX

byte PWM_PIN = 5;  //pin 5 on chip

int pwm_value = 1500;

int time_delay = 7;

void setup() {
    pinMode(ENA, OUTPUT);
    pinMode(in_A, OUTPUT);
    pinMode(in_B, OUTPUT);
    pinMode(in_C, OUTPUT);
    pinMode(in_D, OUTPUT);
    pinMode(PWM_PIN, INPUT);
}

void step1(){
    //A+,B+
    digitalWrite(in_A, 1);
    digitalWrite(in_B, 1);
    delay(time_delay);
}

void step2(){
    //A+,B-
    digitalWrite(in_A, 1);
    digitalWrite(in_B, 0);
    delay(time_delay);
}

void step3(){
    //A-,B-
    digitalWrite(in_A, 0);
    digitalWrite(in_B, 0);
    delay(time_delay);
}

void step4(){
    //A-,B+
    digitalWrite(in_A, 0);
    digitalWrite(in_B, 1);
    delay(time_delay);
}

void clockwise(long st){
    long i = 0;
    while( i < st ){
        //step1
        step1();
        //step2
        step2();
        //step3
        step3();
        //step4
        step4();
        i++;
    }
}

void counter_clockwise(long st){
    long i = 0;
    while( i < st ){
        //step1
        step4();
        //step4
        step3();
        //step3
        step2();
        //step2
        step1();
        i++;
    }
}

void loop() {
    pwm_value = pulseIn(PWM_PIN, HIGH);
    time_delay = 7;

    while (pwm_value <= 1450) {//red LED
        pwm_value = pulseIn(PWM_PIN, HIGH);
        digitalWrite(ENA, 1);
        //    digitalWrite(in_C, 1); //red LED
        //    digitalWrite(in_D, 0); //green LED
        // time_delay = 1;
        speedcw();
        clockwise(2);
    }

    while (pwm_value >= 1550) {//green LED
        pwm_value = pulseIn(PWM_PIN, HIGH);
        digitalWrite(ENA, 1);
        //    digitalWrite(in_C, 0); //red LED
        //    digitalWrite(in_D, 1); //green LED
        time_delay = 1;
        // speedccw();
        counter_clockwise(2);
    }

    while ((pwm_value >= 1451)&&(pwm_value <= 1549)) {
        pwm_value = pulseIn(PWM_PIN, HIGH);
        digitalWrite(ENA, 0);
        digitalWrite(in_C, 0);
        digitalWrite(in_D, 0);
    }
}

void speedcw(){
    if (pwm_value <= 900){
        time_delay = 1;
    }
    else if (pwm_value <= 1000){
        time_delay = 2;
    }
    else if (pwm_value <= 1100){
        time_delay = 3;
    }
    else if (pwm_value <= 1200){
        time_delay = 4;
    }
    else if (pwm_value <= 1300){
        time_delay = 5;
    }
    else if (pwm_value <= 1400){
        time_delay = 6;
    }
}

void speedccw(){
}
```

title: subroutine with if else does not work

Answers: 0


body:
I'm using `aedes` as my custom MQTT broker and `PubSubClient` at the ESP32 side, together with the `ArduinoJSON` package.

My server test code:

    import Aedes from "aedes";
    import net from "net";

    let port = process.env.MQTT_PORT || 1883; // MQTT Port

    const id = "MY_SERVER";

    const aedes = new Aedes({
        id: id,
    });

    aedes.on("client", async (client) => {
        console.log("Client conntected...");
    });

    aedes.on("subscribe", async (subscriptions, client) => {

        let topic = "cmd/" + client.id;

        let msg = {
            topic: topic,
            type: "test",
            param: "p1"
        };

        console.log("Sending command...")
        console.log(msg);

        this.aedes.publish(msg);

    });

    let server = net.createServer(aedes.handle, options);

    server.listen(port, () => {
        console.log(`Find the server at: mqtt://localhost:${port}/`);
    });

When running I'm getting:

    Client connected...
    Sending command...
    { topic: 'cmd/4CA9A712B42A', type: 'test', param: 'p1' }

At the client (ESP32) side I have my PubSubClient callback as follows:

    void callback(char *topic, byte *payload, unsigned int length)
    {
        Serial.println("Message received.....");

        StaticJsonDocument<256> doc;
        deserializeJson(doc, payload, length);

        char *command = doc["type"];
        char *param = doc["param"];

        Serial.println(command);
        Serial.println(param);
    }

The callback is being called property after subscription - but I'm not being able to parse the payload:

    Message received.....
    <empty line>
    <empty line>

How can I fix the server or client to allow then to send/parse correctly the payload.

title: Empty message parse using ArduinoJSON from aedes MQTT server

Answers: 0


body:
I have a 3.5" TFT LCD communicating in parallel connected to Arduino UNO.

I expect it draws a white circle on a black background but all it does is to show a white screen.

How to fix this?

main.c
```
// sudo apt-get install avr-libc gcc-avr binutils-avr gdb-avr avrdude
// avr-gcc -mmcu=atmega328p -Wall -Os -o main.elf main.c
// avr-objcopy -O ihex main.elf main.hex
// avrdude -c arduino -p m328p -P /dev/ttyUSB0 -b 115200 -U flash:w:main.hex

#define DDRA (*(volatile uint8_t*)0x24)
#define DDRB (*(volatile uint8_t*)0x25)
#define DDRC (*(volatile uint8_t*)0x26)
#define DDRD (*(volatile uint8_t*)0x27)

#define PORTA *((volatile uint8_t*)0x3B)
#define PORTB *((volatile uint8_t*)0x38)
#define PORTC *((volatile uint8_t*)0x35)
#define PORTD *((volatile uint8_t*)0x32)

typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;

typedef signed char int8_t;
typedef signed int int16_t;
typedef signed long int32_t;

#define F_CPU 16000000UL

#define LCD_RD A0
#define LCD_WR A1
#define LCD_RS A2
#define LCD_CS A3
#define LCD_RST A4

#define LCD_WIDTH 320
#define LCD_HEIGHT 480

#define LCD_DATA_PORT PORTD
#define LCD_DATA_DDR DDRD

#define LCD_RD_PORT PORTC
#define LCD_RD_DDR DDRC
#define LCD_RD_PIN 0

#define LCD_WR_PORT PORTC
#define LCD_WR_DDR DDRC
#define LCD_WR_PIN 1

#define LCD_RS_PORT PORTC
#define LCD_RS_DDR DDRC
#define LCD_RS_PIN 2

#define LCD_CS_PORT PORTC
#define LCD_CS_DDR DDRC
#define LCD_CS_PIN 3

#define LCD_RST_PORT PORTC
#define LCD_RST_DDR DDRC
#define LCD_RST_PIN 4

#define LCD_DATA_MASK 0b11111111

void delay_ms(uint16_t ms) {
    // calculate the number of cycles needed for the given number of milliseconds
    uint16_t cycles = F_CPU / 1000UL * ms / 4;
    // use a volatile variable to prevent the compiler from optimizing the loop away
    volatile uint16_t count = cycles;
    // loop until the counter reaches zero
    while (count > 0) {
        count--;
    }
}

void writeCommand(uint8_t command) {
    LCD_RS_PORT &= ~(1 << LCD_RS_PIN); // set RS pin to low for command
    LCD_CS_PORT &= ~(1 << LCD_CS_PIN); // enable chip select
    LCD_WR_PORT &= ~(1 << LCD_WR_PIN); // enable write
    LCD_DATA_PORT = command; // write the command to the data port
    asm volatile("nop"); // wait for stability
    LCD_WR_PORT |= (1 << LCD_WR_PIN); // disable write
    LCD_CS_PORT |= (1 << LCD_CS_PIN); // disable chip select
}

void writeData(uint8_t data) {
    LCD_RS_PORT |= (1 << LCD_RS_PIN); // set RS pin to high for data
    LCD_CS_PORT &= ~(1 << LCD_CS_PIN); // enable chip select
    LCD_WR_PORT &= ~(1 << LCD_WR_PIN); // enable write
    LCD_DATA_PORT = data; // write the data to the data port
    asm volatile("nop"); // wait for stability
    LCD_WR_PORT |= (1 << LCD_WR_PIN); // disable write
    LCD_CS_PORT |= (1 << LCD_CS_PIN); // disable chip select
}

void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    writeCommand(0x2A);
    writeData(x0 >> 8);
    writeData(x0);
    writeData(x1 >> 8);
    writeData(x1);

    writeCommand(0x2B);
    writeData(y0 >> 8);
    writeData(y0);
    writeData(y1 >> 8);
    writeData(y1);

    writeCommand(0x2C);
}

void fillScreen(uint16_t color) {
    setAddrWindow(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1);
    for (uint32_t i = 0; i < (uint32_t)LCD_WIDTH * LCD_HEIGHT; i++) {
        writeData(color >> 8);
        writeData(color);
    }
}

void initILI9488() {
    LCD_DATA_DDR = LCD_DATA_MASK;
    LCD_RD_DDR |= (1 << LCD_RD_PIN);
    LCD_WR_DDR |= (1 << LCD_WR_PIN);
    LCD_RS_DDR |= (1 << LCD_RS_PIN);
    LCD_CS_DDR |= (1 << LCD_CS_PIN);
    LCD_RST_DDR |= (1 << LCD_RST_PIN);

    LCD_RD_PORT |= (1 << LCD_RD_PIN);
    LCD_WR_PORT |= (1 << LCD_WR_PIN);
    LCD_RS_PORT |= (1 << LCD_RS_PIN);
    LCD_CS_PORT |= (1 << LCD_CS_PIN);
    LCD_RST_PORT |= (1 << LCD_RST_PIN);
    delay_ms(100);

    writeCommand(0x01); // Software reset
    delay_ms(100);

    writeCommand(0x11); // Sleep out
    delay_ms(100);

    writeCommand(0x3A); // Pixel format set
    writeData(0x55); // 16-bit color

    writeCommand(0x36); // Memory access control
    writeData(0x48); // BGR, horizontal flip

    writeCommand(0x2A); // Column address set
    writeData(0x00);
    writeData(0x00);
    writeData(0x01);
    writeData(0x3F);

    writeCommand(0x2B); // Page address set
    writeData(0x00);
    writeData(0x00);
    writeData(0x01);
    writeData(0xDF);

    writeCommand(0xB0); // Power control
    writeData(0x00);
    writeData(0x1B);
    writeData(0x14);

    writeCommand(0xB1); // Vcom control
    writeData(0x08);
    writeData(0x08);
    writeData(0x08);

    writeCommand(0xB4); // Display inversion control
    writeData(0x07);

    writeData(0x01);
    writeData(0xE0);

    writeCommand(0xC0); // Power control 1
    writeData(0x10);
    writeData(0x10);

    writeCommand(0xC1); // Power control 2
    writeData(0x41);

    writeCommand(0xC5); // VCOM control
    writeData(0x00);
    writeData(0x18);

    writeCommand(0xD0); // Power control 3
    writeData(0x07);
    writeData(0x07);

    writeCommand(0xD1); // Power control 4
    writeData(0x00);
    writeData(0x0E);

    writeCommand(0xD2); // Power control 5
    writeData(0x01);
    writeData(0x02);

    writeCommand(0xE9); // Set image function
    writeData(0x01);

    writeCommand(0x13); // Normal display mode on
    writeCommand(0x29); // Display on
}

#define PI 3.14159265

void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
  int16_t x = 0, y = r;
  int16_t d = 3 - 2 * r;

  while (x <= y) {
    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    if (d < 0) {
        d += 4 * x + 6;
    } else {
        d += 4 * (x - y) + 10;
        y--;
    }
    x++;

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    writeData(color >> 8);
    writeData(color);

    setAddrWindow(x0 - x, y0 - y, x0 + x, y0 + y);

    if (x != y) {
        setAddrWindow(x0 - y, y0 - x, x0 + y, y0 + x);
    }
  }
}

int main() {
    initILI9488();
    while(1)
    {
        fillScreen(0x0000); // Clear screen with black color
        drawCircle(LCD_WIDTH / 2, LCD_HEIGHT / 2, 50, 0xFFFF); // Draw white circle at the center of the screen
        delay_ms(5000); // Wait for 5 seconds
    }
    return 0;
}

```

Connections:
```
ILI9488 VCC <----> 3.3V
ILI9488 GND <----> GND
ILI9488 SD_SS <----> Arduino pin 10
ILI9488 SD_DI <----> Arduino pin 11
ILI9488 SD_DO <----> Arduino pin 12
ILI9488 SD_SCK <----> Arduino pin 13
ILI9488 RESET <----> e.g., pin 5
ILI9488 D0 <----> Arduino pin 8
ILI9488 D1 <----> Arduino pin 9
ILI9488 D2 <----> Arduino pin 2
ILI9488 D3 <----> Arduino pin 3
ILI9488 D4 <----> Arduino pin 4
ILI9488 D5 <----> Arduino pin 5
ILI9488 D6 <----> Arduino pin 6
ILI9488 D7 <----> Arduino pin 7
ILI9488 LCD_RD <----> Arduino pin A0
ILI9488 LCD_WR <----> Arduino pin A1
ILI9488 LCD_RS <----> Arduino pin A2
ILI9488 LCD_CS <----> Arduino pin A3
ILI9488 LCD_RST <----> Arduino pin A4
```

Photos:

[![enter image description here][1]][1]
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/BJFDt.jpg
  [2]: https://i.stack.imgur.com/n9dSZ.jpg

title: TFT Screen with Arduino UNO does not display as expected

Answers: 0


body:
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**

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

 2. 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))`

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

title: Difference between (*(volatile unsigned int *) and (volatile unsigned int)?

Answers: 2

body:
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.

body:
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?


body:
    #include <IRremote.h>
    #include <Adafruit_NeoPixel.h>

    #define LED_PIN 7 // define the LED strip data pin
    #define LED_COUNT 150 // define the number of LEDs in the strip

    Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

    int RECV_PIN = 2; // define the IR receiver pin

    IRrecv irrecv(RECV_PIN);

    int brightness = 100;

    void setup() {
     Serial.begin(9600); // initialize serial communication
    strip.begin(); // initialize LED strip
    strip.show(); // turn off all LEDs
    irrecv.enableIRIn(); // start the receiver
    }

    void loop() {
    case 0xE916FF00: // 0
        Serial.println("0");

          for (int i = 0; i<LED_COUNT; i++) {
          strip.setPixelColor(i, 0, 0, 0); // set all LEDs to off
          strip.show(); // turn off all LEDs
          Serial.println(irrecv.decodedIRData.decodedRawData);
          }

        break;
      case 0xF30CFF00: // 1
        Serial.println("1");

          for (int i = 0; i<LED_COUNT; i++) {
          strip.setPixelColor(i, 255, 255, 255); // set all LEDs to white
          strip.setBrightness(brightness); // set maximum brightness
          strip.show(); // display the color on the LED strip
          }

        break;
      case 0xE718FF00: // 2
        Serial.println("2");
        while (true) {

          for (int i = 0; i < LED_COUNT; i++) {
            strip.setPixelColor(i, random(256), random(256), random(256));
          }
          strip.show();
           delay(1000);
           if(irrecv.decode()){
             break;
           }

        }
        break;

      default:
        break;
    }
    irrecv.resume(); // receive the next code
      }
    }

I have trouble to get out of the loop after i press button 3. When button 1 or 0 is pressed everything works perfectly but when i tried to add animation to my led strip (randomly changing colors) it stops to recieving. I dont know what to do.
I expect that after i press button 3 on my controller LED strip will be continously changing colors until another button is pressed (In my case button 0 or 1)
Can someone help me please?

title: How to change between loops? IR Remote + led strip

Answers: 0


body:
i need to wake up my ESP every 60 min to read some data and post it to server, all process working fine when i use numbers of minute below 60 (converted in microsecond x 1000000) but when i use 60 min above i get the following message:

> src/main.cpp:137:49: warning: integer overflow in expression of type 'int' results in '-694967296' [-Woverflow]
     esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);// set up next wake up after 30 sec

How can i make my ESP wake up every 60 min or above?

simplify code:

```
// for awake and sleep
#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  60 // minute

void setup(){
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 60 * uS_TO_S_FACTOR);// error if time to sleep more than 60 min
}

```

Answers: 1

body:
Change that line to:

    esp_sleep_enable_timer_wakeup((uint64_t) TIME_TO_SLEEP * 60 * uS_TO_S_FACTOR);

That forces the compiler to do 64-bit arithmetic on the constant rather than defaulting to "int" arithmetic.


body:
I have a project that needs 3 serial ports on my ESP32 Dev 38-pin MCU. Two of them are for Nextion touch displays and the other is for a GPS. The problem from what I understand is that the ESP32 has 3 hardware serial ports of which only 2 can be used. GPIO 1 and 3 can not be connected to the display during upload and the software serial that is in Arduino IDE 2.0.4 is not compatible with an ESP32.
Can anyone tell me how I can use 3 serial ports?

Thanks

title: Need ESP32 to use 3 Serial Ports

Answers: 1

body: Welcome Richard, your question is interesting and a common problem in the Arduino arena. I simply use a SPI or I2C board that outputs RS232. I stumbled across them a few years back and used several, they worked great. I do not remember what they were called but here is a link to one of the many that are available: "https://andino.systems/extensions/rs232"This was the first search term I used: arduino SPI to RS232 module". Here is another link for the Pi: "https://forums.raspberrypi.com//viewtopic.php?t=146908&p=1083915#p1024636"


body: It's the Arduino Uno. I've spent hours reading on the internet but found nothing yet. If you use a label in the macro, the 2nd time it's called you get a duplicate label error.

title: Arduino IDE. How do I use labels in a macro?

Answers: 2

body:
Welcome, this is the same thing I had problems a few years back. Define the label in the `macro` (function) and it will be local and not available to the rest of the world. You can use the same label as many times as you want they just need to be inside a `macro`.

    void macro(int label)
    {
       Do something with label and then exit;
    }

You can do whatever you want, say get the value of several pins to see if they are all on then use the return true or false. When you leave the macro all of the variables will be lost and the memory returned to the heap. This is done in several ways in many of the libraries.

body:
Just to make the question clearer, let's take a simple example. Consider
the following assembly macro that implements a delay loop:

```lisp
.macro short_delay
    clr  r0
repeat:
    dec  r0
    brne repeat
.endm
```

and use it in a program that repeatedly blinks the built-in LED of an
Arduino Uno (a faster version of “Blink”):

```lisp
main:
    sbi  DDRB, PB5   ; set pin 13 = PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    short_delay
    cbi  PORTB, PB5  ; turn PB5 LOW
    short_delay
    rjmp loop
```

When the assembler expands the macro, it ends up with this:

```lisp
main:
    sbi  DDRB, PB5   ; set PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    cbi  PORTB, PB5  ; turn PB5 LOW
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    rjmp loop
```

and this fails with

```text
Error: symbol `repeat' is already defined
```

The solution to this problem is to use, inside the macro, only [local
labels][ll]. These labels are just numbers. When using them, one has to
append the suffix “b” (for backwards) or “f” (forwards) depending on
whether the label is defined before or after the point where it is being
referenced.

The nice thing about local labels is that they are... well... local, and
thus they can be safely reused many times. The assembler disambiguates
them by choosing the definition that is _closer_ to the point of use,
along the specified direction. With a local label (I choose `0`), the
delay macro becomes:

```lisp
.macro short_delay
    clr  r0
0:  dec  r0
    brne 0b  ; the branch target is the preceding label `0'
.endm
```

When the macro is expanded, the main program becomes:

```lisp
main:
    sbi  DDRB, PB5   ; set PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    clr  r0
0:  dec  r0
    brne 0b
    cbi  PORTB, PB5  ; turn PB5 LOW
    clr  r0
0:  dec  r0
    brne 0b
    rjmp loop
```

Although repeated, the label is not ambiguous, as `brne 0b` always
refers to the _closest_ label `0` along the **b**ackwards direction.

[ll]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels-1


body:
I am building a remote controlled boat. My remote project freezes after an arbitrary amount of time. The serial stops output, the OLED doesn't update anymore and instructions are not send / received anymore.

For the life of me I cannot figure out why my project freezes. Using an Arduino Nano.

I have tried the following:

- Keep memory small
- Disable Serial as not to overflood
- Not use any risky variables; like String
- Determine if a specific circumstance causes the hang (X amount of time, certain instructions, losing radio connection, etc)
- Replace the Arduino
- Replace the power supply
- Replace the power supply cable
- Put the radio into debug mode, it becomes slow and nothing interesting shows on serial

Please provide help to allow me to continue my two-year long project. My gratitude for any pointers or help is unending.

The Arduino is connected to a NRF24L01 with adapter board, an OLED and two potentiometers.

This is my code:

```
#include <SPI.h>
#include "printf.h"
#include "RF24.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
#include <DifferentialSteering.h>

// Debugging mode:
int debugging_serial = 0;
int debugging_delay = 0;
int debugging_verbose = 0;

// Timers init;
unsigned long start_timer = 0;
unsigned long end_timer = 0;

// Oled state for clearing
int oledstate = 0;

// Create nRF24L01 transceiver using pins 9 and 10.
RF24 radio(9, 10);

// OLED init
#define I2C_ADDRESS 0x3C // 0X3C+SA0 - 0x3C or 0x3D
#define RST_PIN -1 // Define proper RST_PIN if required.
SSD1306AsciiAvrI2c oled;

// Set potentio meter pins
int pot_one_pin = A0;
int pot_two_pin = A1;

// Set Diff Steering
DifferentialSteering DiffSteer;

// Register two radio addresses to use for communication.
uint8_t address[][6] = { "1Node", "2Node" };

// Define sending and receiving payload structs. Note: these should be inversed on remote vs boat code
// DEFINE WHAT WE WILL BE SENDING
struct SendingPayloadObject
{
  // We are sending two numbers
  uint8_t Motor1Speed;
  uint8_t Motor2Speed;
};
// Also create the payload object to prepare and load with defaults in setup
SendingPayloadObject payload;

// DEFINE WHAT WE WILL BE RECEIVING
struct ReceivingPayloadObject
{
  // We are sending a message and a number
  char message[7];  // only using 6 characters for TX & ACK payloads
  uint8_t counter; // struct counter variable as example
};

void setup()
{
  if(debugging_serial)
  {
    Serial.begin(115200);
    Serial.println("Remote Code Started!");
  }

  // Oled setup
  // Call oled.setI2cClock(frequency) to change from the default frequency.
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
  //oled.setFont(System5x7);
  oled.clear();
  oled.println("Boat Remote Started!");
  oled.clear();

  // Check if radio works
  if (!radio.begin())
  {
    if(debugging_serial)
    {
      Serial.println(F("Radio hardware is not responding!"));
    }

    while (1) {}  // hold
  }

  // Set the PA Level low to try preventing power supply related problems
  // because these examples are likely run with nodes in close proximity to
  // each other. (RF24_PA_MAX is default)
  radio.setPALevel(RF24_PA_LOW);

  // To use ACK payloads, we need to enable dynamic payload lengths (for all nodes). ACK payloads are dynamically sized
  radio.enableDynamicPayloads();

  // Acknowledgement packets have no payloads by default. We need to enable this feature for all nodes (TX & RX) to use ACK payloads.
  radio.enableAckPayload();

  // Set the TX address of the RX node into the TX pipe and the opposite to the RX pipe. The remote radio address is 1!
  radio.openWritingPipe(address[1]);
  radio.openReadingPipe(1, address[0]);

  // Sender role code
  // Set payload defaults and put radio in send (TX) mode
  payload.Motor1Speed = 0;  // set the payload payloadMotor1Speed
  payload.Motor2Speed = 0;  // set the payload payloadMotor1Speed
  radio.stopListening();                 // put radio in TX mode

  if(debugging_verbose)
  {
    printf_begin();             // needed only once for printing details
    radio.printDetails();       // (smaller) function that prints raw register values
    radio.printPrettyDetails(); // (larger) function that prints human readable data
  }

  // DiffSteer init
  DiffSteer.begin(0);
}

void loop()
{
  //// REMOTE CONTROL STUFF:

  // NEW LOGIC FOR MANEURVERING
  int motorSpeed1 = 0;
  int motorSpeed2 = 0;

  // Steering using potentiometers
  int steering_pot_value = map(analogRead(pot_two_pin), 0, 1023, -127, 127);
  int power_pot_value = map(analogRead(pot_one_pin), 0, 1023, 0, 127);

  // Go Straight when steering almost straight
  if(steering_pot_value <= 15 && steering_pot_value >= -15)
  {
    steering_pot_value = 0;
  }

  // Compute differential steering
  DiffSteer.computeMotors(steering_pot_value, power_pot_value);

  // map motor outputs to needed range
  motorSpeed1 = map(DiffSteer.computedLeftMotor(), 0, 127, 0, 255);
  motorSpeed2 = map(DiffSteer.computedRightMotor(), 0, 127, 0, 255);

  // Corrective measures for smoother steering
  // Fix division by 0, full power when pot completley off
  if(power_pot_value <= 1) { motorSpeed1 = 0; motorSpeed2 = 0; };

  // OLED motor control code (for testing)
  //  Speeds directley from pot meters
  //  motorSpeed1 = map(analogRead(pot_one_pin), 0, 1023, 0, 255);
  //  motorSpeed2 = map(analogRead(pot_two_pin), 0, 1023, 0, 255);
  //

  // Set motor speeds in payload
  payload.Motor1Speed = motorSpeed1;
  payload.Motor2Speed = motorSpeed2;

  //// RADIO STUFF:

  // Let's time the tranmission for maagd / nerd purposes
  if(debugging_serial)
  {
     start_timer = micros();                  // start the timer
  }

  // Send over radio TX;
  bool report = radio.write(&payload, sizeof(payload));  // transmit & save the report

  if(debugging_serial)
  {
    end_timer = micros();                    // end the timer
  }

  if (report)
  {
    if(debugging_serial)
    {
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // print the timer result
      Serial.print(F(" us. Sent (Motor 1 Speed: "));
      Serial.print(payload.Motor1Speed);
      Serial.print(F(" , Motor 2 Speed: "));
      Serial.print(payload.Motor2Speed);
      Serial.print(F(")"));
    }

    // Define the pipe
    uint8_t pipe;

    if (radio.available(&pipe))
    {
      if (oledstate != 1) { oled.clear(); }; oledstate = 1;
      oled.set1X();
      oled.setFont(System5x7);
      oled.setCursor(0 , 0);
      oled.print("Transmission OK \n");
      oled.setCursor(0 , 30);
      oled.print("Motors L:");
      // Add leading zeroes to get true values (otherwise old number remains)
      if(payload.Motor1Speed < 100 && payload.Motor1Speed >= 10) { oled.print("0"); };
      if(payload.Motor1Speed < 10) { oled.print("00"); };
      oled.print(payload.Motor1Speed);
      oled.setCursor(80 , 30);
      oled.print("R:");
      if(payload.Motor2Speed < 100 && payload.Motor2Speed >= 10) { oled.print("0"); };
      if(payload.Motor2Speed < 10) { oled.print("00"); };
      oled.print(payload.Motor2Speed);

      // is there an ACK payload? grab the pipe number that received it
      ReceivingPayloadObject received;
      radio.read(&received, sizeof(received));  // get incoming ACK payload

      if(debugging_serial)
      {
        Serial.print(F(" Recieved "));
        Serial.print(radio.getDynamicPayloadSize());  // print incoming payload size
        Serial.print(F(" bytes on pipe "));
        Serial.print(pipe);  // print pipe number that received the ACK
        Serial.print(F(": "));
        Serial.print(received.message);    // print incoming message
        Serial.println(received.counter);  // print incoming counter
      }
    }
    else
    {
      if (oledstate != 2) { oled.clear(); }; oledstate = 2;
      oled.set1X();
      oled.setCursor(0, 0);
      oled.setFont(System5x7);
      oled.print("Transmission: \n \n");
      oled.setCursor(0, 80);
      oled.set2X();
      oled.print("No Reply (empty ACK)");

      if(debugging_serial)
      {
        Serial.println(F(" Recieved: an empty ACK packet"));
      }
    }
  }
  else
  {
    if (oledstate != 3) { oled.clear(); }; oledstate = 3;
    oled.set1X();
    oled.setCursor(0, 0);
    oled.setFont(System5x7);
    oled.print("Transmission: \n \n");
    oled.setCursor(0, 80);
    oled.set2X();
    oled.print("Failed");

    if(debugging_serial)
    {
      Serial.println(F("Transmission failed or timed out"));
    }
  }

  // Add a delay while programming for reading purposes
  if(debugging_verbose)
  {
    delay(10000);
  }
  else
  {
    if(debugging_delay)
    {
      delay(1000);
    }
  }
}

title: Arduino hangs / freezes - can't figure out why

Answers: 1

body:
A basic rule of debugging complex problems is to simplify the configuration until you get to a working baseline, and then build back up from there, one chunk at a time.

I would start with the simplest possible setup with a single RF transceiver at each end. No other peripherals, no other code; something that simply sends "hello" back and forth at wide spaced intervals - like once per second, to make sure there's no way the RF channel will be overloaded.

Once you get to a baseline where your test configuration will run indefinitely, then start adding code and/or peripherals, one at time, with a long-duration test at each step.  Eventually you will reach a point where the system becomes intermittent; when this happens, back up one step to confirm proper operation, and then repeat this forward/back step until you are convinced that this is the step that produces the errant behavior.

Then divide the last step (the one that produces the bad behavior) into smaller steps, and find out which one of those steps produces the bad behavior, and eventually you will get down to one line of code, or one particular peripheral that causes the problem, and in all likelihood it will be something where you will say "OH! I should have thought of that long ago!".

Just as a last thought - you mentioned the 'if radio.availible()' function as a possible culprit.  You could start the process by, for instance, modifying the library code (you can do this - it's just another bit of Arduino code) so that it simply returns 'true' (or false - doesn't matter) every time it is called. If your system operates OK with this setup, but doesn't operate OK with the original library code, then that may well be the source of the problem.

Looking at the RF24.cpp, I see that available() calls get_status(), so maybe it is get_status() that is hanging up.

Just some thoughts,

Frank