1

I'm running very basic code and my ESP8266 times out during the stepper motor function. I get a "Soft wdt Reset" about 1600 ms into the myStepper.step function call.

The program works for a MyStepper.setSpeed of 38, but not for 37. This happens on two out of two boards I've tried. Is there a way around this problem? I'm using the Arduino programming software, code is below.

#include <Stepper.h>

const int stepsPerRevolution = 200;  
unsigned long startT;

// initialize the stepper library:
Stepper myStepper(stepsPerRevolution, 14, 12, 13, 15); //D5, D6, D7 & D8

void setup() {
  // set the speed at in rpm:
  myStepper.setSpeed(37); //38 good (~1571 ms), 37 bad (~1614 ms)
  
  // initialize the serial port:
  Serial.begin(9600);
  Serial.println("Started stepper_oneRevolution_mk-------------------------");
}

void loop() {
  startT=millis();
  // step one revolution  in one direction:
  Serial.print("clockwise took: ");
  myStepper.step(stepsPerRevolution);
  Serial.println(millis()-startT);
  delay(1000);
}
ocrdu
  • 2,172
  • 6
  • 15
  • 22
Matt
  • 13
  • 3

2 Answers2

1

The Watchdog Timer is complaining you are hogging the processor for too long.

myStepper.step() is blocking, so other processes can't use the processor until the motor has finished moving.

During this time, processes like WiFi communication and managing the TCP/IP stack also can't run, and the Watchdog Timer is there to reset the ESP8266 in such cases.

You can avoid this by making the stepper motor move just a few steps per loop, and add a yield() if necessary, or up the speed so it makes a full rotation before the watchdog gets angry.

You could try a quick & dirty way by doing 20 steps, then a short delay() or a yield(), and do that 10 times in its own for loop. You would have to experiment to arrive at something that doesn't trigger the watchdog, and compensate the time measurements you do.

You could also use an Arduino or an ESP that has an extra core dedicated to the WiFi, or find a stepper library that isn't blocking.

ocrdu
  • 2,172
  • 6
  • 15
  • 22
  • Yuck! That is not what I was hoping to hear. It is a workaround and will make the code much more clumsy. – Matt Nov 05 '20 at 14:38
  • Such is life with the ESP8266. I have updated the answer, BTW. – ocrdu Nov 05 '20 at 14:47
  • Thanks, I was hoping to find a non blocking stepper motor call. Running in multiple loops can affect the sound and the fluidity of the movement. – Matt Nov 05 '20 at 15:24
  • Maybe there is another stepper library that does things differently. I remember seeing AccelStepper and Unistep2, but I can't remember if they are blocking or not. – ocrdu Nov 05 '20 at 16:08
  • Don't forget to accept the answer (if you accept the answer) so the question doesn't stay open. – ocrdu Dec 01 '20 at 02:38
1

This is how I solved this issue.

  • I could step the motor once in the time period allowed by watchdog
  • So instead of telling the motor to step 30 times
    • myStepper.step(stepsPerRevolution * 30);
  • I tell it to step 1 revolution, 30 times. :)
    • The key here is calling yield() between each revolution

Oversimplified

int steps = 30;
while(stepsTaken < steps){
    yield(); // Let other things run
    myStepper.step(-stepsPerRevolution * 1);
    stepsTaken++;
}

Yielding for ESP8266 (sparkfun)

More complete example. This is missing all the wifi and mqtt bits but should give you the gist.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
// D1 and D2 is set by the Board selection
// It will error as not defined if you have the wrong board 
// specified in the Arduino ID
#include <Stepper.h>

// I need to be able to complete this before watchdog runs
const int stepsPerRevolution = 800; 

// First Pin is Step
// Sec Pin is Dir
Stepper myStepper(stepsPerRevolution,D1,D2);


// you need to define your mqtt client, wifi ect.


// This is the callback you define for your mqtt client
// client.setCallback(callback);
void callback(char* topic, byte* message, unsigned int length) {
StaticJsonDocument<256> messageTemp;
deserializeJson(messageTemp, message, length);

if (String(topic) == "esp32/output") {
    const char* dir = messageTemp["dir"];
    int steps = messageTemp["steps"];
    int stepsTaken = 0;
    while(stepsTaken < steps){
      yield();
      if(String(dir) == "up"){
        Serial.println("up");
        myStepper.step(stepsPerRevolution * 1);
      }
      else if(String(dir) == "down"){
        Serial.println("down");
        myStepper.step(-stepsPerRevolution * 1);
      }
      stepsTaken++;
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(D1,OUTPUT); 
  pinMode(D2,OUTPUT);
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

}

styks
  • 3,193
  • 1
  • 23
  • 36