Help with strange behavior in for loop

Hi guys,

Never used the forums before but simply cannot figure this one out after a couple of days of research.
My guess is that I am doing something really stupid in the for loop of there are conflicts or complications with the library’s on hw used in this project

Actual behavior:
For loops (near the end of the sketch) wont run without Serial.println() included.
When included sketch runs fine!

Expected behavior:
for loop to run without the need the include Serial.println()

Additional:
Same behavior with while loop.

Really need some guidance on this one as im concerned the code is not stable in its current state and will lead to additional issues at a later stage.

Cheers,
Rob

Arduino 1.8.13
NodeMCU 8266

BasicAutoBlinds_v6_loopIssue.ino (11.6 KB)

Explain why you thin they "don't run". Because the stepper isn't running?

Most likely Serial.println() is introducing a delay.
Replace Serial.println() with an explicit delay() statement.

What happens now?

Sorry yes, i guess i left that bit out…

The stepper motor does not rotate, only nudge which i assume it moved by 1 step (there are 2048 steps for 1 rotation for this stepper so its barely noticeable)

replacing: Serial.println(“running movedown”);
with: delay(10); motor will not run, loop jumps to end (myStepper.disableOutputs():wink:
with: delay(100); motor will not run, loop jumps to end (myStepper.disableOutputs():wink:
with: delay(1000); motor will not run, loop jumps to end (myStepper.disableOutputs():wink:

To be honest i dont think i can use delays with the included library’s.

The strange thing is im passing 1000 into this loop (movedown(int dist)) which works fine with Serial.print()!
but even with the delays and nothing happening i would expect the loop to last delay(10)1000 or delay(1000) 1000 long but they compelte instantly like its being skipped unless the Serial.print is included.

Changes made to one loop:

void movedown(int dist) {
Serial.println(“running movedown”);
for (int i = 0; i <= dist; i++) {
//buttonStateDown = digitalRead(buttonPinDown); // this can be ignored
//if (buttonStateDown == HIGH) {
//Serial.println(“running movedown”); // works fine with this in place
delay(1000); does nothing, not even cause a delay
myStepper.setSpeed(500);
myStepper.run();
ESP.wdtFeed();
// } ignore
}
myStepper.disableOutputs(); // seems to jump to here and disable the motor straight away.
}

Thanks for the suggestion but it does not address the problem.

More members will see your code if posted properly. Read the how to use this forum-please read sticky to see how to properly post code. Remove useless white space and format the code with the IDE autoformat tool (crtl-t or Tools, Auto Format) before posting code.

for (int i = 0; i <= dist; i++) { Why “less-than-or-equal”?

I don't think "myStepper.run();" does what you think it does. As far as I can tell you have not told the stepper where you want it to move to so the .run() doesn't have anything to do. Perhaps you want ".runSpeed()" if you don't care how far it gets or, if you want it to move the specified number of steps:

  // Move forward the specified number of steps
  myStepper.runToNewPosition(myStepper.currentPosition() + dist);

I'm not sure how the Serial output changed anything.

Guess i had just taken the standard loop example from the Arduino website at the time.
Corrected to:

for (int i = 0; i < dist; i++) {

Does not correct the loop with or without the delay:

example:

void movedown(int dist) {
  Serial.println("running movedown");
  for (int i = 0; i < dist; i++) {
    delay(10);
    myStepper.setSpeed(500);
    myStepper.run();
    ESP.wdtFeed();

  }
  myStepper.disableOutputs();
}

Thanks for pointing this out.

Hi John,

I get what you are saying but i have to run the stepper in 1 step increments in a loop so that i can use ESP.wdtFeed to prevent reboot due to watchdog, as these loops will run for 5000 steps taking about 10 seconds to complete.
That is why i use: myStepper.run();

Ref

As stated, this works absolutely fine with Serial.print inside the for loop which i find so strange.

If you are going to tell me to just disable the wdt i have tried this already at the start of the void

Example with your suggestion will move the stepper correctly but cause reboot after 5 seconds or so...

void movedown(int dist) {
  Serial.println("running movedown");
  myStepper.runToNewPosition(myStepper.currentPosition() + dist);
  myStepper.disableOutputs();
}

example with wdtdisable / enable (which reboots on enable every time!):
If i have this written incorrectly or doing something stupid here place let em know.

void movedown(int dist) {
  Serial.println("running movedown");
  ESP.wdtDisable();
  myStepper.runToNewPosition(myStepper.currentPosition() + dist);
  myStepper.disableOutputs();
  ESP.wdtEnable(0);
}

If you are fighting the ESP watchdog timer, all you have to do is periodically call ANY delay function - delay() or delayMicroseconds(). I believe there may also be a yield() function, but not sure. So, try replacing your Serial.print with delayMicroseconds(1), or even delayMicroseconds(0), and see if that helps.

Regards,
Ray L.

Just give the stepper a destination and call .run() in a loop until the motion is done.

void movedown(int dist) 
{
  Serial.println("running movedown");
  myStepper.move(dist);  // Relative move
  while (myStepper.distanceToGo() != 0)
  {

    myStepper.run();
    ESP.wdtFeed();
 }
  myStepper.disableOutputs();
}

Do you have to re-enable outputs after you disable them, or is that done automatically for you?

RayLivingston:
If you are fighting the ESP watchdog timer, all you have to do is periodically call ANY delay function - delay() or delayMicroseconds(). I believe there may also be a yield() function, but not sure. So, try replacing your Serial.print with delayMicroseconds(1), or even delayMicroseconds(0), and see if that helps.

Regards,
Ray L.

Hi Ray,

I can handle the watchdog with ESP.wdtFeed() inside a loop which runs fine, the main problem / mystery is that the loop will not run without serial.print, delay does not fix the problem.

Yes, there is a yield() but i cannot use with the ESPAsyncWebServer library.

Cheers tho!

johnwasser:
Just give the stepper a destination and call .run() in a loop until the motion is done.

void movedown(int dist) 

{
  Serial.println("running movedown");
  myStepper.move(dist);  // Relative move
  while (myStepper.distanceToGo() != 0)
  {

myStepper.run();
    ESP.wdtFeed();
}
  myStepper.disableOutputs();
}




Do you have to re-enable outputs after you disable them, or is that done automatically for you?

John, id buy you a pint if i knew where your local was! that seems to have fixed the issue (loop runs fine and motor runs fine with no resets!! Very happy with that, thanks for sticking with it and taking the time to resolve.

ps, stepper automatically re-enables so there was no need for me to include anything else.

Now.. which one of these buttons makes you forum king :slight_smile:

Cheers,
Rob

racally:
Now.. which one of these buttons makes your forum king :slight_smile:

Karma [add].