ESP32 red LED won't stop blinking after upload

Hey everyone,

I'm quite new to all the programation of ESP32 and that sort of things and i'm struggling to troubleshoot a bug i've been encountering for a while now :

The onboard LED won't stop blinking after i upload my code and won't do anything else.

For context, i want to make a little accelerometer with a screen to display on a small SH1106 OLED pannel both current speed (m/s) and acceleration(m/s²).

It worked for a while, displaying the sensors' reading on the display and everything seems accurate. And it stopped working as soon as i tried to factorize my code.

Here are my parts :

Here's the latest faulty code :

#include <Wire.h>

// OLED display 128px * 64px
#include <Arduino.h>
#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


// Accelerometer ADXL345
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

char* float_to_string(float value)
{
  char str[24];
  return dtostrf(value, 8, 2, str);
}

void display_accel_value(int display_x, int display_y, char[8] prefix, char* value, char[8] suffix)
{
  // prefix                     // value                     // suffix
  u8x8.drawString(0,3,prefix ); u8x8.drawString(2,3,value ); u8x8.drawString(5,3,suffix);
  return ;
}


void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0);

  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    u8x8.drawString(0,1,"no ADXL345 detected");
    u8x8.drawString(0,2,"___________________________________");
    while(1);
  } else {
    u8x8.drawString(0,1,"ADXL345 sensor detected !");
    u8x8.drawString(0,2,"___________________________________");
  }
  accel.setRange(ADXL345_RANGE_16_G);
}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  /* Get a new sensor event */ 
  sensors_event_t event; 
  accel.getEvent(&event);
  
  /* Display the results (acceleration is measured in m/s^2) */
  display_accel_value(0, 3, "X : ", float_to_string(event.acceleration.x), " m/s²");
  display_accel_value(0, 4, "Y : ", float_to_string(event.acceleration.y), " m/s²");
  display_accel_value(0, 5, "Z : ", float_to_string(event.acceleration.z), " m/s²");
  u8x8.drawString(0,6,"___________________________________");
  display_accel_value(0, 7, "Sum : ", float_to_string(abs(event.acceleration.x) + abs(event.acceleration.y) + abs(event.acceleration.z)), " m/s²");

  delay(100);
}

And here's the last working code :

#include <Wire.h>

// OLED display 128px * 64px
#include <Arduino.h>
#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


// Accelerometer ADXL345
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);



// End of constructor list


void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0);

  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    u8x8.drawString(0,1,"no ADXL345 detected");
    while(1);
  }
  accel.setRange(ADXL345_RANGE_16_G);
}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  /* Get a new sensor event */ 
  sensors_event_t event; 
  accel.getEvent(&event);
  
  char strx[32];
  char stry[32];
  char strz[32];

  /* Display the results (acceleration is measured in m/s^2) */
  u8x8.drawString(0,3,"X : "); u8x8.drawString(4,3, dtostrf(event.acceleration.x, 8, 2, strx)); 
  u8x8.drawString(0,4,"Y : "); u8x8.drawString(4,4, dtostrf(event.acceleration.y, 8, 2, stry));
  u8x8.drawString(0,5,"Z : "); u8x8.drawString(4,5, dtostrf(event.acceleration.z, 8, 2, stry));

  delay(10);
}

PS : the compilation and upload works and doesn't output any error, but i'm getting this for every build now : Sketch uses 324439 bytes (24%) of program storage space. Maximum is 1310720 bytes. Global variables use 22272 bytes (6%) of dynamic memory, leaving 305408 bytes for local variables. Maximum is 327680 bytes.
PS2: I tried pressing the rst button after uploading with no success sadly :frowning:

Thanks in advance for everyone's help !

Can you post the full report?
It seems to be compiling but not uploading.

You need to check the instructions on how to use your equipment, From your post, I am assuming it is all there, you compiled but did not enter the upload phase. Start with the blink sketch since it appears it is working and change the timing and be sure to observe the changes in the LED when programing it. If it does not change you did not program the part. Once you get this then try your code as the tools are now working.

Most of the time i had problems with ESP32 classic or the S3 uploading, it was a cheap board with a offbrand chip soldered in, a COM port issue, or a bad USB cable.
USB type C can come with only 2 wires, which dont transfer data but only charge. *Make sure your USB cable is correct and in good condition. Try transferring a simple file with it to your PC.
*Make sure the correct board has been selected in the IDE before you upload code.
*There should be a boot and another button that you can use to reset the board.
*There are strapping pins you want to avoid using in your project on the ESP32s.
Also there are other pins and even fuses you can burn permanently on certain pins.
Id highly recommend reading the datasheets on what you are using.
Dont have to read it all but the strapping pins and designated pins for I2c and SPI, etc you need to know.
Espressif has a wealth of documentation which helps tremendously
However
Most times its the simplest of things causing issues. :upside_down_face:

You can't return a pointer to a local variable. The variable ceases to exist when the function exits. Trying to print the char array is going to continue until the code randomly hits a null character, which is likely causing the ESP32 to reset.

Do other programs work?
Upload blink example and check if it works.

Here are 2 videos, the fisrt one of the working script and the second non working script :

Here's the full build and upload log :

Sketch uses 324667 bytes (24%) of program storage space. Maximum is 1310720 bytes.
Global variables use 22272 bytes (6%) of dynamic memory, leaving 305408 bytes for local variables. Maximum is 327680 bytes.
esptool v5.0.0
Serial port COM3:
Connecting.....
Connected to ESP32 on COM3:
Chip type:          ESP32-D0WD-V3 (revision v3.1)
Features:           Wi-Fi, BT, Dual Core + LP Core, 240MHz, Vref calibration in eFuse, Coding Scheme None
Crystal frequency:  40MHz
MAC:                ec:e3:34:66:88:b4

Uploading stub flasher...
Running stub flasher...
Stub flasher running.
Changing baud rate to 921600...
Changed.

Configuring flash size...
Flash will be erased from 0x00001000 to 0x00007fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x0005ffff...
Compressed 25168 bytes to 16063...

Writing at 0x00001000 [                              ]   0.0% 0/16063 bytes... 

Writing at 0x00007250 [==============================] 100.0% 16063/16063 bytes... 
Wrote 25168 bytes (16063 compressed) at 0x00001000 in 0.6 seconds (343.8 kbit/s).
Hash of data verified.
Compressed 3072 bytes to 146...

Writing at 0x00008000 [                              ]   0.0% 0/146 bytes... 

Writing at 0x00008c00 [==============================] 100.0% 146/146 bytes... 
Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (288.6 kbit/s).
Hash of data verified.
Compressed 8192 bytes to 47...

Writing at 0x0000e000 [                              ]   0.0% 0/47 bytes... 

Writing at 0x00010000 [==============================] 100.0% 47/47 bytes... 
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (615.3 kbit/s).
Hash of data verified.
Compressed 324816 bytes to 175801...

Writing at 0x00010000 [                              ]   0.0% 0/175801 bytes... 

Writing at 0x0001bf72 [=>                            ]   9.3% 16384/175801 bytes... 

Writing at 0x0002a199 [====>                         ]  18.6% 32768/175801 bytes... 

Writing at 0x0002f715 [=======>                      ]  28.0% 49152/175801 bytes... 

Writing at 0x0003509f [==========>                   ]  37.3% 65536/175801 bytes... 

Writing at 0x0003a776 [============>                 ]  46.6% 81920/175801 bytes... 

Writing at 0x0003fa50 [===============>              ]  55.9% 98304/175801 bytes... 

Writing at 0x00045091 [==================>           ]  65.2% 114688/175801 bytes... 

Writing at 0x0004b9af [=====================>        ]  74.6% 131072/175801 bytes... 

Writing at 0x0005563d [========================>     ]  83.9% 147456/175801 bytes... 

Writing at 0x0005afa9 [==========================>   ]  93.2% 163840/175801 bytes... 

Writing at 0x0005f4d0 [==============================] 100.0% 175801/175801 bytes... 
Wrote 324816 bytes (175801 compressed) at 0x00010000 in 3.7 seconds (701.0 kbit/s).
Hash of data verified.

Hard resetting via RTS pin...

Hey,
Thanks a lot for your reply !

I understand what's the problem, but how would I implement a fix please ?
I've never use c++ before and just going through trial and error until something works, but i really don't have an idea of how pointers works

I tried implemeting a buffer like that but i get the same problem, ie: red blinking light

// NOT WORKING

#include <Wire.h>

// OLED display 128px * 64px
#include <Arduino.h>
#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


// Accelerometer ADXL345
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

void float_to_string(float value, char* buffer, size_t len)
{
  dtostrf(value, 8, 2, buffer);
}

void display_accel_value(int display_x, int display_y, const char* prefix, const char* value, const char* suffix)
{
  // prefix                     // value                     // suffix
  u8x8.drawString(display_x, display_y, prefix );
  u8x8.drawString(display_x + 2, display_y, value );
  u8x8.drawString(display_x + 5, display_y, suffix);
  return ;
}


void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0);

  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    u8x8.drawString(0,1,"no ADXL345 detected");
    u8x8.drawString(0,2,"___________________________________");
    while(1);
  } else {
    u8x8.drawString(0,1,"ADXL345 sensor detected !");
    u8x8.drawString(0,2,"___________________________________");
  }
  accel.setRange(ADXL345_RANGE_16_G);
}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  /* Get a new sensor event */ 
  sensors_event_t event; 
  accel.getEvent(&event);

  char buffer[24];

  float_to_string(event.acceleration.x, buffer, sizeof(buffer));
  display_accel_value(0, 3, "X : ", buffer, " m/s²");

  float_to_string(event.acceleration.y, buffer, sizeof(buffer));
  display_accel_value(0, 4, "Y : ", buffer, " m/s²");

  float_to_string(event.acceleration.z, buffer, sizeof(buffer));
  display_accel_value(0, 5, "Z : ", buffer, " m/s²");

  u8x8.drawString(0,6,"___________________________________");

  float sum = abs(event.acceleration.x) + abs(event.acceleration.y) + abs(event.acceleration.z);
  float_to_string(sum, buffer, sizeof(buffer));
  display_accel_value(0, 7, "Sum : ", buffer, " m/s²");

  delay(100);
}

Thanks a lot in advance !

The way you have the buffer should work ok, although at that point putting dtostrf() in a function seems like more trouble than it is worth.

Looking at the code again, the problem may be that you are using the display in setup() before setting a font with setFont(). I tried that on an UNO and get random pixels instead of characters on the display, it appears there is no default font in u8x8. In your working code, you only use the display in setup() if the ADXL345 is not found, so the display is not normally used.

With that in mind, and considering this is a runtime error, the normal way to proceed would be to comment-out sections until your code does run normally.

Since in the last working code there is a perfectly good way of doing it already.