text:
TFT Screen with Arduino UNO does not display as expected
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:

Which development environment are you using and did you get any compiler warnings, say duplicate definitions etc. ?

I use linux avr-gcc with no error/warning. The commands I used are the first few lines of the comment.

It may not help you much but for that board and screen I would have used the Arduino development environment and the MCUFRIEND_kbv library.

@6v6gt, is it serial or parallel?

This https://github.com/prenticedavid/MCUFRIEND_kbv appears to support screens based on the ILI9488 controller and some controllers with an 8bit parallel interface so you may be lucky.

@6v6gt, As far as I understand SPI means the communication is serial. Are you talking about any particular example?

Yes. SPI is serial and is used at least for the SD card reader on that board and possibly any touch screen controller (although your screen does not appear to support touch control). The display controller appears to have a parallel interface. Your screen picture appears similar to one appearing in this thread: https://forum.arduino.cc/t/3-5-tft-lcd-from-mcufriend-for-arduino-uno-320x480-ili9327/339132 . I assumed from your code that you had already identified the controller type as ILI9488. Did you get this information from the supplier?

@6v6gt, tried that library but it has issues. I have this problem. fatal error: ADA_GFX_kbv.h: No such file or directory.

It says this explicitly: ADA_GFX_kbv.h only gets used by non-Arduino projects. e.g. MBED or Keil. You are not using the Arduino development environment or are you now ? You can find that file here: https://github.com/prenticedavid/MCUFRIEND_kbv/tree/master/extras/unused. The author of that repository is very active in the display section of the Arduino.cc  forum so you may get more specific help there. I can't contribute much more here.


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

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

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

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

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

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

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

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

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

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

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

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

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

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

source: Stack Exchange

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

sort: votes


text:
How to change between loops? IR Remote + led strip
#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?

you don't have any code for button 3 ... this is a question and answer site ... just ask a question that you would like answered ... Can someone help me please? is not a question about the problem ... besides, what is the point of asking a question that always has a yes answer

your code is missing parts... please read https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

@jsotola so could you please help me? What is wrong in my code? Yeah i made a mistake it's button 2 not a button 3.

Basically I need to jump off the loop after I press another button on IR controller and I can't figure it out.

I told you what's wrong with your code on Mar 8 ... it's button 2 not a button 3 ... don't explain in a comment, edit your question and make the correction there ... When button 1 or 0 is pressed everything works perfectly ... how can it work perfectly when the code does not even compile without an error?

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


text:
integer overflow in expression of type 'int' results
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
}

More or less the same question here. On the ESP32 the long  and int types have the same range.

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.


text:
Need ESP32 to use 3 serial ports
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.

use ota to upload sketches, it's faster, safer,  and more flexible anyway. you can also use a software serial, mos def.

It's easy to remap any of the ESP32 serial port pins to other pins, so you're not bound to the standard pinout.

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"

Not a full answer, but, depending on your GPS model, you might be able to use I2C instead.

Yes it is possible to assign any GPIO pins to serial using HardwareSerial library for up to 3 UART Connections. See this link for reference: https://copperhilltech.com/blog/esp32-programming-three-serial-ports-uarts-using-the-arduino-ide/
I'm playing with 2 nextions and esp32 also. would be great to chat with you and brainstorm

    #define UART1_ODU_BAUD_RATE 2400
    #define U1RXD 32
    #define U1TXD 33

Use this for UART Init in the setup
    // UART1 Configuration
      uart_config_t Configurazione_UART1 = {
        .baud_rate = UART1_ODU_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_EVEN,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
      };
      uart_param_config(NUMERO_PORTA_SERIALE, &Configurazione_UART1);
      esp_log_level_set(TAG, ESP_LOG_INFO);
      uart_set_pin(NUMERO_PORTA_SERIALE, U1TXD, U1RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
      uart_driver_install(NUMERO_PORTA_SERIALE, BUF_SIZE, BUF_SIZE, 20, &uart1_queue, 0);
      xTaskCreate(UART_ISR_ROUTINE, "UART_ISR_ROUTINE", 2048, NULL, 12, NULL);
      //vTaskDelete(NULL);

Create a ISR function
    static void UART_ISR_ROUTINE(void *pvParameters)                //uart1
    {
      uart_event_t event;
      size_t buffered_size;
      bool exit_condition = false;
      String ODU_PAC_ONE_Temp = "";

      ODU_PAC_ONE = "";

      while (1) {
        if (xQueueReceive(uart1_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
          if (event.type == UART_DATA) {
            uint8_t UART1_data[128];
            int UART1_data_length = 0;
            ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_1, (size_t*)&UART1_data_length));
            UART1_data_length = uart_read_bytes(UART_NUM_1, UART1_data, UART1_data_length, 100);

            for (byte i = 0; i < UART1_data_length; i++) {
                ODU_PAC_ONE_Temp += (int) UART1_data[i];
            }
          }
          else if (event.type == UART_FRAME_ERR) {

          }
        }
        if (exit_condition) {
          break;
        }
      }
      vTaskDelete(NULL);
    }

You will get your data in here (int) UART1_data[i]

This answer might benefit from a bit of explanation. In what way is this better than a simple port remap?


text:
Arduino IDE. How do I use labels in a macro?
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.

Please provide your code and the exact error message and describe what you are trying to achieve

I suggest only using local lables in assembly macros.

Its the aduino uno ... no it's not ... the problem you describe has nothing to do with the type of arduino

Many thanks Edgar Bonet. Local labels is exactly what I  was looking for.

Just to make the question clearer, let's take a simple example. Consider
the following assembly macro that implements a delay loop:
.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”):
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:
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
Error: symbol `repeat' is already defined

The solution to this problem is to use, inside the macro, only local
labels. 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:
.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:
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 backwards direction.

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.

The question is about the use of labels in assembly macros, not about the use of variables in C++ functions.


text:
Arduino hangs / freezes - can't figure out why
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);
    }
  }
}

Maybe add to your post the RAM/storage usage statistics which the compiler provides at the end of the output. Also say what board it is.

where does the program hang?

Approaching the problem from another angle, why not use a watchdog to reboot the Arduino when it hangs.

Thanks for your replies! I dont have the usage number at hand, but it was very low. Maybe 30%. Using a Nano. The program hangs somewhere in if radio.availible as far as I can determine. A watchdog is not a great solution as it would render the boat inoperable for some seconds. Looking forward to more thoughts and advice!

You appear to have used a relatively complex nrf24l01 code base for your project which originally supported role swapping between the "transmitter" and "receiver" parts. If you have a single transmitter and a single receiver then a simpler example, also handling ack packets, can be found here: https://forum.arduino.cc/t/simple-nrf24l01-2-4ghz-transceiver-demo/405123/3 .
If you don't use your debugging options, the transmitter is likely to flood the receiver because there is otherwise no pause in the loop().

Thank you for your reply. Can you eloborate a bit on the last part? Why would I want a pause, since I aim to keep control instant and snappy? How would I confirm and prevent a flood event? Can it be set up more like UDP than TCP - speaking in networking terms? @6v6gt

The  receiver will take a finite amount of time to respond to the transmitter. There are also unpredictable effects like retransmissions of either the payload or the acknowledgement affecting the round trip time. You can bring this under some control with the setRetries() method. I guess that at least a 50ms or so pause at the end of the loop would be good but that depends also on what the receiver is doing after the ack is sent. The protocol for handling clean end to end transmission of the data is proprietry "Shock Burst". The options are here: https://nrf24.github.io/RF24/classRF24.html

It would be much easier to help you if we knew what you have. Post an annotated schematic showing exactly how you have wired it including all connections, power, ground and power sources.

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


text:
Where does this sketch have Undefined Behavior?
Simple sketch and simple question: where does this sketch have undefined behavior?
Note: I don't need a solution to fix the code. I already have code that works. I really need to understand where my thinking is wrong.
Background: some kids were writing a program for a line follower robot which has 3 digital sensors. Many of them bricked their Arduino. I reduced the affected sketches to quite a minimum so that it still reproduces the problem. The sketch is pretty self-explanatory I hope.
It gives no warnings in Arduino IDE 1.8.9, 1.8.15 and 2.0.4 even with all warnings enabled.
Still, this code bricks all the Arduino clones (9 instances of Elegoo Smart Robot Car Kit 3.0 Plus) and I spent several hours to find a reliable procedure to unbrick them. Therefore I have strong belief that this code must have undefined behavior - except that I can't see it.
The unbrick procedure is:

Remove the shield, if not removed yet
Disconnect Arduino from USB
Connect Arduino to USB
Press Reset button on the Arduino board
Disconnect Arduino from USB again (!)
Connect Arduino to USB
Compile and upload an empty sketch

long PIN_LINE_LEFT = 10;
long PIN_LINE_MID = 4;
long PIN_LINE_RIGHT = 2;
long DATARATE = 115200;

void setup() {
  pinMode(PIN_LINE_LEFT, INPUT);
  pinMode(PIN_LINE_MID, INPUT);
  pinMode(PIN_LINE_RIGHT, INPUT);
  Serial.begin(DATARATE);
}

void loop() {
  byte leftValue = digitalRead(PIN_LINE_LEFT);
  Serial.println(leftValue);
}

Here's my analysis:
IMHO, the sketch is unusual just in one way: instead of #defineing the pin numbers and other stuff, it declares them as global variables of type long.
According to the Arduino reference about data types a long is 32 bit. Printing sizeof(long) confirms that. Therefore, 115200 will not overflow at 65536 (16 Bit).
For Serial.begin(), the DATARATE will be converted into an unsigned long, which IMHO should not be a problem here, since the number is positive.
Sure enough, the pin numbers needn't be long and should be declared as uint8_t to better match the pinMode() and digitalRead() function. But I still think the implicit conversion down to uint8_t should be fine, since there is no overflow either.
Next, digitalRead() officially returns an int. The result is assigned to a byte which is an alias for uint8_t. It seems that this also gets converted implicitly. However, the values should only be HIGH or LOW, i.e. 1 or 0, which does not generate a signed overflow either.
What I tried:
Changing DATARATE to the more appropriate unsigned long DATARATE = 115200UL; doesn't change anything.
Changing byte leftValue = digitalRead(PIN_LINE_LEFT); to the more appropriate int leftValue = digitalRead(PIN_LINE_LEFT); also didn't change anything.
Changing long PIN_LINE_MID = 4; and all others to the more appropriate uint8_t PIN_LINE_xxx = xxx; also doesn't change anything.
IMHO with these changes, there's basically nothing left to fix and this should be a super valid C/C++ program without any implicit dangerous casts.
A Serial.flush(); in the loop is not needed according to the documentation of Serial.write(). So there will not be a buffer overflow.

Comments have been moved to chat; please do not continue the discussion here. Before posting a comment below this one, please review the purposes of comments. Comments that do not request clarification or suggest improvements usually belong as an answer, on [meta], or in [chat]. Comments continuing discussion may be removed.

Your sketch does not have undefined behaviour. It works:

I already have code that works.

Your problem apparently is that after loading this sketch you have trouble uploading a new sketch:

this code bricks all the Arduino clones

They aren't "bricked" as you say:

But your method works in ~9 out of 10 cases. I can't believe this.

Your sketch, which outputs repeatedly to the serial port, apparently makes it hard for a clone to respond to a new upload. The cheaper USB interface which the clones use, to save a few cents, evidently don't react as well as the genuine Arduino to attempts to upload a new sketch.
The suggested method in the comments (referencing my post Have I bricked my Arduino Uno? Problems with uploading to board) indicates the solution, and I quote:

Take these steps:

Power off the board completely (remove the USB cable).
Hold down the Reset button, and keep it held down (or, run a jumper wire from the RESET pin to the GND pin). This stops the problem sketch from starting, and thus activating the watchdog timer
Still holding down Reset, reconnect the USB cable.
Start uploading a sketch that does not have this problem (eg. Blink)
Once the IDE reports "Uploading" release the Reset button (or remove the jumper wire).
It should now upload OK - as the sketch which activated the watchdog timer never started.

The solution above is to not let the current sketch run at all, thus avoiding whatever-it-is that it does to stop new sketches from uploading.
The references to the watchdog timer are from the original post, they are not relevant here.

It gives no warnings in Arduino IDE 1.8.9, 1.8.15 and 2.0.4 even with all warnings enabled.

That's because there are no problems with the sketch per se. The hardware? Well, you buy cheaper hardware, you may get some problems. The technique described above helps you work around those problems.

With some USB to TTL Serial chips it is a problem to start the upload if there is too much input from the MCU on the Serial side. In this case it is the Holtek UART Bridge which is not common for Arduino boards.
To stop the sketch, hold the reset button until the upload from IDE starts. When the reset button is released, the bootloader starts and receives the upload.


text:
Baud rate above 115200 don't work for esp32
I have equipment transmitting data via uart with a baud rate of 1382400 and I would like to read this information through the Serial2 port of the ESP32.
I've tried to set this high baud rate using Serial2.begin(1382400) but I can't read anything.
Using the function below to detect the baud rate I can read a maximum of 922190 bauds.
Below is the sketch I used to check the baudrate:
void setup() {

     Serial.begin(115200);
     delay(100);
     Serial.println();
     // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
     Serial2.begin(0, SERIAL_8N1, -1, -1, true, 11000UL);

     unsigned long detectedBaudRate = Serial2.baudRate();
     if(detectedBaudRate) {
       Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
     } else {
       Serial.println("No baudrate detected, Serial2 will not work!");
     }
   }

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

}

The answer I get is as follows:
Detected baud rate is 922190
I managed to communicate between the equipment and the esp32 using a baud rate of 115200.
I changed the baud rate to 230400 and I couldn't communicate anymore. From 230400 no baud rate worked.
The transmitting equipment uses pic 18F4520 and engineering sent me the following information:
The crystal of the equipment is 11.0592 MHz
The PLL quadruples this frequency, so the pic's clock is 44.2368 MHz
I connect the tx with the rx , I interconnect the GND. As far as I understand it is not a connection problem because in 115200 it works.
Unfortunately I can't change it to 115200 definitively because it changes other functions of the equipment.
Is this a limitation of ESP32? Could I do something else to test?
Sorry for the long post and language mistakes as English is not my main language .

ESP32 can operate up to 922190 bps without any problem. I use it all the time. In fact, it is default upload speed every time you update code to the ESP32.  If there is any something that doesn't work, it is more likely that your PIC18F4520 can't support it.

@hcheung - I asked to set the speed of the pic to 922190 and even then I couldn't communicate. Using the code in the question I realized that the baudrate difference detected exceeds 3%, could this be the source of the problem?
Another curiosity, using Realterm for windows and setting it to 922190 I also can't read anything in esp.

Well, maybe you should ask whoever ask you to run PIC at 922190, why he/she think the PIC can run at that speed according to table 18-3 (page 196) of 18F4520 datasheet?

@hcheung - yes according to the manual 115200 would be the maximum but in the equipment the current speed is 1382400 bps. This equipment communicates at this high speed with an hc-06 module. So I believe it could be something with the ESP32.
The hardware developer makes it available via bluetooth , command to change the communication speed going up to 1382400.
If you want I can detail the calculation he explained to me to see it clarifies something.


text:
Connecting HM-10 and relay to Arduino Uno
I have an 8 channel relay, an Arduino Uno, and this HM-10 bluetooth module: https://www.amazon.com/dp/B06WGZB2N4
The Goal
Send a number (1-8) from my Android phone via bluetooth to turn a relay on.
The Problem
I can't seem to get the bluetooth to reply to anything I send. I'm trying to use "Arduino Bluetooth" from the app store to send commands, but it either errors or ignores me and doesn't do anything. I can't communicate with the bluetooth from the Arduino IDE either.
The wiring
I'm SUPER new to small electronics, I suspect I'm not giving the system enough power and might need to give my relay its own 5.5v supply, but here's what I've got:
HM-10    | Uno
-------------------
RX       | Digital 3
TX       | Digital 2
VCC      | 3.3V
GND      | GND

Uno      | Relay
-------------------
Digital 4       | IN8
Digital 5       | IN7
Digital 6       | IN6
Digital 7       | IN5
Digital 8       | IN4
Digital 9       | IN3
Digital 10      | IN2
Digital 11      | IN1
GND             | GND
5V              | VCC

The code:
#include <SoftwareSerial.h>

const int relayPins[] = {4, 5, 6, 7, 8, 9,10,11};
SoftwareSerial HM10(2, 3);

void setup() {
  Serial.begin(9600);
  HM10.begin(9600);
  for (int i = 0; i < sizeof(relayPins) / sizeof(relayPins[0]); i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], HIGH); // set relays to OFF
  }
}

void loop() {
  if (HM10.available() > 0) {
    int relayNum = HM10.read() - '0'; // convert ASCII to integer
    if (relayNum >= 1 && relayNum <= 11){
        digitalWrite(relayPins[relayNum - 1], LOW);
        Serial.print("Turned on relay ");
        Serial.println(relayNum);
        delay(1000); // wait for 1 second
        digitalWrite(relayPins[relayNum - 1], HIGH);
        Serial.print("Turned off relay ");
        Serial.println(relayNum);
    }
  }
}

add some debugging code


text:
How does Arduino IDE reset a board before flashing? Why doesn't avrdude do it?
I have the beetle board, a Leonardo clone same as in this  question.

Using the reset pin and quick hands on the keyboard, I am able to flash with avrdude and get also the board info with a command line like this:
$ avrdude -c avr109 -p atmega32u4 -P /dev/ttyACM1

And get the output:
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)

avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)

avrdude done.  Thank you.

This is good but when I flash something from the ArduinoIDE I noticed I don't have to reset the board manually by grounding the reset pins, the boot loader starts automatically
How does ArduinoIDE reset the bootloader, some kind of communication on /dev/ttyACM1?

The uploaded Arduino sketch has in the part provided by core a code which waits for a 1200 baud connection on USB. If a 1200 baud connection is established it resets the board to bootloader. The bootloader then starts the com port and waits for the upload.
To reset a board which has in boards.txt upload.use_1200bps_touch=true Arduino IDE opens a 1200 baud connection to the board, then detects the new com port and start avrdude for the upload.


text:
What is the best way to create a library from existing functions?
I was tasked to take functions that work, and create a library with these functions.
Take a look at the following function that existed inside a program:
char* Num_to_HEX_char_array(int32_t value)
{
  Clear_array(MyTempArray, MY_TEMP_ARRAY_LENGTH);
  ltoa(value, MyTempArray, HEX);
  return MyTempArray;
}

(Let's ignore the fact that this function)
This cannot be immediately made into a library, as MyTempArray is non existant.
This, in the .cpp file, i will have to manually create these lines:
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];

Now the library compiles fine.
However, this library can be called by many programs that I create, and some of them might require a different array length, while others ay require a different name than this one.
So what is the best way to create this library?
*One approach that I thought was to dynamically create these arrays with malloc().
And then, on the main program, you will have to realloc() the arrays with the ones you want.
Also, use undef and re#define.
The drawbacks to this approach is that you have to remember to ALWAYS use these statements, if you want your library to work
*Another approach is to place all this code:
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];

inside a configuration header file. The variables will be of global scope.
Then, when you create an application, you will only have to change this file.
My question to this approach is How exactly can you make sure that this configuration file is read by all the libraries?
Maybe you many libraries, for example, string-handling, or sensor-handling...
Each and every one of these user-created libraries have to #include and see that configuration header file, in order to make sure that the definitions and arrays of correct/name and size.
How can you do this so that it is visible by all your user-created libraries?
Where is the optimal location to place that file?
In general, what is the best approach to solve this issue?

what do you mean when you say best?

I'd write such a function to expect the calling function to allocate the array and pass it and its size as arguments. That leaves the memory allocation and deallocation up to each library user, who may want/need (for other reasons) to use a static array, heap memory, or an automatic array and allows them to de-allocate it (or not) when their application no longer needs it. Coding these details into your library would restrict its usability.

First of all, I must say I have an issue with the example you provide.
The function Num_to_HEX_char_array() should use an array that has the
maximum size that ltoa() may ever need. No more, no less. There is no
point in letting the user of the library choose this size. Here is how I
would implement this function:
char *Num_to_HEX_char_array(int32_t value)
{
    static char buffer[2 * sizeof(long) + 1];
    return ltoa(value, buffer, HEX);
}

That being said, I am willing to accept the idea that your library has
some static buffers for which it does make sense to let the user choose
the size. You could probably find a better example to put in the
question though.
In this case, I would suggest you first consider the approach proposed
by JRobert, and let the user provide those buffers. Using static buffers
in a library can make the API easier to use in the most common cases.
There are many function in the C standard library that do this, like,
e.g. ctime(). This, however, comes at a cost:

the user must be well aware that calls to the library can clobber
data returned by previous calls

the functions are not re-entrant, meaning they cannot be used in
multiple threads, and they cannot be used both in interrupt and
non-interrupt contexts.

This is why you have functions such as ctime_r(): to provide an
alternative that lets the user handle the buffer, and does not suffer
from the previous shortcomings.
If you still believe you want static buffers inside your library, then
you should first consider whether it is possible to fix the size, like
in the Num_to_HEX_char_array() example. If this is not possible, then
the best I can think of is to use C++ templates. For example:
template<size_t size> class CircularBuffer {
    int buffer[size];
    // ...
};

which would be instantiated like this:
// Let `queue' be a 42-slot circular buffer.
CircularBuffer<42> queue;

Keep in mind, though, that this technique forces you to put most of the
code in the header file.

Command line compilers and most IDEs for C and C++ enable to set project defines as -D parameters in project settings. Arduino IDE does not enable this yet, because it doesn't have a project configuration file.
With Arduino IDE you can add defines for platform or for board definitions with build.extra_flags in platform.local.txt or in boards.local.txt. Example for boards.local.txt for Arduino Mega:
mega.build.extra_flags=-DUIP_CONF_UDP_CONNS=20 -DUIP_CONF_MAX_LISTENPORTS=30
platform.local.txt and boards.local.txt must be in boards package folder nect to platform.txt and boards.txt.


text:
Stepper motor micros (millis) non-blocking delay simple example?
I am trying to get a simple non-blocking replacement for:
digitalWrite(stepPinX, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinX, LOW);
delayMicroseconds(500);

This is what I tried, and the stepper motor stays still:
const int dirPinX = 0;
const int stepPinX = 2;

unsigned long startMicros = micros();
unsigned long currentMicros;
const unsigned long period = 500;

void setup()
{
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);

  digitalWrite(dirPinX, HIGH);
}

void loop()
{
  stepX();
}

void stepX()
{
  currentMicros = micros();  //get the current "time" (time since program start)

  if (currentMicros - startMicros >= period)  //test whether period elapsed
  {
    digitalWrite(stepPinX, HIGH);
  }
  if ((currentMicros - startMicros >= period) && (currentMicros - startMicros <= period*2))
  {
    digitalWrite(stepPinX, LOW);
  }

  startMicros = currentMicros;
}

Any suggestions on how to correct this? (I do not want to use a library like Accelstepper. I want to use millis/micros.)

the second if statement will execute only very infrequently ... why have a separate if statement for the two output states?

edited question and program

do only one if (currentMicros - startMicros >= period) ... keep track of stepPinX state

Your stepX() function looks like this:
void stepX()
{
  currentMicros = micros();
  // conditionally do some stuff..
  startMicros = currentMicros;
}

Since there is nothing that can block it, it will always execute very
fast. This means that, by the time the function returns, startMicros
will be very close to the current time. Then, on the following call,
currentMicros - startMicros will be very small, way smaller than
period, and the conditional code will never execute.
The solution is to change the meaning of startMicros: instead of
representing the time of the last call to stepX(), let it represent
the time when the last step started. For this, you have to reset it only
when finishing a step:
void stepX()
{
  currentMicros = micros();
  if (currentMicros - startMicros < period) {           // 1st phase
    digitalWrite(stepPinX, HIGH);
  } else if (currentMicros - startMicros < 2*period) {  // 2nd phase
    digitalWrite(stepPinX, LOW);
  } else {                                              // complete cycle
    startMicros = currentMicros;
  }
}

  {
    digitalWrite(stepPinX, LOW);
    startMicros = currentMicros;
  }```

Like that? Same result as before.

@adamaero: Oops! Indeed, I did not notice that the logic of the if conditions was wrong. Edited the answer.

Looks like startMicros and currentMicros values always stay close to each other because of using micros() before and after the conditional block. Since the conditional block executes faster than 500 micros, resulting in never entering the conditional block.
From here you can take two approaches,

Approach 01: Play with your code variables and debug in realtime to see what's wrong and where. Then tweak,debug, repeat until you reach the desired result
Approach 02: Rethink w.r.t the code execution and simplify your code right from entry to exit in sequential steps.

Since your action can be simplified to a toggle operation every 500 microseconds, we can refactor code similar to what I have written,
bool toggle_flag = false;
unsigned long last_toggle;
const unsigned long period = 500;

void setup() {
    last_toggle = micros();
    pinMode(stepPinX, OUTPUT);
}

void loop() {
  // Check to see if time elapsed
  if (micros() - last_toggle >= period ) {

      // Step 01: reset the last_toggle with current time
      last_toggle = micros();

      // Step 02: check toggle flag and perform the toggle action
      (toggle_flag) ? digitalWrite(stepPinX, HIGH) : digitalWrite(stepPinX, LOW);

      // Step 03: toggle the toggle flag variable after our action
      toggle_flag = !toggle_flag;

  }

}

Hope this answer helps.


text:
MQTT on ESP8266 cannot connect if using Last Will service
Issue (short) description
An ESP8266 using PubSubClient fails to establish connection to MQTT broker (mosquitto) if requesting Last Will Testament (LWT) on connection, though it is able to connect without LWT.
The aim and detailed description of the issue
The aim is actually to make the ESP to receive messages that been published while it was offline. Following the generic recipe for MQTT, I tried to set cleanSession =false which in PubSubClient also requires passing LWT arguments. Using code shown bellow (with the arguments passed to the PubSubClient.connect() method)  results in that the same ESP board connecting to the same MQTT server could not connect anymore (the code below is stripped to MQTT relevant parts):
WiFiClient wclient;
PubSubClient mqtt_client(wclient);

String DEVICE_NAME = "esp8266_test";
const int DEVICE_ID = 1;
String MQTT_CLIENT_ID = DEVICE_NAME + (String)(DEVICE_ID);

const char * mqtt_client_id = MQTT_CLIENT_ID.c_str();
const char* willTopic = (DEVICE_NAME + "/will").c_str();
uint8_t willQos = 0;
bool willRetain = false;
const char* willMessage = "will";
bool cleanSession = false;
int mqtt_keep_alive = 60;

void connect_mqtt(const char *mqtt_user, const char *mqtt_pass, const int timeout){
  int i = 0;
  logger.info("Connecting to MQTT broker.");
  while ((!mqtt_client.connected()) && (i < timeout) && (WiFi.status() == WL_CONNECTED)) {
    logger.info("Attempt " + (String)(++i));
    mqtt_client.setKeepAlive(mqtt_keep_alive);
    mqtt_client.connect(
      mqtt_client_id,
      mqtt_user,
      mqtt_pass,
      willTopic,
      willQos,
      willRetain,
      willMessage,
      cleanSession);
  }

  if (mqtt_client.connected()) {
        logger.info("MQTT broker connected.");
    } else {
        logger.error("Connection timeout. Failed with state: " + (String)(mqtt_client.state()));
        }
}

void start_mqtt(IPAddress mqtt_server, const int mqtt_port, const char *mqtt_user, const char *mqtt_pass){

  mqtt_client.setServer(mqtt_server, mqtt_port);
  // mqtt_client.setCallback(callback);
  connect_mqtt(mqtt_user, mqtt_pass, timeout);
}

In the code above start_mqtt() function is called from setup(), the output it will result in looks as follows:
INFO: Connecting to WIFI SSID: xxxxxxx
INFO: WiFi Connection established
IP address:     192.168.178.55
INFO: Connecting to MQTT broker.
INFO: Attempt 1
INFO: Attempt 2
INFO: Attempt 3
INFO: Attempt 4
INFO: Attempt 5
INFO: Attempt 6
ERROR: Connection timeout. Failed with state: -4

If instead one calls connect() method with only mqtt_client_id, mqtt_user, mqtt_pass arguments, the connection can be established without any issues, e.g.:
mqtt_client.connect(mqtt_client_id, mqtt_user, mqtt_pass)

Attempts to troubleshoot:

I've tried using connect() without cleanSession argument, the behaviour is the same: cannot connect with state -4. So I've concluded that the issue is in LWT service, which I actually don't need but it seems one has to use it with cleanSession
According to PubSubClient documentation the -4 state is "the server didn't respond within the keepalive time", so I've started looking on the server side (see next items)
The server log looks like this:

2023-04-01 18:37:09 1680367029: Client <unknown> disconnected due to protocol error.
2023-04-01 18:38:36 1680367116: New connection from 172.17.0.1:54174 on port 1883.

If connecting without LWT (using only mqtt_client_id, mqtt_user, mqtt_pass arguments) connection can be established and the log looks like this:

2023-04-01 18:38:36 1680367116: New client connected from 172.17.0.1:54174 as esp8266_test1 (p2, c1, k60, u'xxxx').

Mosquitto documentation doesn't say anything about enabling LWT, which suggests that it should work with the mostly default config which is used here.

I tried two different Mosquitto servers configured for user/password authentication, results are the same.

Questions
Based on behaviour above, my conclusion is that using PubSubClient with LWT results in a sort of change of a protocol which is not recognised/supported by Mosquitto. Therefore, the questions are:

Is there is a way to fix the issue, or to further troubleshoot it?
Is there is a way to use cleanSession = false without enabling LWT?
Is there other ways of receiving "offline" MQTT messages on ESP8266 (without using cleanSession = false)?

Hi @Vadim - could you please edit the question to include the values you're using for willTopic, willQos, willRetain and willMessage?

@romkey sure, done


text:
ESP32 - BLE does not connect/restart after light sleep
noob in arduino here.
I'm trying to connect via BLE after the ESP32 wakeups from light sleep. I have tried many different things, but none of them work. Everything works fine before the device sleeps the first time. Could you guys please give some ideas of what is wrong? the official docs are terrible.

    btStop();
    delay(1000);
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
    Serial.println("Going to light sleep now");
    esp_light_sleep_start();
    btStart();

I finally found the answer, you just need to advertise again the service after it sleeps. First you need to define this:
#if CONFIG_PM_ENABLE
// Configure dynamic frequency scaling:
// maximum and minimum frequencies are set in sdkconfig,
// automatic light sleep is enabled if tickless idle support is enabled.
// esp_pm_config_esp32c3_t pm_config = { // old version
esp_pm_config_t pm_config = {
        .max_freq_mhz = 160, //  e.g. 80, 160,
        .min_freq_mhz = 80, // 40
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
        .light_sleep_enable = true
#endif
    };
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
#endif // CONFIG_PM_ENABLE

Then in your loop you could do something like:
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Going to light sleep now");
esp_light_sleep_start();
Serial.println("depois do sleep start");
BLEDevice::startAdvertising();


text:
Code works in Arduino Web editor but not in PlatformIO IDE or Arduino IDE with board Nicla Sense ME
Here is the verbose for the Arduino IDE:
Flashing with command:/Users/hakan/.arduino-create/arduino/openocd/0.11.0-arduino2/bin/openocd -d2 -s /Users/hakan/.arduino-create/arduino/openocd/0.11.0-arduino2/share/openocd/scripts/ -f interface/cmsis-dap.cfg -c transport select swd; adapter speed 1000 -f target/nrf52.cfg -c telnet_port disabled; init; reset init; halt; adapter speed 10000; program {/var/folders/dy/qqk78q1956s1pb94hc4y_x5m0000gn/T/arduino-create-agent511362936/sketch_mar22a.elf}; reset run; shutdown

Open On-Chip Debugger 0.11.0+dev-gab95bac57-dirty (2021-05-11-10:57)

Licensed under GNU GPL v2

For bug reports, read

http://openocd.org/doc/doxygen/bugs.html

debug_level: 2

adapter speed: 1000 kHz

Info : CMSIS-DAP: SWD Supported

Info : CMSIS-DAP: FW Version = v1.0

Info : CMSIS-DAP: Serial# = AA7EAA93

Info : CMSIS-DAP: Interface Initialised (SWD)

Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1

Info : CMSIS-DAP: Interface ready

Info : clock speed 1000 kHz

Info : SWD DPIDR 0x2ba01477

Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints

Info : starting gdb server for nrf52.cpu on 3333

Info : Listening on port 3333 for gdb connections

target halted due to debug-request, current mode: Thread

xPSR: 0x01000000 pc: 0x00006dc4 msp: 0x20010000

target halted due to debug-request, current mode: Thread

xPSR: 0x01000000 pc: 0x00006dc4 msp: 0x20010000

** Programming Started **

Info : nRF52832-CIAA(build code: E0) 512kB Flash, 64kB RAM

Warn : Adding extra erase range, 0x0001d8f8 .. 0x0001dfff

** Programming Finished **

shutdown command invoked

Here is the one for PlatformIO:
AVAILABLE: blackmagic, cmsis-dap, jlink, nrfjprog, nrfutil, sam-ba
CURRENT: upload_protocol = cmsis-dap
openocd -d2 -s /Users/hakan/.platformio/packages/tool-openocd/scripts -f interface/cmsis-dap.cfg -f target/nrf52.cfg -c "transport select swd;" -c "adapter speed 1000" -c "program {.pio/build/nicla_sense_me/firmware.hex}  verify reset; shutdown;"
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-17-00:18)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 2

Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
Warn : Transport "swd" was already selected
swd
adapter speed: 1000 kHz

Info : CMSIS-DAP: SWD  supported
Info : CMSIS-DAP: FW Version = v1.0
Info : CMSIS-DAP: Serial# = AA7EAA93
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : nrf52.cpu: Cortex-M4 r0p1 processor detected
Info : nrf52.cpu: target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for nrf52.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x000008e4 msp: 0x20000400
** Programming Started **
Info : nRF52832-CIAA(build code: E0) 512kB Flash, 64kB RAM
Warn : Adding extra erase range, 0x00052738 .. 0x00052fff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked

Platform.ini content:
[env:nicla_sense_me]
platform = nordicnrf52
board = nicla_sense_me
framework = arduino
monitor_speed = 115200
debug_speed = 1000
upload_protocol = cmsis-dap

lib_deps =
    Wire
    /Users/marcopolo/Documents/PlatformIO/Projects/C1/include/Arduino_BHY2
    /Users/marcopolo/Documents/PlatformIO/Projects/C1/include/ArduinoBLE-master

The code is a very basic blink example.
Edit: Here is the error:
++ MbedOS Fault Handler ++

FaultType: HardFault

Context:
R   0: 20010000
R   1: 0001BB1C
R   2: 00000005
R   3: 00000000
R   4: 20010000
R   5: 20010000
R   6: 0001BB1C
R   7: 00000000
R   8: 00000000
R   9: 00000000
R  10: 00000000
R  11: 00000000
R  12: FFFFFFFF
SP   : 20002CA0
LR   : 00010CB7
PC   : 00013B3E
xPSR : A1070000
PSP  : 20002C80
MSP  : 2000FFC0
CPUID: 410FC241
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000082
UFSR : 00000000
DFSR : 00000000
AFSR : 00000000
BFAR : 20010000
Mode : Thread
Priv : Privileged
Stack: PSP

-- MbedOS Fault Handler --

++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0x13B3E
Error Value: 0x2000303C
Current Thread: main Id: 0x20001A78 Entry: 0x13057 StackSize: 0xC00 StackMem: 0x200020D0 SP: 0x20002CA0
For more info, visit: https://mbed.com/s/error?error=0x80FF013D&tgt=NICLA
-- MbedOS Error Info --

Edit: Same board works pretty fine in Windows OS.

Verbose compilation and compare parameters. For example micro:bit had issue with -DNRF52 (second port wasn't available - but for 52832 it's valid define) and -DUSE_LFXO used external 32k crystal configuration for millis(), but there is none on the board and so on...

I appreciate if you can elaborate.

I'm reading about that board and you might be able to run it in debugger - you can just step through the program and what is causing that hard fault. (micro:bit has 1-click debug too same this board)

@KIIV, I have just found out that the board works fine in Windows. Regarding the cause, the program is a very simple blink.


text:
How to scroll text on an OLED display using only the SSD1306Wire library?
I'm a 13 years old boy and I am doing a project with esp01 and an OLED screen to display project ideas on the OLED with the ChatGPT API. The answer is displayed on the OLED but I would like it to scroll from bottom to top and so on to the next query so I can see the whole answer.I noted that the only library that worked for me for the esp01 was the SSD1306Wire library .My code is :
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <Wire.h>
#include <SSD1306Wire.h>
#include <ArduinoJson.h>

const char* ssid = "WIFI_NAME";
const char* password = "WIFI_PASSWORD";

const char* apiEndpoint = "https://api.openai.com/v1/engines/text-davinci-002/completions";
const char* apiToken = "OPENAI_TOKEN";

SSD1306Wire  display(0x3c, 2, 0);
void setup() {
 Serial.begin(115200);

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

 Serial.println("Connected to WiFi");

 display.init();
 display.flipScreenVertically();
 display.setFont(ArialMT_Plain_10);
}

void loop() {
 WiFiClientSecure client;
 client.setInsecure();
 HTTPClient http;
 http.begin(client, apiEndpoint);
 http.addHeader("Content-Type", "application/json");
 http.addHeader("Authorization", "Bearer " + String(apiToken));
 String payload = "{\"prompt\": \"TEXT_TO_QUERY\",\"temperature\":0.8,\"max_tokens\":40}";
 int httpResponseCode = http.POST(payload);
 String response = "";

 if (httpResponseCode == 200) {
   response = http.getString();
   int startIndex = response.indexOf("text\":") + 7;
   int endIndex = response.indexOf("\",\"index\"");
   response = response.substring(startIndex, endIndex);
   response.replace("\\n", "\n");
   Serial.println(response);
 } else {
   Serial.print("Error: ");
   Serial.println(httpResponseCode);
 }

 http.end();

 display.clear();
 display.drawStringMaxWidth(0, 0, 128, response);
 display.display();

 delay(18000000);
}

Could anyone help me?

have you looked at the example sketches?

The 5 hour pause is supposed to be 30 minutes, my mistake. The library doesn't seem to have example sketches.

then do an internet search for SSD1306Wire.h

But my problem is that the library does not support the scroll function

Are  you asking for smooth scrolling or jumping by a character or line of text?  Assuming the former, are you asking for horizontal scrolling or vertical scrolling.  I think horizontal scrolling is supported but is undocumented.  I'm not sure about vertical scrolling.

I would like the texte to scroll smoothly
From the bottom to the top

The library I think you are using is hosted at github.com and does not appear to support vertical scrolling as there has been discussion that looks to have ended about vertical scrolling in the issues.  It may support horizontal scrolling, but that discussion also points to a fork of the project on another github.com page. If you want to know more I suggest going there and reading these discussions.  Perhaps participating in them.

Ok thank you . Should I close the discussion or something like that?

You, or the person answering your question (@st2000) should convert the comments into an actual answer. Then it can be marked as accepted, in order to help others with the same query.

The SSD1306Wire code, its development history and discussions can be found here on github.com.
The Google search pattern "scroll
site:github.com/ThingPulse/esp8266-oled-ssd1306" can be used to find
all matches to "scroll" on these web pages. There appears to be
interest in vertical scrolling by others but no support as of yet.
There also appears to be some horizontal scrolling support or success as
discussed in this github.com issue for this project.
Also in that thread, there is a link to another DSS1306 github.com project
which explicitly states it supports horizontal scrolling.


text:
BLE disconnect during code "pause"
I have a code that should pause the script for a specific time (x_time). if x_time is above 30-40 sec the BLE connection to the android phone is lost. Any suggestions on how to avoid the lost connection and creating a pause in the script?
code:
#include "LSM6DS3.h"
#include "Wire.h"
#include <ArduinoBLE.h>  // Arduino BLE library

//Create a instance of class LSM6DS3
LSM6DS3 myIMU(I2C_MODE, 0x6A);  //I2C device address 0x6A
const char* UUID_serv = "75681d64-fd7e-40f7-874f-c6f2e7ec996c";

// UUids for accelerometer characteristics
const char* UUID_AccBLE = "75681d64-dd7e-40f7-874f-c6f2e7ec996c";

BLEService myService(UUID_serv);
BLEIntCharacteristic AccBLE(UUID_AccBLE, BLERead | BLENotify);

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

    pinMode(LEDB, OUTPUT);  // onboard led blue
    //Call .begin() to configure the IMUs
    if (myIMU.begin() != 0) {
      Serial.println("Device error");
    } else {
      Serial.println("Device OK!");
    }
    // init BLE
    if (!BLE.begin()) {
      Serial.println("BLE: failed");
    }
    Serial.println("BLE: ok");

    BLE.setAdvertisedService(myService);
    myService.addCharacteristic(AccBLE);
    BLE.addService(myService);
    AccBLE.writeValue(0);
    // start advertising
    BLE.advertise();
    Serial.println("Advertising started");
    Serial.println("Bluetooth device active, waiting for connections...");
  }
}
float accelerometerX;
unsigned long BreakPreviousMillis;
unsigned long timestamp = micros();

int x_time = 50000;
void loop() {
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");

    while (central.connected()) {
      accelerometerX = myIMU.readFloatAccelX();
      if (accelerometerX > 2) {
        BreakPreviousMillis = millis();
        while (millis() < BreakPreviousMillis + x_time) {
          Serial.println("pause");
        }
      }
      AccBLE.writeValue(accelerometerX);
      Serial.print("*************LOOP TIME[uS] = ");
      Serial.println(micros() - timestamp);  // 13HZ =79000-80000 uS   // used to check framerate
    }

    digitalWrite(LEDB, HIGH);  // High == turning off the Led
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

Which core? There are two of them, one has RTOS and second mbed-os (like Arduino 33 nano ble), there might be some differences. Or it needs calling some method to handle events. For example BLE.poll(); or something

Thanks for the comment. I use the mbed-os core

One more thought - add some delay in that while loop, maybe the BLE service is running on lower priority thread and it's "starving" for resources

you can just use delay(x_time); instead of the while loop

Thanks for the response. I tried the delay(x_time) however it was even worse and disconnected  af 10-15 sec.


text:
How to run avr-gcov on a .ino sketch file
I am new to Arduino and gcov. I have a .ino sketch file, avr-gcov, and avr-gcc from Arduino library in the same directory. Could someone guide me to the steps I should take to run avr-gcov on my .ino file and get a .gcov file?
These are the things I have tried so far. When I run
./avr-gcov filename.ino,
it throws the error filename.gcno: cannot open notes file. My assumption was that I needed create a .gcno file before running gcov. So I tried to create one using the command
./avr-gcc -c -Wall -pg -fprofile-arcs -ftest-coverage filename.ino.
But doing so gives a warning: linker input file unused because linking not done and doesn't produce anything.
I tried to create an object code from the sketch file by passing -o flag but that throws the error avr-gcc: fatal error: -fuse-linker-plugin, but liblto_plugin.so not found.
Any help would be appreciated.

why do you want to use gcov?

The sketch file is very large. I would like to get the code coverage and identify the blocks that are reached more often and generate a control flow graph based on that.

Code coverage by "gcov" has some prerequisites:

Instrumented code to count the number the control flow reaches certain points of the program. This is done via the options you tried.
Linking with the support library. This is done via the options you tried. The result is a "gcno" file for each translation unit.
This support library expects a file system to store the accumulated counter values.
Running the application, the support library creates a "gcda" file for each translation unit. This file holds the accumulated counter values.
"gcov" expects all these "gcno" and "gcda" files to generate an annotated listing.

Since common Arduinos don't have a file system, the prerequisites cannot be fulfilled. This is the reason why you receive the error messages.
So what can you do now? There are multiple alternatives, but this site is not appropriate to present you ready-made solutions.

You can compile the sketch for the PC. For this you need to provide all used Arduino functions, for example as mocks or simulation.
You can provide the missing functions on your own, some kind of persistent storage, and finally transfer the data as "gcda" files to your PC. (This sounds complicated and resource expensive, and it is. However, it's doable, I did this years ago with another embedded system and a former version of "gcov".)
Refrain from using "gcov" and try other approaches of finding your hot spots. For example, toggle different port pins and/or with different patterns to literally "see" which code is executed. You need a good oscilloscope or logic analyzer for this.


text:
Issues getting WPS working on ESP32
I am trying to implement WPS on ESP32. A WT32-SC01 Plus to be exact.
It seems to working so far that I'll get the WPS connection but then it takes around 5 minutes [!!!] to get IP address from the router.
Also when the WPS connection was successful, after a reboot it do not reconnect but expects a new WPS initialization.
Can you take a look and tell me what am I doing wrong.
Here is my code:
#include "WiFi.h"
#include "esp_wps.h"

#define ESP_MANUFACTURER  "ESPRESSIF"
#define ESP_MODEL_NUMBER  "ESP32"
#define ESP_MODEL_NAME    "ESPRESSIF IOT"
#define ESP_DEVICE_NAME   "ESP STATION"

struct WiFiHandler
{
    bool connected = false;
    bool connecting = true;
    bool wpsDone = false;

    WiFiHandler()
    {
        WiFi.mode( WIFI_STA );
        // WiFi.setAutoReconnect( false );
        WiFi.onEvent( [ = ] ( WiFiEvent_t event, arduino_event_info_t info ) -> void
        {
            switch( event ) {
                case ARDUINO_EVENT_WIFI_STA_START:
                    Output::Message( "Station Mode Started" );
                break;
                case ARDUINO_EVENT_WPS_ER_PIN:
                    Output::Message( "PIN: %d", info.wps_er_pin.pin_code );
                break;
                case ARDUINO_EVENT_WIFI_STA_GOT_IP:
                    Output::StartUpMsg( "Connected" );
                    connected = true;
                    connecting = false;
                break;
                case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
                    Output::Message( "Reconnecting" );
                    WiFi.reconnect();
                break;
                case ARDUINO_EVENT_WPS_ER_SUCCESS:
                    Output::StartUpMsg( "WPS Successfull." );
                    WiFi.disconnect();
                    wpsStop();
                    WiFi.begin();
                    wpsDone = true;
                break;
                case ARDUINO_EVENT_WPS_ER_FAILED:
                    Output::StartUpMsg( "WPS Failed!" );
                    connecting = false;
                break;
                case ARDUINO_EVENT_WPS_ER_TIMEOUT:
                    Output::StartUpMsg( "WPS Timedout!" );
                    connecting = false;
                break;
            }
        } );
    }

    bool initialise()
    {
        int cnt = 0;
        TaskHandle_t taskHandle = NULL;
        xTaskCreate( this->blink, "WiFiConnect", 1000, this, 1, &taskHandle );
        Output::StartUpMsg( "Establishing network connection ..." );

        if( String( WiFi.SSID().c_str() ).length() ) {
            WiFi.begin( WiFi.SSID().c_str(), WiFi.psk().c_str() );
            while( ( WiFi.reconnect() != ESP_OK && !this->connected ) && ( ++cnt < 20 ) ) {
                lv_bar_set_value( ui_BootProgress, lv_bar_get_value( ui_BootProgress ) + 1, LV_ANIM_ON );
                delay( 100 );
            }
        }
        if( !this->connected ) {
            WiFi.begin();
            Output::StartUpMsg( "Please initialise WPS connection on the router." );
            cnt = 0;
            if( wpsInit() ) {
                if( esp_wifi_wps_start( 1000 ) != ESP_OK ) {
                    Output::StartUpMsg( "Can't start WPS" );
                }
                while( WiFi.status() != WL_CONNECTED )
                {
                    delay( 1000 );
                    if( WiFi.status() == WL_IDLE_STATUS && wpsDone ) {
                        WiFi.reconnect();
                    }
                    // if( WiFi.status() == WL_CONNECTION_LOST && wpsDone ) {
                    //     WiFi.disconnect();
                    //     WiFi.begin( WiFi.SSID().c_str(), WiFi.psk().c_str() );
                    // }
                    Output::Message( WiFi.SSID().c_str() );
                    Output::Message( WiFi.localIP().toString().c_str() );
                    Output::Message( String( WiFi.status() ).c_str() );
                }
                delay( 2000 );
                this->connected = true;
            }
        }
        if( this->connected ) {
            while ( !WiFi.SSID().length() )
            {
                lv_bar_set_value( ui_BootProgress, lv_bar_get_value( ui_BootProgress ) + 1, LV_ANIM_ON );
                delay( 100 );
            }
            Output::StartUpMsg( "Connected to: " + WiFi.SSID() );
            while ( !String( WiFi.localIP() ).length() || WiFi.localIP().toString() == "0.0.0.0" )
            {
                lv_bar_set_value( ui_BootProgress, lv_bar_get_value( ui_BootProgress ) + 1, LV_ANIM_ON );
                delay( 100 );
            }
            Output::StartUpMsg( "IP: " + String( WiFi.localIP().toString() ) );
            delay( 500 );
            this->connecting = false;
            this->connected = true;
        }
        return this->connected;
    }

    String getIP()
    {
        return String( WiFi.localIP().toString() );
    }

    String getPass()
    {
        return String( WiFi.psk().c_str() );
    }

    String getNetworkName()
    {
        return String( WiFi.SSID() );
    }

    String getMAC()
    {
        return String( WiFi.macAddress() );
    }

    static void blink( void *pvParameter )
    {
        WiFiHandler *l_pThis = ( WiFiHandler * ) pvParameter;
        for( int i = 0; l_pThis->connecting; i++ )  {
            i%2 ? lv_obj_add_flag( ui_WiFiStatus1, LV_OBJ_FLAG_HIDDEN ) : lv_obj_clear_flag( ui_WiFiStatus1, LV_OBJ_FLAG_HIDDEN );
            delay( 250 );
        }
        l_pThis->connected ? lv_obj_clear_flag( ui_WiFiStatus1, LV_OBJ_FLAG_HIDDEN ) : lv_obj_add_flag( ui_WiFiStatus1, LV_OBJ_FLAG_HIDDEN );
        vTaskDelete( NULL );
    }

    static bool wpsInit()
    {
        int cnt = 0;
        esp_wps_config_t config;
        config.wps_type = WPS_TYPE_PBC;
        strcpy( config.factory_info.manufacturer, ESP_MANUFACTURER );
        strcpy( config.factory_info.model_number, ESP_MODEL_NUMBER );
        strcpy( config.factory_info.model_name, ESP_MODEL_NAME );
        strcpy( config.factory_info.device_name, ESP_DEVICE_NAME );
        esp_err_t status = esp_wifi_wps_enable( &config );

        if( status != ESP_OK ) {
            Output::StartUpMsg( "WPS config failed! " + String( esp_err_to_name( status ) ) );
            return false;
        }
        return true;
    }

    static void wpsStop()
    {
        if( esp_wifi_wps_disable() ) {
            Output::StartUpMsg( "WPS Disable Failed" );
        }
    }
};

Ok people, my router was apparently acting weird. It seems to works fine now!
EDIT: Why the hell someone downvoted my answer? people are weird

how could anyone other than you solve the problem? it is not an Answer.

Nobody because it was a router issue. But as I posted it I assumed it was something with my code.


text:
How to connect Arduino to a switch that doesn't accept 10M?
I've been playing around with several Arduino ethernet modules based on the ENC28J60 and the W5500 chipset. All modules are advertised as 10/100M, but in reality only work when the port of a switch is configured to handle 10M explicitly.
At this point in time that isn't a problem, however I'll be switching to new switches in the near future that can no longer handle 10M, having 100M as the slowest possible port speed.
How can I still connect my Arduino modules to these new switches (specifically Extreme Networks 5720-48MW)? Are there ethernet modules available that can connect to the 5720-48MW switches? And if so, how do I differentiate these modules, since all modules are advertised as 10/100M?

Have you actually determined that your new switches will cause problems?

@StarCat Yes, this is a well known issue, not only limited to these Arduino modules. 10M devices will not work with switches that have speeds of 2.5GBit of higher.

I see now that the ENC28J60 is regularly advertised as supporting 10/100Mbps speeds but according to its datasheet it only supports 10Base-T (10Mbps). The WS5500 should be able to support 10/100 however, if properly implemented.


text:
Digital potentiometer DS3502 question
I am using adafruit DS3502 breakout board for arduino. When I follow procedure written in
https://learn.adafruit.com/ds3502-i2c-potentiometer/arduino
My serial display shows correct voltage values.
My question is: When I remove RL,RH, RW pins from arduino and measure resistance between RW and RL or RW and RH with a multimeter, it doesnt show correct value in ohms. It shows between 300 to 400 K Ohms. Anyone knows is this known behaviour or am I doing something wrong.

If you ground the (-) lead of the meter and probe the RW pin while programmatically  changing the steps, do you get reasonable values?  See https://electronics.stackexchange.com/questions/590633/is-there-a-better-way-to-determine-the-resistance-of-a-digital-potentiometer-tha

NO...doesnt read values at all like this.