Simple code to stop a motor for 5 seconds..

Hi,

I have trouble with my code and the millis function.
I have studied BlinkWithoutDelay and many other examples.
On it for 2 days now. So i hope some can help me out ... again.

Its a simple code i want the motor to run in one direction for 3000 steps.
Then wait for, lets say 5 seconds, and then run again 3000 steps in the same direction.

Issue: the motor runs the first 3000 steps but after the wait statement it does nothing.

What am i not getting here?

By the way i have tried using millis() directly without a code but get the same result!

#include <elapsedMillis.h>
#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

elapsedMillis timeElapsed; //declare global if you don't want it reset every time loop runs

// delay in milliseconds
unsigned int interval = 5000;


void setup() 
{                
}

void loop()
{
          stepperA.setMaxSpeed(4000);
          stepperA.setAcceleration(4000);
          stepperA.moveTo(3000);
          stepperA.run();
  
  if (timeElapsed > interval) 
  {       
    stepperA.setMaxSpeed(4000);
          stepperA.setAcceleration(4000);
          stepperA.moveTo(3000);
          stepperA.run();
    timeElapsed = 0;       // reset the counter to 0 so the counting starts over...
  }
}

tnx

What am i not getting here?

The fact that you are NOT using millis() directly.
The fact that you need to post links to non-standard libraries.

It seems strange to set an instance of a class to 0. Why are you doing that?

I have changed de code to millis() directly. Same result.

This is the accelstepper.h link: AccelStepper: AccelStepper Class Reference

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);


unsigned long previousMillis = 0;     
const long interval = 1000;          

void setup() {

}
void loop() {

          stepperA.setMaxSpeed(4000);
          stepperA.setAcceleration(4000);
          stepperA.moveTo(3000);
          stepperA.run();

  
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) 
  {
    previousMillis = currentMillis;

         stepperA.setMaxSpeed(4000);
          stepperA.setAcceleration(4000);
          stepperA.moveTo(3000);
          stepperA.run();

  }
}

Hope you can help.

Can someone please try to check the code and helpme to the right direction?

tnx

I suspect that using smarter names for variables would cause a light to go on. currentMillis is a stupid name for now. previousMillis is a stupid name for when some event happened.

Use names that mean something!

The run() function needs to be called on EVERY pass through loop(), NOT just when you feel like calling it.

PaulS:
I suspect that using smarter names for variables would cause a light to go on. currentMillis is a stupid name for now. previousMillis is a stupid name for when some event happened.

I think they are lovely names :slight_smile:

...R

Looking at the code in Reply #2 I believe you need the line
previousMillis() = millis() at the start of the timing period. Something like this. And note that I have used a different name for the variable for added clarity

Try this version - and study the changes I have made

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;     
const long interval = 1000;
boolean waitingToStartRun2 = false;   

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
}

//==========
void loop() {
    currentMillis = millis();
    stepperA.moveTo(3000);
    if (stepperA.distanceToGo == 0) {
        endFirstRunMillis = currentMillis;
        waitingToStartRun2 = true;
    }

    if (currentMillis - endFirstRunMillis >= interval and waitingToStartRun2 == true)
    {
        waitingToStartRun2 = false;
        stepperA.moveTo(3000); // shouldn't this be 6000?
    }
    
    stepperA.run();
}

By the way I am not sure what you want to happen when run2 finishes and I have made no attempt to deal with that

If you want to use acceleration then the value for setAcceleration() should be much lower than the value for maxSpeed().

If you don't wish to use acceleration then use runSpeed() in place of run()

...R

        endFirstRunMillis = currentMillis;

Didn't you mean previousMillis1? 8)

PaulS:
Didn't you mean previousMillis1?

Just in case the OP is confused, the answer is NO.

...R

Thank for the relays and help guys! i appreciate it.

I'm understand the logic of your code Robin. (thanks for your time)

Now it seems that this code results in the same way my code did.

After the first run succesfully completes, the motor stops and doesn't move any more.

I can see with the serial monitor that the code does go throu first run. But never gets in the second run.
See code below. Yes it should be 6000, Robin. i was testing with move() there.

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;     
const long interval = 2000;
boolean waitingToStartRun2 = false;   

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
Serial.begin(9600);
}

//==========
void loop() {
    currentMillis = millis();
    stepperA.moveTo(3000);
    if (stepperA.distanceToGo() == 0) {
        endFirstRunMillis = currentMillis;
        waitingToStartRun2 = true;
        Serial.println("first run");
    }

    if (currentMillis - endFirstRunMillis >= interval and waitingToStartRun2 == true)
    {
      Serial.println("second run");
        waitingToStartRun2 = false;
        stepperA.moveTo(6000); 
    }
    
    stepperA.run();
}

Again thanks a lot for your help!

You are unconditionally telling the stepper to move to position 3000 on every pass through loop(). Why?

ok, i got your point.

so made this change with the while(). But the result is still the same :cry:

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;     
const long interval = 2000;
boolean waitingToStartRun2 = false;   

const int crashPin1 = 6;
int crashPin1State;

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
    Serial.begin(9600);
}

//==========
void loop() {
    currentMillis = millis();

   while (waitingToStartRun2 != false)
   {
    //Serial.println("in the while");
                      stepperA.moveTo(3000);
                      stepperA.run();
                      if (stepperA.distanceToGo()==0)
                      {
                        break;
                      }
   }                  
                      if (stepperA.distanceToGo() == 0) {
                          endFirstRunMillis = currentMillis;
                          waitingToStartRun2 = true;
                          Serial.println("first run");
                      }
                  
                      if (currentMillis - endFirstRunMillis >= interval and waitingToStartRun2 == true)
                      {
                        Serial.println("second run");
                          waitingToStartRun2 = false;
                          stepperA.moveTo(6000); 
                      }

    stepperA.run();
}

Try this version. I suspect the earlier version was getting confused about which state it was in.

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;     
const long interval = 2000;

enum motorStateENUM {
    WAITING,
    FIRSTRUN,
    BETWEENRUNS,
    SECONDRUN,
    FINISHED,
};

motorStateENUM motorState = WAITING;

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
Serial.begin(9600);
}

//==========
void loop() {
    currentMillis = millis();
    
    if (motorState == WAITING) {
        stepperA.moveTo(3000);
        motorState = FIRSTRUN;
        Serial.println("first run");
    }

    if (motorState == BETWEENRUNS) {
        if (currentMillis - endFirstRunMillis >= interval and waitingToStartRun2 == true)
        {
          Serial.println("second run");
            motorState = SECONDRUN;
            stepperA.moveTo(6000);
        }
    }

    if (stepperA.distanceToGo() == 0) {
        if (motorState == FIRSTRUN) {
            endFirstRunMillis = currentMillis;
            motorState = BETWEENRUNS;
        }
        if (motorState == SECONDRUN) {
            motorState = FINISHED;
        }
    }

    stepperA.run();
}

...R

Hi Robin, thanks for helping.

I don't understand but also with this version the result is the same again

Kumalix:
I don't understand but also with this version the result is the same again

Please describe the symptoms in as much detail as possible.

...R

This line in my program is wrong

if (currentMillis - endFirstRunMillis >= interval and waitingToStartRun2 == true)

it should be

if (currentMillis - endFirstRunMillis >= interval)

I tried this version on my Uno, without a motor attached and it goes through all the stages

// python-build-start
// action, upload
// board, arduino:avr:uno
// port, /dev/ttyACM0
// ide, 1.6.3
// python-build-end

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;
const long interval = 2000;

enum motorStateENUM {
    WAITING,
    FIRSTRUN,
    BETWEENRUNS,
    SECONDRUN,
    FINISHED,
};

motorStateENUM motorState = WAITING;

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
    Serial.begin(115200);
}

//==========
void loop() {
    currentMillis = millis();

    if (motorState == WAITING) {
        stepperA.moveTo(3000);
        motorState = FIRSTRUN;
        Serial.println("first run");
    }

    if (motorState == BETWEENRUNS) {
        if (currentMillis - endFirstRunMillis >= interval)
        {
          Serial.println("second run");
            motorState = SECONDRUN;
            stepperA.moveTo(6000);
        }
    }

    if (stepperA.distanceToGo() == 0) {
        if (motorState == FIRSTRUN) {
            endFirstRunMillis = currentMillis;
            motorState = BETWEENRUNS;
            Serial.println("between runs");
        }
        if (motorState == SECONDRUN) {
            motorState = FINISHED;
            Serial.println("finished");
        }
    }

    stepperA.run();
}

...R

IT WORKS. Now i have to figure out how this version of your code works.
Have to implement it into my "real" skatch. But i think it should not be a problem.

1000 x thanks to you Robin!!!

Kumalix:
IT WORKS. Now i have to figure out how this version of your code works.

Good to hear.

I reckon the only unusual part of my program is the use of an ENUM. Google C++ ENUM and learn all about it.

If you Serial.print() the ENUM constants you will find that they just represent values 0,1,2,3 etc. But by giving them names it makes it more obvious what is going on.

...R

PS... Just ignore (and delete, if you wish) the comments at the top of my example. They are just instructions for the program I use to compile my code. I forgot to delete them before posting.

Yes, the ENUM is the one that confuses me :confused:
But i'm tying to figure it out.

While i do, can you check my "real" sketch below.

I have implemented your code. But now the motor just keeps spinning.

Do you think i have to look for the awser in the direction of the ENUM or is it more the timing that is off now?

Hoop i'm not taking to much of your time.. :blush:

For anyone else out there this video explains the basics of ENUM's.

it helpt me to get the basics of it..

Now i know the awnser to my question... and that is that i have to look at the timing not ENUM's..

And also i fixed the code. Thanks to Robin.

This one works perfectly:

// python-build-start
// action, upload
// board, arduino:avr:uno
// port, /dev/ttyACM0
// ide, 1.6.3
// python-build-end

#include <AccelStepper.h>

AccelStepper stepperA(AccelStepper::DRIVER, 3,4);

unsigned long currentMillis;
unsigned long endFirstRunMillis;
const long interval = 2000;

enum motorStateENUM {
    WAITING,
    FIRSTRUN,
    BETWEENRUNS,
    SECONDRUN,
    FINISHED,
};

motorStateENUM motorState = WAITING;

//==========
void setup() {
    stepperA.setMaxSpeed(4000);
    stepperA.setAcceleration(4000);
    Serial.begin(115200);
}

//==========
void loop() {
    currentMillis = millis();

    if (motorState == WAITING) {
        stepperA.moveTo(3000);
        motorState = FIRSTRUN;
        Serial.println("first run");
    }

    if (motorState == BETWEENRUNS) {
        if (currentMillis - endFirstRunMillis >= interval)
        {
          Serial.println("second run");
            motorState = SECONDRUN;
            stepperA.moveTo(6000);
        }
    }

    if (stepperA.distanceToGo() == 0) {
        if (motorState == FIRSTRUN) {
            endFirstRunMillis = currentMillis;
            motorState = BETWEENRUNS;
            Serial.println("between runs");
        }
        if (motorState == SECONDRUN) {
            motorState = FINISHED;
            Serial.println("finished");
        }
    }

    stepperA.run();
}