Soft WDT reset - NodeMCU

Hi,

I'm working on a project, the idea is to have a stepper motor lock/unlock my door.

However, now in my developing phase I've runned into a Soft WDT reset issue.

void lockDoor() {
  while(digitalRead(lockedSensor) != LOW) {
    stepper.turnClockwise(2);
  }
  Serial.println("Door locked!");
}

This is my lock door function, the idea is to have the motor stop turning once the button (lockedSensor) is pressed.
But right now, when the stepper motor have turned about 180 degree's I get a Soft wdt reset...

This is the error:

Soft WDT reset


ctx: cont
sp: 3ffef160 end: 3ffef370 offset: 01b0

>>>stack>>>
3ffef310:  3fffdad0 000003e7 3ffee2e8 402023db
3ffef320:  3ffe863c 3ffee320 00000000 4020241f
3ffef330:  402018fa 000003e8 3ffee320 40202632
3ffef340:  3fffdad0 3ffee320 00000000 4020269c
3ffef350:  feefeffe 00000000 3ffee33c 402014e8
3ffef360:  feefeffe feefeffe 3ffee350 402021e4
<<<stack<<<

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

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v3ffe8468
~ld

Please help?

main code:

#include "Arduino.h"
#include "WiFiClient.h"
#include "ESP8266WiFi.h"
#include "Stepper28byj48.h"

Stepper28byj48 stepper(D5, D6, D7, D8);

const int led = D0;
const int button = D2;
const int lockedSensor = D1;

int switchstate = 0; //State of the "checkIfLocked" button

void setup() {
  Serial.println("Initializing...");
  Serial.begin(115200);
  pinMode(button, INPUT_PULLUP);
}

void lockDoor() {
  while(digitalRead(lockedSensor) != LOW) {
    stepper.turnClockwise(2);
  }
  Serial.println("Door locked!");
}

void loop() {
  Serial.println("Close door in:");
  for(int i=3; i>0;i--) {
    Serial.print(i);
    Serial.print("..");
    delay(1000);
  }
  Serial.println("");
  lockDoor();
}

Stepper library:

#include "Arduino.h"
#include "Stepper28byj48.h"

Stepper28byj48::Stepper28byj48(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4) {
  IN1 = pin1;
  IN2 = pin2;
  IN3 = pin3;
  IN4 = pin4;
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  direction = true;
  steps = 0;
  stepsLeft = 0;

}
void Stepper28byj48::setDirection(){
  if(direction==1){ steps++;}
  if(direction==0){ steps--; }
  if(steps>7){steps=0;}
  if(steps<0){steps=7;}
}

void Stepper28byj48::stepper(int xw){
  for (int x=0;x<xw;x++){
    switch(steps){
       case 0:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, HIGH);
       break;
       case 1:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, HIGH);
         digitalWrite(IN4, HIGH);
       break;
       case 2:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, HIGH);
         digitalWrite(IN4, LOW);
       break;
       case 3:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, HIGH);
         digitalWrite(IN3, HIGH);
         digitalWrite(IN4, LOW);
       break;
       case 4:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, HIGH);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, LOW);
       break;
       case 5:
         digitalWrite(IN1, HIGH);
         digitalWrite(IN2, HIGH);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, LOW);
       break;
         case 6:
         digitalWrite(IN1, HIGH);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, LOW);
       break;
       case 7:
         digitalWrite(IN1, HIGH);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, HIGH);
       break;
       default:
         digitalWrite(IN1, LOW);
         digitalWrite(IN2, LOW);
         digitalWrite(IN3, LOW);
         digitalWrite(IN4, LOW);
       break;
     }
    setDirection();
    }
  }

void Stepper28byj48::resetStepper() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

void Stepper28byj48::runStepper(int degree) {
  long calculateSteps = 4095 / 360;
  calculateSteps *= degree;
  stepsLeft = calculateSteps;
  while(stepsLeft > 0){
    currentMillis = micros();
    if(currentMillis - lastTime >= 1000){
      stepper(1);
      lastTime = micros();
      stepsLeft--;
    }
  }
  resetStepper();
}

void Stepper28byj48::runStepper() {
  stepsLeft = 4095;
  while(stepsLeft > 0){
    currentMillis = micros();
    if(currentMillis - lastTime >= 1000){
      stepper(1);
      lastTime = micros();
      stepsLeft--;
    }
  }
  resetStepper();
  Serial.println("Turned one cycle");
}

void Stepper28byj48::turnClockwise(int degree) {
  direction = true;
  runStepper(degree);
}

void Stepper28byj48::turnClockwise() {
  direction = true;
  runStepper();
}

void Stepper28byj48::turnAntiClockwise(int degree) {
  direction = false;
  runStepper(degree);
}

void Stepper28byj48::turnAntiClockwise() {
  direction = false;
  runStepper();
}

I believe this is the cause:

albzn540:

  while(digitalRead(lockedSensor) != LOW) {
   stepper.turnClockwise(2);
 }

The ESP8266 is a little different than the standard Arduino boards in that it has the watchdog (WDT) turned on by default. If the watchdog timer isn't periodically reset then it will automatically reset your ESP8266. The watchdog is reset every time one of the following occurs:

  • Return from loop() (i.e., reach the end of the function)
  • You call delay()
  • You call yield()

If you have blocking code like the above then the watchdog may time out, resulting in your reset. So to fix this you can change the above code to:

  while(digitalRead(lockedSensor) != LOW) {
    stepper.turnClockwise(2);
    yield();
  }

You should do the same to any other blocking code (that doesn't call delay()) you might use. This is the most simple solution, but in general it's not a good idea to write blocking code so you might consider reworking your code to allow loop() to continue to run unimpeded.

4 Likes

Hi!

Thank you for your reply!

If I understand blocking code correcly, I could make an if statement instead? Would that correct the problem I'm having?

The if statement will make lockDoor() non-blocking but it will no longer work correctly unless you make the rest of your code also non-blocking because you will need to run lockDoor() multiple times to achieve the same behavior as your current code. The idea is that loop() is constantly running. You can see an example of this by comparing File > Examples > 01.Basics > Blink with File > Examples > 02.Digital > BlinkWithoutDelay. The former is blocking, the latter is non-blocking. The delay(1000) in loop() is blocking so this prevents other code from running while it's sitting there waiting out the delay. delay() doesn't cause WDT reset though because it automatically calls yield() to prevent that.

2 Likes

I see, thank you! :smiley:

Thanks a lot!!!
It was very useful!!

Thank you very much pert! I was stuck in my code because of it. Very useful tip!

If I use while loop, it causes Wdt reset . How to resolve this?

Rtwin_ad:
If I use while loop, it causes Wdt reset . How to resolve this?

Why didn't you read this?

pert:
The ESP8266 is a little different than the standard Arduino boards in that it has the watchdog(WDT) turned on by default. If the watchdog timer isn't periodically reset then it will automatically reset your ESP8266. The watchdog is reset every time loop() runs or you call delay() or yield() but if you have blocking code like the above then the watchdog may time out, resulting in your reset. So to fix this you can change the above code to:

  while(digitalRead(lockedSensor) != LOW) {

stepper.turnClockwise(2);
    yield();
  }



You should do the same to any other blocking code(that doesn't call delay()) you might use. This is the mos simple solution but in general it's not a good idea to write blocking code so you might consider reworking your code so that loop() continues to run unimpeded.

thanks man, this solved it for me. I am guessing that this yields back to the watchdog timer to reset? anyways I had seen the same error on my Wemos D1 and added "yield();" into my while code was doing a long interaction with a stepper motor. After that my ESP8266 stopped doing a full reset on long calls to the Stepper controller.

pert:

  while(digitalRead(lockedSensor) != LOW) {

stepper.turnClockwise(2);
    yield();
  }

Thanks!

You're welcome. I'm glad to hear it's working now. Enjoy!
Per

WDT and yield();
Interesting that.
I have been working on a NodeMCU NTP-related project.
I want it to "takeabreak()", a function of mine, and with non-blocking/millis() it would bomb every time -- like it was resetting back to setup()**. I tried delay(43200000) and it would stay there - never exiting. Changing that up, using a for loop there for minutes, each pass (720) being a delay(60000), works/-ed.

1 Like

Thank you really helped it :slight_smile:

Sklicko:
... but i have similar problem with Soft WDT reset.

Start a new thread. Few people are going to read a new post on a topic that is already solved.

hello i have the same problem i got soft wdt reset. im using esp8266 nodemcu and max30100. can anyon help me thanks.

*/
#include <CircularBuffer.h>
#include <MAX30100.h>
#include <MAX30100_BeatDetector.h>
#include <MAX30100_Filters.h>
#include <MAX30100_PulseOximeter.h>
#include <MAX30100_Registers.h>
#include <MAX30100_SpO2Calculator.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"

#define REPORTING_PERIOD_MS 1000

// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;

uint32_t tsLastReport = 0;

// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
Serial.println("Beat!");
}

void setup()
{
Serial.begin(115200);

Serial.print("Initializing pulse oximeter..");

// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
} else {
Serial.println("SUCCESS");
}

// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
// pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();

// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
Serial.print("Heart rate:");
Serial.print(pox.getHeartRate());
Serial.print("bpm / SpO2:");
Serial.print(pox.getSpO2());
Serial.println("%");

tsLastReport = millis();
}
}

kpol:
hello i have the same problem i got soft wdt reset. im using esp8266 nodemcu and max30100. can anyon help me thanks.

Start a new thread. Don't hijack an existing thread because you most likely won't even get read.

Please read "Read this before posting a programming question" at the top of the forum and post your sketch using code tags.