0

I've written a pair of sketches for two NodeMCUs to implement a noise meter. The master MCU voltage samples off an opamp's output pin and periodically digests 500 samples at a time into an RMS-type calculation. Every 500ms or so, when it has accumulated 10 of those RMS samples, it sends off a packet with a timestamp and checksum to the slave MCU. This mostly works -- It's been running for about 4 and a half hours without a RST. However, I added a bit of logic recently to request an updated value from the slave and now I'm having trouble with the watchdog timer resetting the master MCU. These resets lose anywhere from a single packet to about 2 minutes of data.

NOTE: WiFi is disabled on this master MCU using a preinit function.

I've done some trial-and-error, including:

  • adding delay(1) to allow housekeeping and interrupts but this seems to introduce other instabilities
  • add calls to system_soft_wdt_feed() which has very little explanation in the docs.

Given that the problem is infrequent, it's quite difficult to reproduce the conditions for it to happen. There appears to be some perfect storm of unusual conditions that cause it to trigger. So my question is this:

Is there some way to determine from the serial monitor output where the watchdog timer is firing? And a follow-on question what does this wdt output (boot mode, csum, etc) mean? Here are a handful of watchdog timer messages I see in the serial monitor when the reset happens:

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

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
--
 ets Jan  8 2013,rst cause:4, boot mode:(3,2)

wdt reset
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld

As you can see, the RST output seems quite consistent, I just have no idea how to locate the point in my code where code execution goes on too long. The docs here have a stack trace associated with these resets if they are triggered from the software watchdog, but my serial monitor output does not have these stack traces, which suggests that it's the hw watchdog that's doing it. That page says:

Please note that for restarts initialized by h/w wdt, there is no stack trace to help you identify the place in code where the lockup has happened. In such case, to identify the place of lock up, you need to rely on debug messages like Serial.print distributed across the application.

Sadly, I don't know how wise it is to use Serial.print in my loop. The code inside my loop() completes in an average of about 5 microseconds so the output might be extremely verbose. In practice, adding Serial.print commands to track things tends to destabilize the sketch even more, dwarfing the problem I'm trying to solve.

The sketch is pretty lengthy, but its code is here. I've removed the comments for brevity, but it's still about 500 lines. I'm happy to post that code in this post, but worry it might make this post too long.

EDIT: If this is indeed the hardware watchdog that's firing, I would add a question: Is it possible to disable the hardware watchdog or somehow adjust its behavior? I am certain that my app is not locked up because its output continues to be communicated to the slave which posts the samples to a web server. Is the only solution to allow the loop function to complete more frequently?

EDIT: I added a timer which checks micros() at beginning and tracks the maximum amount of time to execute the loop. Usually, this is less than 2500 microseconds, although in one case it took 100ms -- but this did not cause a watchdog reset. The hardware watchdog reset doesn't appear to be related to how much time it takes to execute my loop function. It's something else.

EDIT: I updated my ESP8266 core to 2.7.2 and this did not solve the problem. I would add an additional question: Why is the hardware timer firing and not the software timer?. I have not disabled the software watchdog, and I have no indications that there are any infinite loops preventing completion of the main loop() routine.

  • 1
    system_soft_wdt_feed appears to be related to some type of a software watchdog timer ... that particular command pospones the software WDT reset ... i have a suspicion that it is different from the hardware WDT ... it is unclear if the software WDT triggers the hardware WDT – jsotola Jul 13 at 1:17
  • @jsotola I agree. It would appear from the docs here that software watchdog resets come with a stack trace, but hw wdt resets do not. Also, I have tried numerous calls to system_soft_wdt_feed() and these don't seem to remedy the problem. Sounds like hw watchdog to me, too. Is there any way to disable it? Or appease it somehow? – S. Imp Jul 13 at 1:20
  • googled esp8266 feed watchdog ... found this ... techtutorialsx.com/2017/01/21/esp8266-watchdog-functions – jsotola Jul 13 at 1:39
  • @jsotola I've read that, and it mostly just refers back to the docs i linked. It does provide a bit of additional detail -- e.g., the argument to ESP.wdtEnable() isn't even used -- but it does not provide any detail about how to pinpoint the code where timeouts are happening, or how hw wdt works or how to adjust its behavior. – S. Imp Jul 13 at 2:16
  • 1
    it shows you that disabling the software WDT allows the hardware WDT to take over .... it also shows you how to feed the hardware watchdog .... feed the watchog at the begining of loop() ... if that is not enough, feed near middle of loop() also .... otherwise time your loop and find out how much time various parts use – jsotola Jul 13 at 2:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.