ESP8266 NodeMCU (CH340) Random Reboots with AHT10 Sensor Code

Description:

Hello everyone,

I am facing an issue with my NodeMCU board (ESP8266 with CH340 USB-to-Serial chip). After uploading code for the AHT10 temperature and humidity sensor, the board frequently reboots or disconnects from USB. I’m hoping to get some advice on troubleshooting this problem.

Hardware Details:

  • Board: NodeMCU ESP8266 (CH340)
  • Sensor: AHT10 (temperature and humidity sensor)
  • Connections: The board is powered via USB, and only the AHT10 sensor is connected. SDA is on D2, SCL is on D1.

Problem Description:

  1. After flashing the firmware (using esptool.py) and uploading the AHT10 sensor test code, the board starts to behave inconsistently:
  • It often reboots or disconnects from USB.
  • Sometimes I have to press the Reset or Flash button multiple times or unplug/replug the USB cable to make it work temporarily.
  1. When the board does work for a short while, it prints correct temperature and humidity data to the Serial Monitor.

Here’s an example of the Serial Monitor output when it starts to fail:

lua

CopyEdit

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Soft WDT reset

Exception (4):
epc1=0x40201068 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffe50 end: 3fffffd0 offset: 0160
3fffffb0:  feefeffe feefeffe 3ffee714 402022bc  
3fffffc0:  feefeffe feefeffe 3fffdab0 40100f91  
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3424, room 16 
tail 0
chksum 0x2e
load 0x3fff20b8, len 40, room 8 
tail 0
chksum 0x2b
csum 0x2b
v000436c0
~ld

Occasionally, after several reset attempts, I see correct sensor readings like this:

makefile

CopyEdit

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3424, room 16 
tail 0
chksum 0x2e
load 0x3fff20b8, len 40, room 8 
tail 0
chksum 0x2b
csum 0x2b
v000436c0
~ld
Temperature: 28.61 °C
Humidity: 69.79 %
Temperature: 28.68 °C
Humidity: 75.04 %
Temperature: 28.77 °C
Humidity: 74.64 %
Temperature: 28.80 °C
Humidity: 71.56 %
Temperature: 28.76 °C
Humidity: 68.53 %
Temperature: 28.71 °C
Humidity: 66.23 %
Temperature: 28.65 °C
Humidity: 64.54 %
Temperature: 28.60 °C
Humidity: 63.48 %
Temperature: 28.56 °C
Humidity: 62.78 %
...

What I’ve Tried:

  1. Checked connections: All sensor wires are securely connected.
  2. Flashed firmware: Used esptool.py to reflash the firmware. Flashing completes successfully.
  3. Tried different USB cables: Tested with high-quality cables to ensure stable power and data.
  4. Modified code: Added delay(1000) at the beginning of setup() and yield() in loops, but the issue persists.

Additional Notes:

  • Power Supply: The board is powered via USB. I’ve tested it with different USB ports and external power supplies (5V, 1A).
  • Arduino IDE Settings:
    • Flash Size: 4M (FS:2MB OTA:~1MB)
    • CPU Frequency: 80 MHz
    • Upload Speed: 115200
  • Exception Decoder: I’m not familiar with how to interpret the exception logs. Any help with decoding this would be appreciated.

Questions:

  1. Could this be a hardware issue (e.g., a faulty NodeMCU board or sensor)?
  2. Is there a way to fix the rebooting and USB disconnection problem?
  3. What other troubleshooting steps should I try?

Any guidance or suggestions would be greatly appreciated!

Thank you in advance.


Feel free to copy, paste, and adjust this post as needed for the forum!

Your sketch (which you didn't include) is going too long without calling yield() and feeding the watchdog.

I imagine if you put the exception information through the exception decoder it'd likely narrow down where in your code it's taking too long without yielding.

#include <Adafruit_AHT10.h>

Adafruit_AHT10 aht;

void setup() {
  Serial.begin(115200);
  Serial.println("Adafruit AHT10 demo!");

  if (! aht.begin()) {
    Serial.println("Could not find AHT10? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT10 found");
}

void loop() {
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
  Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");

  delay(500);
}

ode does not need to explicitly call yield() because it uses delay(500) in the loop.

Why is yield() not required?

  • delay() automatically calls yield(): When you use delay(), it allows the ESP8266 system to run background tasks (such as WiFi and system services).
  • As a result, the Watchdog Timer (WDT) is fed, preventing any resets.

When is yield() needed?

  • If you write a loop or block of code that takes a long time to execute without calling delay() (e.g., in a long-running while or for loop), you should call yield() manually to avoid a WDT reset.

Not to disagree with ChatGPT, but it's neglecting the time it takes to do the conversion and print the results. The latter is trivial, but you don't know how long the former takes. The fact that the watchdog is barking indicates that something is taking quite a while.

I see you totally ignored the suggestion to use the exception decoder and find out where the watchdog was barking. That's your prerogative. If you don't want to find where the problem is, that's fine.

But if you're using ChatGPT as an authority, I'm out of here. Good luck.

I will be using the ESP Exception Decoder, and I’m sorry if I’ve caused any inconvenience. I’m trying all possible solutions myself, and I’m using ChatGPT as a consultant. I would appreciate it if you could continue to assist me in the next post.

This program may help in finding the problem

// FOR TEST
/*
   Error codes for Wire.endTransmission
    0: success
    1: data too long to fit in transmit buffer (32 byte max)
    2: received NACK on transmit of address
    3: received NACK on transmit of data
    4: other error (???)
*/

#include <Wire.h>
byte I2CError;

void setup()
{
  Wire.begin();
  Wire.setClock(100000);  // Make sure SCL is 100kHz
  Serial.begin(115200);
  I2CError = 0;
}

void loop()
{
  Wire.beginTransmission(0x38);

  I2CError = Wire.endTransmission(true);
  if (I2CError == 0)
    Serial.println ("OK ");
  else
  {
    Serial.print ("Error      ");
    Serial.println (I2CError);
  }
  while (I2CError != 0) delay(1000);
  delay (2000);

}

thanks , i will try it