Steppers motors deserve to be used in our projects much more than they are. Their use in 3D printers has brought the prices for the motors and drivers down dramatically. But the libraries to drive them lag behind. The Stepper library, part of Arduino, is very limited since it blocks and only allows one motor at a time to move. The AccelStepper library, created by Mike McCauley and easily installed using the Arduino Library Manager, overcomes these restrictions, but is considered difficult to use. The purpose of this manual is to explain AccelStepper so its use can become much more widespread.
Using the AccelStepper Library - Overview
The AccelStepper library is a library for Arduino written in C++. To use it, you construct (or "instantiate" in C++ speak) named objects of AccelStepper type. These software objects typically have "motor" or "stepper" as part of their names and are related directly to physical stepper motors and their interface electronics ("drivers"). Several different interfaces are supported. The appropriate one for an individual application must be specified when the object is constructed. Once an object is constructed, the various functions (called "member functions") provided in the library may be used to control the objects. I find it helps to break these into groups. The first group is setup functions that specify physical capabilities (such as speed and acceleration) of the motor and physical values (such as position to move to). The next group are the functions that actually move the motor by sending it signals that will cause steps. These functions use the values from the setup functions to control the motion. Next are the functions that report information about the status of the motion. Then come the pin management functions that configure and control the pins that interact with the driver. These functions will be discussed below, but first it is good to understand how AccelStepper works.
Motion Overview
A stepper moves when it receives an electrical signal that causes the motor to take a step. The AccelStepper library only has one callable function that causes motion: runSpeed(). Other functions that result in motion call runSpeed() to produce the actual steps. Each such function has the word "run" in its name. The motion functions are of two types: constant speed (limited by the current value of speed), and variable speed (limited by settings of acceleration and maxSpeed, and by position relative to the target). Each of these types contains blocking and non-blocking functions. Blocking functions will run until a stop condition occurs, but no other code will run until they complete. Non-blocking functions cause a single step (if a step is due - see below) and return immediately in any case. Since each call to a non-blocking function only makes at most a single step, they must be called as often as possible; usually in the main loop. Otherwise the motor will not be stepped at the desired speed.
The function runSpeed() determines when a step is to be taken. runSpeed() subtracts the time of the last step from the current time. If the result is greater than or equal to the value of stepInterval ( we say, "A step is due."), runSpeed will increment (or decrement, as required) currentPosition, call step(), and update the time the last step was taken. (step() is an internal function - not directly callable. It causes the correct electrical signal to be sent to the interface.) Each call to runSpeed() repeats this process, so runSpeed() must be called at least speed times per second. Usually, this means putting a call to runSpeed() in loop(). Calling runSpeed() when no step is due does nothing
The controlling variable for runSpeed() is stepInterval so we need to understand how AccelStepper calculates it. An internal variable, stepInterval is not directly manipulated by the user. In the simplest case, calling setSpeed() will cause a new value of speed - and stepInterval - to be calculated....
Read more »
Yes, my motors keep heating a bit. After 45 minutes in final position you can feel motor is heat by toucging it. so I disconnected them becaus temperature is mounting.
ULN 2003 ( 2 units, one per stepper) are feed with exactly 5 volts from external power (yes , all grownds are tied)
I attach an extract of my program. Purpose is moving railroad level crossing gates.
When Pushbutton 5 goes from 0 to 1, stepper moves to Down Position (posAbajo1, 200) and keeps going while Pushbutton is 1 and it arives to Down Position.
When Pushbutton 5 goes from 1 to 0, stepper moves to Up Position and keeps going while Pushbutton is 0 and it arrives to Up Position (posArriba1 , 0).
Every move is perfectly done. Only problem is stepper temperature.
See my attache extract of program:
/* Railroad level-crossing gates
Works with driver ULN-2003 and two unipolar stepper motors 28 BYJ-48,5V
*/
#include <AccelStepper.h>
// When pushbutton 5 is on, Track in use. When it is = 0, track is free
const int puls5= 22; // Track in use (simulation with pushbutton 5)
// Starting and final gate positions
const long posArriba1 = 0; // Gate 1 up, initial position
const long posAbajo1 = 200; // Gate 1 down, final position
// Stock current pushbutton 5 value
int valpuls5 = 0;
// Stock former pushbutton value
int valpuls5old = 0;
// SEQUENCE IS In1, In3, In2, In4
AccelStepper stepper1(AccelStepper::FULL4WIRE, s1In1, s1In3, s1In2, s1In4);
void setup() {
pinMode(puls5,INPUT);
// set the maximum speed, acceleration ,
stepper1.setMaxSpeed(200.0);
stepper1.setAcceleration(25.0);
stepper1.setCurrentPosition(posArriba1);
}
void loop() {
valpuls5 =digitalRead(puls5);
//When track goes from free to "in use"
if (valpuls5== HIGH && valpuls5old == LOW) {
stepper1.moveTo(posAbajo1); //Final Position will be 200
valpuls5old = HIGH;
}
//When track goes from "in use" to free
if (valpuls5== LOW && valpuls5old == HIGH) {
stepper1.moveTo(posArriba1); // Final position will be =0
valpuls5old = LOW;
}
if (stepper1.distanceToGo() != 0) {
stepper1.run();
}
}