ESP8266 Soft WDT reset

Moin,

ich habe aktuell das Problem, dass mein Sketch mit einem “Soft WDT reset” aussteigt.
Ja, kenn ich, kommt davon, wenn der ESP nicht seinen eigenen Kram machen darf und zu lange davon abgehalten wird.
Dazu gibt es yield() damit er mal zwischendurch seinen Kram machen kann.

Nun hab ich mein Sketch mal laufen lassen, das klappt einige tausend Schleifendurchläufe, und plötzlich in unregelmäßigen Abständen: “Soft WDT reset”

Wenn der “Soft WDT reset” kommt, dann ist das Sketch immer in der “StepperShake” Prozedur.
Es finden ca. 70-130 “Turns” statt bis einmal der “StepperShake” kommt.
Der erste “Soft WDT reset” kam beim 35. Shake.
Der ESP startet dann neu.
Der zweite “Soft WDT reset” kam beim 17. Shake.
Da sehe ich kein Muster.
Ich hätte ja vermutet dass der Fehler immer in der gleichen Periode auftaucht, aber es sieht mir relativ willkürlich aus.

Hier mal der Output vom Monitor auf den interessanten Bereich eingekocht:

.
.
.
Turn: 2524
Turn: 2525
Shake: 35

Soft WDT reset

ctx: cont 
sp: 3ffffd10 end: 3fffffd0 offset: 01b0

>>>stack>>>
3ffffec0:  3ffee8bd 00000002 3ffee7f9 40203346  
3ffffed0:  00000001 00000001 3ffee8bd 402017c9  
3ffffee0:  4010665c ffe00000 00000002 3ffee7f8  
3ffffef0:  80000000 40d1b6bf 00000001 3ffee7f8  
3fffff00:  80000000 40e1b6bf ffffffff 40203229  
3fffff10:  00000000 00000000 3ffee848 4020351e  
3fffff20:  3ffe84f8 3ffe84e8 3ffee7f8 4020378d  
3fffff30:  3ffe84f8 3ffe84e8 3ffee7f8 40203a07  
3fffff40:  3ffe84f8 3ffe84e8 3ffee7f8 40203a2c  
3fffff50:  00000103 3ffee884 00000fff 40202f20  
3fffff60:  000002ce 3ffee91c 3ffee7f8 4020433a  
3fffff70:  00000103 48f42400 3ffee7f8 3ffee890  
3fffff80:  00000103 3ffee884 00000fff 4020318a  
3fffff90:  3ffe84e4 3ffee88c 3ffe84f8 3ffee940  
3fffffa0:  00000000 00000000 00000001 3ffee940  
3fffffb0:  3fffdad0 00000000 3ffee938 4020430c  
3fffffc0:  feefeffe feefeffe 3ffe8608 40100739  
<<<stack<<<
Z+k⸮⸮Z⸮⸮
Turn: 1
Turn: 2
Turn: 3
Turn: 4
.
.
.
Turn: 1270
Turn: 1271
Turn: 1272
Turn: 1273
Shake: 17

Soft WDT reset

ctx: cont 
sp: 3ffffd00 end: 3fffffd0 offset: 01b0

>>>stack>>>
3ffffeb0:  fffffffb 00000001 0000000c 4010668d  
3ffffec0:  3ffee8bd 00000002 3ffee7f9 40203346  
3ffffed0:  00000001 00000001 3ffee8bd 402017c9  
3ffffee0:  4010665c 80080000 00000002 3ffee7f8  
3ffffef0:  40000000 40c11fd1 00000005 3ffee7f8  
3fffff00:  40000000 40d11fd1 fffffffa 40203229  
3fffff10:  00000000 00000000 3ffee848 4020351e  
3fffff20:  3ffe84f8 3ffe84e8 3ffee7f8 4020378d  
3fffff30:  3ffe84f8 3ffe84e8 3ffee7f8 40203a07  
3fffff40:  3ffe84f8 3ffe84e8 3ffee7f8 40203a2c  
3fffff50:  000000fa 3ffee884 00000fff 40202f20  
3fffff60:  000002ce 3ffee91c 3ffee7f8 4020433a  
3fffff70:  000000fa 48f42400 3ffee7f8 3ffee890  
3fffff80:  000000fa 3ffee884 00000fff 4020318a  
3fffff90:  3ffe84e4 3ffee88c 3ffe84f8 3ffee940  
3fffffa0:  00000000 00000000 00000001 3ffee940  
3fffffb0:  3fffdad0 00000000 3ffee938 4020430c  
3fffffc0:  feefeffe feefeffe 3ffe8608 40100739  
<<<stack<<<
⸮⸮⸮%⸮
Turn: 1
Turn: 2
Turn: 3
Turn: 4
Turn: 5
Turn: 6
.
.
.

Da ist die Prozedur “StepperShake” doch aber schon völlig ausgestopft mit yields()

Was kann ich denn noch tun, damit es stabiler läuft?

Danke und lieben Gruß,
Chris

Und hier das ganze Sketch:

#include <AccelStepper.h>
#include <AS5600.h>
#define STEPpin  14
#define DIRpin   12
#define Microstepping 16                    // Stepperdriver is set to 1/n microsteps (here 1/4)
#define StepperStepsPerRevolution 200           //one revolution of the stepper is 200 steps
int StepsPerRevolution = (StepperStepsPerRevolution * Microstepping);       // results in 800 steps per one revolution of the stepper
int Pos[4] = {115, 1129, 2153, 3177}; // Der Winkelsensor hat Werte für 0-360° Sensorradposition von 0-4095. Diese vier Werte in dem Array markieren im Wertebereich 0-4095 die Positionen der vier Mulden im Sensorrad
int RelativeStep[4];
int StartupPos;
int EncoderPos;
int StepperPos;
int StepperOffset;
int ErrorThreshold = 30;  //Fehlerschwelle Stepper
int PosErrorCount; //Fehlerzähler Stepper
int MaxAllowedError = 10;  //maximale Fehlerzahl
int StepperShakeCount;
int TurnCount;
int n;
unsigned long currentMillis;
bool AlternateLoop = true;

unsigned long previousMillis = 0;
unsigned long stepperMillis = 0;
const long PosMeasureInterval = 50;            //alle 100 ms wird die Position des Sensorrads gemessen
AS5600 encoder;

AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);

void StepperShake() {
  StepperShakeCount ++;
  Serial.print("Shake: ");
  Serial.println(StepperShakeCount);
  stepper.setCurrentPosition(0);
  stepper.setMaxSpeed(100000);
  stepper.setAcceleration(100000);
  stepper.runToNewPosition(-10);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.setMaxSpeed(150000);
  stepper.setAcceleration(150000);
  stepper.runToNewPosition(-10);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.setMaxSpeed(250000);
  stepper.setAcceleration(250000);
  stepper.runToNewPosition(-10);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.setMaxSpeed(350000);
  stepper.setAcceleration(350000);
  stepper.runToNewPosition(-10);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.setMaxSpeed(500000);
  stepper.setAcceleration(500000);
  stepper.runToNewPosition(-10);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
  stepper.runToNewPosition(-100);
  yield();
  stepper.runToNewPosition(100);
  yield();
}
void StepperFindOrigin() {
  stepper.setCurrentPosition(0);
  stepper.setMaxSpeed(1000); // 10000 ist wunderbar
  stepper.setAcceleration(1000); // 1000 scheint hier ein relalistischer Wert zu sein, 100000 ist schön schnell, 200 ist schön langsam
  RelativeStep[0] = (map(Pos[1], 0, 4095, 1, StepsPerRevolution)) - (map(Pos[0], 0, 4095, 1, StepsPerRevolution));
  RelativeStep[1] = (map(Pos[2], 0, 4095, 1, StepsPerRevolution)) - (map(Pos[1], 0, 4095, 1, StepsPerRevolution));
  RelativeStep[2] = (map(Pos[3], 0, 4095, 1, StepsPerRevolution)) - (map(Pos[2], 0, 4095, 1, StepsPerRevolution));
  RelativeStep[3] = StepsPerRevolution - (map(Pos[3], 0, 4095, 1, StepsPerRevolution)) + (map(Pos[0], 0, 4095, 1, StepsPerRevolution));
  StartupPos = encoder.getPosition();
  if ( (Pos[0] != StartupPos) && (Pos[1] != StartupPos) && (Pos[2] != StartupPos) && (Pos[3] != StartupPos) ) {
    if (Pos[0] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[0] - StartupPos, 0, 4095, 1, StepsPerRevolution));
    }
    else if (Pos[1] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[1] - StartupPos, 0, 4095, 1, StepsPerRevolution));
    }
    else if (Pos[2] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[2] - StartupPos, 0, 4095, 1, StepsPerRevolution));
    }
    else if (Pos[3] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[3] - StartupPos, 0, 4095, 1, StepsPerRevolution));
    }
    else {
      stepper.runToNewPosition(map(4095 - StartupPos + Pos[0], 0, 4095, 1, StepsPerRevolution));
    }
  }
  EncoderPos = encoder.getPosition(); // get the absolute position of the encoder
  StepperPos = stepper.currentPosition(); // get the position of the stepper
  StepperOffset = EncoderPos - map(StepperPos, 1, StepsPerRevolution, 0, 4095);
  stepper.setMaxSpeed(10000); // 10000 ist wunderbar
  stepper.setAcceleration(100000); // 1000 scheint hier ein relalistischer Wert zu sein, 100000 ist schön schnell, 200 ist schön langsam
}
void setup()
{
  Wire.setClock(400000L); //setzt die I²C Taktfrequenz auf 400kHz
  Serial.begin(9600);
  delay(100);
  Serial.println("");
  StepperFindOrigin();
}
void loop() {
  currentMillis = millis();
  if (AlternateLoop)  // mit diesem Trick kann man pro Loop Durchlauf entweder einen Zweig oder einen anderen Zweig durchlaufen lassen, hier ist der 1. Zweig aktiv
  {
    if (stepper.distanceToGo() == 0)
    {
      stepperMillis = currentMillis;
      n ++;
      TurnCount ++;
      Serial.print("Turn: ");
      Serial.println(TurnCount);
      if (n > 3) {
        n = n - 4;
      };
      AlternateLoop = false;
    }
  } else {   // hier ist der 2. Zweig aktiv
    if (currentMillis - stepperMillis >= 500)  // 500ms in einer der 4 Positionen warten, hier wird später die Farbe gemessen
    {
      stepper.move(RelativeStep[n]);
      AlternateLoop = true;
    }
  }
  stepper.run();
  //*************** Prozedur Positionsabgleich begin ***************
  if (currentMillis - previousMillis >= PosMeasureInterval) {
    previousMillis = currentMillis;
    EncoderPos = encoder.getPosition(); // get the absolute position of the encoder
    StepperPos = stepper.currentPosition(); // get the position of the stepper
    //Serial.print("SOLL: ");
    //Serial.print((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095);
    //Serial.print("   IST: ");
    //Serial.print(EncoderPos);
    //Serial.print("   DIFFERENZ: ");
    //Serial.print((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095 - EncoderPos);
    if (((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095 - EncoderPos < -ErrorThreshold )  || ((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095 - EncoderPos > ErrorThreshold )) {
      PosErrorCount++;  //Wenn die Positionsabweichung ausserhalb der erlaubten Toleranz ist, den Fehlerzähler um 1 erhöhen
    }
    //Serial.print("   PosErrorCount: ");
    //Serial.println(PosErrorCount);
    if (((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095 - EncoderPos > -ErrorThreshold )  && ((StepperOffset + map(StepperPos, 1, StepsPerRevolution, 0, 4095)) % 4095 - EncoderPos < ErrorThreshold )) {
      PosErrorCount = 0;  //Wenn die Positionsabweichung innerhalb der erlaubten Toleranz ist, den Fehlerzähler auf 0 setzen
    }
    if (PosErrorCount > MaxAllowedError) { //Wenn die Fehlerzähler mehr als 5 ist, dann Fehlerprozedur aufrufen
      StepperShake();
      StepperFindOrigin();
      PosErrorCount = 0;
    };
  }
  //*************** Prozedur Positionsabgleich end ***************
}

Hi,

kleiner Schuss ins Blaue:

versehe mal die hohen Werte in der Funktion StepperShake() mit L oder UL, z.B.:

  stepper.setMaxSpeed(250000UL);
  stepper.setAcceleration(250000UL);

Ob das den Fehler behebt kann ich nicht sagen, allerdings weiß ich auch nicht ob es überhaupt ein Problem ist, zumindest machen fehlende Deklarationen bei Berechnungen bei hohen Zahlen Probleme (int > 32767 = Überlauf). Ich lasse mich aber auch gerne eines Besseren Belehren. :smiley:

Die Idee verstehe ich.
Aber müsste der Fehler dann nicht immer an der gleichen Stelle kommen?

Das ist eine sehr gute Frage, dafür blicke ich bei deinem Sketch bei weitem nicht durch, was nicht unbedingt an deinem Code liegen mag... :wink: Vielleicht helfen dir mehr Serial.print(); in StepperShake().

Ein Blick in die Doku zu Accelstepper hätte die Problemlösung sicher beschleunigt:

runToNwePosition() blockiert bis zum Erreichen der Position.
Da helfen die yield() zwischen den Aufrufen auch nicht.

Gruß Tommy

Das weiss ich schon, dass runToNewPosition den Sketch blockiert.
Ich hätte aber nicht gedacht, dass die auch den WatchDog blockiert. Das bedeutet in Accelstepper fehlt das yield()? (oder hab ich das nicht richtig verstanden und selbst das würde nichts nützen, weil die Loop meines Sketches warten muss?)

Wie kann ich Abhilfe schaffen? (Ich brauche runToNewPosition)

Warum nicht mit moveTo und run?

Gruß Tommy

Weil ich dann mehr Schleifen bauen muss und das mit Runtonewposition schon fertig wäre.

Kann man sich jetzt überlegen, ob man mich für faul hält oder smart weil ich auf Fertiges zurückgreife, um mich mit dem Wesentlichen zu beschäftigen und weil es übersichtlicher ist. Ansichtssache.

Ich möchte ja auch was lernen. Daher stehen immernoch die Fragen im Raum:
Das bedeutet in Accelstepper fehlt das yield()?

Oder hab ich das nicht richtig verstanden und selbst das würde nichts nützen, weil die Loop meines Sketches warten muss?

Ich sehe das so, dass Accelstepper kein yield benötigt, wenn man die Lib richtig verwendet.
Wieso brauchst Du Schleifen? Du hast doch loop().

Gruß Tommy

Wieso brauchst Du Schleifen? Du hast doch loop().

Jetzt verunsicherst du mich.
Entweder ich weiss nicht wie es richtig geht, oder du hast meinen Sketch nicht gesehen?!

Ich brauche die Bewegung in meiner Prozedur StepperShake.

Da ist noch keine Schleife drin.
Da müsste ich dann Schleifen reinbauen und immer schauen, ob der Stepper schon angekommen ist.
Erst wenn der Stepper angekommen ist darf die Prozedur doch fertig sein, damit es im Loop wieder weitergehen kann.
Oder stehe ich auf dem Schlauch und merke es nicht?!

Ich denke, ohne den Blick in die Doku zum Accelstepper wirst Du nur weiter im Nebel stochern.
Schau Dir die Beschreibung zu run() an. Es bringt Dir nichts, wenn wir sie lesen.

Gruß Tommy

Hi

Wenn jetzt eh schon blockierend geschrieben wurde und bei Runtonewposition der Wachhund zubeißt - warum nicht schnöde ein While-Konstrukt?

  • Zielposition setzen
  • while (stepstogo){
  • .run
  • yield();
  • }

So werden yield aufgerufen, Das reicht für drei Andere gleich mit ;).

MfG

Okay, hab ich genauso umgesetzt, aber nun ist das irre lang.

Der Stepper soll jeweils 3x 100 Schritte rückwärts und 100 Schritte vorwärts laufen.
Das soll 5x nacheinander mit steigender Geschwindigkeit (aktuell 100000, 150000, 250000, 350000, 500000, kann aber auch was anderes sein, z.B. linear ansteigend oder quadratisch oder ähnlich …..) geschehen.

Nun würde ich das gerne aus mehreren verschachtelten Schleifen zusammenbauen.
Allerdings gelingt mir das nicht so recht. Irgendwie fehlt mir die richtige Idee das umzusetzen.

void StepperShake() {
  StepperShakeCount ++;
  Serial.print("Shake: ");
  Serial.println(StepperShakeCount);
  stepper.setCurrentPosition(0);
  stepper.setMaxSpeed(100000);
  stepper.setAcceleration(100000);
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.setMaxSpeed(150000);
  stepper.setAcceleration(150000);
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.setMaxSpeed(250000);
  stepper.setAcceleration(250000);
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.setMaxSpeed(350000);
  stepper.setAcceleration(350000);
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.setMaxSpeed(500000);
  stepper.setAcceleration(500000);
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(-100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
  stepper.moveTo(100);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
    yield();
  }
}

Lieben Gruß,
Chris