Simple forward wait then backward with AccelSepper

Hello,

I have been racking my head over two days reading hours and hours and still cant seem to figure out my problem. I thought it would be really simple to use AccelStepper to make a stepper motor go forward, wait one min or less then return back to the original position then repeat. Would some one please point me in the right direction or tell me what’s wrong with my code. I’m new but eager to learn. the following code will only make the stepper turn counter clockwise. Thank you very much.
Below is my code.

AccelStep2.ino (1.07 KB)

I didnt see a place to put my code but here it is:

#include <AccelStepper.h>

AccelStepper stepper (1, 34, 35); // name of stepper motor (1 = driver, pin 34 = step, pin 35 = direction)

const long distance = 100; //distance of the stepper

void setup()
{
stepper.setMaxSpeed(1000);
stepper.setAcceleration(100);

pinMode(33, OUTPUT); //This sets the enable pin output. I dont know how to use enablepin() function
digitalWrite(33, LOW); //This sets that output LOW which is active

stepper.move(distance);

}

void loop()
{
exposeRA(); //run the stepper forward
//<--------I think right here is where I need to be able to wait a certain amount of time for examp 30 seconds

hideRA(); //run the stepper backward
//<-------now repeat
}

void exposeRA()
{
stepper.run();
stepper.moveTo(stepper.currentPosition() + distance);
stepper.stop();
}

void hideRA()
{
stepper.run();
stepper.moveTo(stepper.currentPosition() - distance);
stepper.stop();
}

You need a state machine to handle the reverse move, and to understand how to use the AccelStepper library better. Calling stop () is for emergencies really. Use move/moveTo, and always call run() in loop(). distanceToGo() is handy too.

boolean trigger_forward = false ;
boolean trigger_backward = false ;
unsigned long time = 0L ;

void loop ()
{
  stepper.run () ;   // always call this in loop () everytime.

  if (digitalRead (pin) == LOW)       // initial trigger - say from a switch
    trigger_forward = true ;

  if (trigger_forward)     // if triggered set the forward motion going, setup for return motion
  {
    time = millis () ;
    trigger_forward = false ;
    trigger_backward = true ;
    stepper.move (distance) ;
  }

  if (millis () - time >= 60000L && trigger_backward)  // if return is due, do it
  {
    trigger_backward = false ;
    stepper.move (-distance) ;
  }
}

You'll need to adapt this a bit, but the form of loop checking for every input and statechange one after another is the key. Nothing gets missed.

Thank you for your reply MarkT because it really helped me get a step further. I modified your code and I almost have it. There are no external pins to press so I just made trigger_forward = true in setup. I don’t know if this is the best way to handle this but it seems to work. I run the first part of the code ok but the only problem I have now is when it runs the code below the “if (millis ()” argument that has the time in it. It will wait for the amount of time to start it, which is good, but then it seem to run the stepper motor for that same wait time instead of the amount of steps that are inputted. Also the second thing is that it wont repeat. It will only run through once forward for the amount of steps then wait for the amount of time then reverse for the amount of time(instead of steps) then stop and not repeat. Could you tell me why or show me what the correct code should look like? Thanks again I appreciate it. Here is the code:

#include <AccelStepper.h>

AccelStepper stepper(1, 34, 35);

boolean trigger_forward = false ;
boolean trigger_backward = false ;
unsigned long time = 0L ;

void setup()
{
pinMode(33, OUTPUT);
digitalWrite(33, LOW);
stepper.setMaxSpeed(1000);
stepper.setAcceleration(500);
trigger_forward = true ;
}

void loop ()
{
stepper.run(); // always call this in loop () everytime.
if (trigger_forward) // if triggered set the forward motion going, setup for return motion
{
time = millis () ;
trigger_forward = false ;
trigger_backward = true ;
stepper.moveTo (-15000) ;
}

if (millis () - time >= 32000L && trigger_backward) // if return is due, do it
{
trigger_backward = false ;

stepper.moveTo (15000) ;

}
}

Tulaherl,

Assuming you have an Arduino UNO and an Adafruit motor shield, the solution to your problem is easy.

In the AccelStepper library is an example called stepper test.

It drives a stepper forward, pauses, then in reverse in different modes, eg, single, interleaved, microstep etc.

Simply change the parameters to make the stepper rotate further, and wait longer between reversing direction.

Attached is the Adafruit sketch.

Ken

/* 
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
It won't work with v1.x motor shields! Only for the v2's with built in PWM
control

For use with the Adafruit Motor Shield v2 
---->	http://www.adafruit.com/products/1438
*/


#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 

// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Stepper test!");

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  myMotor->setSpeed(10);  // 10 rpm   
}

void loop() {
  Serial.println("Single coil steps");
  myMotor->step(100, FORWARD, SINGLE); 
  myMotor->step(100, BACKWARD, SINGLE); 

  Serial.println("Double coil steps");
  myMotor->step(100, FORWARD, DOUBLE); 
  myMotor->step(100, BACKWARD, DOUBLE);
  
  Serial.println("Interleave coil steps");
  myMotor->step(100, FORWARD, INTERLEAVE); 
  myMotor->step(100, BACKWARD, INTERLEAVE); 
  
  Serial.println("Microstep steps");
  myMotor->step(50, FORWARD, MICROSTEP); 
  myMotor->step(50, BACKWARD, MICROSTEP);
}

If you want the code to keep looping, then when backwards motion is triggered you
need to setup for the next forward motion, just like the forwards motion sets up for
the next backwards motion - set the time and trigger forwards. Add a test for the
time having elapsed in the if that starts forward motion - have a play and figure it out.

Add Serial.print() s to see what happens when, its a useful debugging technique.

Neksmerj, I’m not using a shield. Thank you for the suggestion though. I’m using the Arduino Mega 2560.

Thank you Mark I think I have it now. I played around as you suggested and I finally got it to work…Sort of. I have it doing what I need it to do but honestly I’m not sure whats happaning in the loop. All I know is that it is doing what I needed it to do which is moving the screw out, waiting for a few moments then returning back the to home position then looping it out again. The kind of steppers I have have a screw as their center axel so that when the run if the axel is held stationary the stepper will screw them out or back in. Here is my code:

#include <AccelStepper.h>

AccelStepper stepper(1, 43, 44);

boolean trigger_forward = false ;
boolean trigger_backward = false ;
unsigned long time = 0L ;

void setup()
{
pinMode(42, OUTPUT);
digitalWrite(42, LOW);

stepper.setMaxSpeed(500);
stepper.setAcceleration(500);
trigger_forward = true ;
Serial.begin(9600);

}

void loop ()
{

stepper.run(); // always call this in loop () everytime.
if ( millis () - time >= 20000 && trigger_forward) // if triggered set the forward motion going
{
time = millis() ;
trigger_forward = false ;
trigger_backward = true ;
stepper.moveTo (-15000) ;

}
//Serial.println(millis ());
if (millis ()- time >= 32000L && trigger_backward) // if return is due, do it
{
time = millis();
trigger_backward = false ;
trigger_forward = true;
stepper.moveTo (1450) ;

}
}

MarkT, if I misses something or if there was something I could have done with a little more finess I would appreciate the correction.

Thanks