Wemos Watchdog Timer resets

I wrote some code which runs just fine on Arduino. I then moved it to Wemos D1 and added WiFi functionality but from time to time I get watchdog timer resets occurring.
I have read about blocking and non blocking functions and believe that it may be something to do with those.
In my code I make use of delay(1000) to wait a second - thinking that was the culprit I created a routine to replace delay() which I thought would cure the problem as follows:

void nonBlock()
{
time_now = millis();
while(millis() <time_now + period){
//waiting!
}
}

When I load the code - it runs but the problem is far worse - so I have obviously missed something. Is the while function also blocking?

I just want to call something that waits without blocking. Am I heading in the wrong direction? I note that most examples of non-blocking code tend to do things in the main program loop and check for the right time to do things. At present I don’t think my existing code would work that way.

I have attached the full program which is cobbled together and no doubt full of bad practices ( I am very much a beginner) for reference but at the moment, if I use delay(1000) instead of calling nonBlock() - it runs for most of the time without resetting. Changing to the delay - it resets every few seconds.

Dueal_Nixie_Experiment_NodeMCU_NTP_11_11_Non-Blocking.ino (14.8 KB)

I’m not familiar with ESP based devices. But the below is just as blocking as an ordinary delay.

void nonBlock()
{
time_now = millis();
while(millis() <time_now + period){
  //waiting! 
}
}

Possibly not the neatest solution but maybe you can kick the watchdog in that while-loop?

It is important when using the WDT to reset it periodically to prevent undesired resets. If the reset period is set too low, lengthy functions can cause unscheduled resets, delay() most certainly. Simply embed a wdr() anywhere that you think there might be a problem. A simple macro I use, which only consumes 1 clk cycle is,

#define wdr()       __asm__ __volatile__ ("wdr \n")

If you include <avr/wdt.h> this macro is available as wdt_reset() - same asm instruction.

delay feeds the watchdog and the esp8266 doesn't reset. the while loop you use, causes a watchdog reset

. . . or in any loop which may run for more than a few hundred mS , add a yield() statement. This is effectively a delay(0) and resets the software watchdog timer.

never too late :

#include <avr/wdt.h>

void setup()
{
.
.
.
.
wdt_enable(WDTO_2S);
}

void loop()
{
wdt_reset();
.
.
.
.
}

/* your nonBlock() is exaclty a delay() :

void nonBlock()
{
time_now = millis();
while(millis() <time_now + period)
{
//waiting!
}
}

*/

// but this non Block() will work …

void nonBlock()
{
uint16_t period = 1000; //period from 1 to 64.000 ms
uint32_t time_now = millis();
while(millis() < time_now + period)
{
wdt_reset(); //waiting!
}
}

Or better

void nonBlock(uint16_t period ) //period from 1 to 64.000 ms

{
uint32_t time_now = millis();
while(millis() < time_now + period)
{
wdt_reset(); //waiting!
}
}

dritan:
never too late :

#include <avr/wdt.h>

void setup()
{
.
.
.
.
wdt_enable(WDTO_2S);
}

this is for AVR. OP has esp8266

void setup()
{
.
.

ESP.wdtEnable(WDTO_4S);
}

void loop()
{
.
.
.
nonBlock(10000); // period from 1 to 64.000 ms like delay(10000)
}

void nonBlock(uint16_t period)
{
uint32_t time_now = millis();
while(millis() < time_now + period)
{
wdt_reset(); //waiting!
}
}

dritan:
void setup()
{
.
.

ESP.wdtEnable(WDTO_4S);
}

void loop()
{
.
.
.
nonBlock(10000); // period from 1 to 64.000 ms like delay(10000)
}

void nonBlock(uint16_t period)
{
uint32_t time_now = millis();
while(millis() < time_now + period)
{
wdt_reset(); //waiting!
}
}

on esp8266 core the watchdog reset is done by the core.