Stepper Speed Control Library
by Matthew Ford 12th July 2019 (originally
posted 12th July 2019)
© Forward Computing and Control Pty. Ltd. NSW Australia
All rights reserved.
This SpeedStepper library is a rewrite of the AccelStepper library to allow speed control of the stepper motor. The SpeedStepper library lets you change the set motor speed and then accelerates/decelerates to the new set speed using the same algorithm as AccelStepper library. The SpeedStepper library also allow you to set plus and minus limit and a 'home' position. There is a goHome command to return to the home position.
Limitations: The SpeedStepper library only drives direction and step outputs and so needs to be connected to a motor driver, such as Easy Driver, to actually drive the stepper motor. The AccelStepper library provides more driving options which could be copied to this library if required.
Two example sketches are provided, both of which can be run without a motor or motor driver. SpeedStepperPlot sketch issues example speed commands and the goHome command and generates a plot of the resulting speed and position. The SpeedStepperSetup sketch provides a menu driven setup to set the motor's home and limits and then run the motor and adjust the speed up and down and goHome to finish.
While the AccelStepper library provides good position control, speed control was needed for the Prototype Ice-Melting Probe for Collecting Biological Samples on Europa. Here is a video of an earlier version of the prototype, which used weight instead of a motor.
This library runs on Arduino Uno and Mega2560, but for the prototype a the larger memory / faster processor SparkFun Redboard Turbo was used.
To run the example sketches only an Arduino UNO or Mega2560 and the software libraries are needed
For bench testing of the library a
SparkFun Redboard Turbo was used with an
a 200 steps/rev, 12V 350mA stepper motor and
a 12 DC supply 2A or larger, e.g. https://www.sparkfun.com/products/14934.
USB A to Micro cable
USB to TTL Serial Cable
Arduino IDE V1.8.9 and a computer to run it on.
pfodParser library for the nonBlockingInput and pfodBufferedStream classes
millisDelay library for non-blocking delays
Download and install the SpeedStepper library Save the SpeedStepper.zip and then use the Arduino IDE menu item Sketch → Include Library → Add .ZIP library to import the library
Download and install the millisDelay library as well
Open the Examples → SpeedStepper → speedStepperPlot example sketch (Restart the IDE if necessary). This sketch is configured to work with Serial, e.g. UNO and Mega etc. For running on the SparkFun Redboard Turbo see below.
No driver board or stepper motor is need to run this example. These examples use D6 and D7 as outputs. You can change the output pins to any digital output by changing the STEP_PIN and DIR_PIN settings near the top of the sketch.
Upload the sketch to board and then open the Tools → Serial Plotter at 115200 baud to show the plot of the speed (RED) and position (BLUE) The plus limit is set to 360 which causes the speed to ramp to zero from about 100 point on the x-axis. The minus limit is -510. The position stops at ~-390 because the speed has been demanded to 0.0. The at 380 point on the x-axis, the goHome cmd is issued which returns the stepper to position zero.
The example sketch is designed to a bases for your own stepper motor application. It provides a menu driven interface that allows you move to motor to its home position, if not already there and then optionally reset the plus and minus limits and then run the motor within that range. The 'run' menu allows you to increase and decrease the speed, freeze at the current speed, stop and also return to home.
This sketch illustrate a number of software features that keep the loop() responsive so that you can add your own sensor inputs to control the stepper. It takes pains to avoid delays that would interfere with the speed control. (See Delays are Evil)
Install the libraries used for running the SpeedStepperPlot, above, and then also install the pfodParser library. The pfodParser library supplies the NonBlockingInput and pfodBufferedStream classes that are used to handle the user input and menu output with blocking the loop() from running.
Open the Examples → SpeedStepper → speedSpeedSetup example. This sketch is configured to work with Serial, e.g. UNO and Mega etc. For running on the SparkFun Redboard Turbo see below.
No driver board or stepper motor is need to run this example. These examples use D6 and D7 as outputs. You can change the output pins to any digital output by changing the STEP_PIN and DIR_PIN settings near the top of the sketch. Upload the sketch to the board and then open the Tools → Serial Monitor at 115200 to see the SETUP menu.
SETUP pos:0 sp:0.00 +Lim:500000 -Lim:-500 LATENCY: stepper:492uS loop:0uS p -- set Home l -- set limits h -- goHome r -- run >
When the sketch runs the current position of the stepper is taken as it 'home' (0) position. If you need to re-position the stepper to its true 'home' position, enter the p command to display the SET HOME menu
SET HOME pos:0 sp:0.00 +Lim:1073741808 -Lim:-1073741808 LATENCY: stepper:752uS loop:3852uS x -- setHome here and exit + -- Forward - -- Reverse s -- swap Forward/Reverse <else> -- hardStop >
As you can see the limits coded in the sketch have been removed so you can re-position the stepper anywhere. You need to take care you don't drive it past the physical limits or you may break something.
Use the + cmd to start moving the stepper forward, if you find it moving in the wrong direction enter a non-command or just an empty line to stop it and then use the s command to swap the direction of Forward. You should update the sketch to include a call to invertDirectionLogic() in the setup to fix this for the next run.
Use the + / - cmds to position the stepper to the correct zero position. The motor starts off slow and then builds up speed as it proceeds, just use and empty line to stop it. The maximum speed for this and the limits menu is set by the MAX_SETUP_SPEED at the top of the setupMenus.cpp.
Once the motor has been positioned at its 'home' position, use the x cmd to re-set the current position as 0 and return to the SETUP menu.
If you need to set the limits, usually only the on the initial setup, use the l cmd to enter the SET LIMITS menu
SET LIMITS pos:0 sp:0.00 +Lim:1073741808 -Lim:-1073741808 LATENCY: stepper:944uS loop:5796uS l -- setLimit here + -- Forward - -- Reverse h -- goHome x -- exit <else> -- hardStop >
Use the + cmd to more forward to the plus limit and then use the l cmd to set it as the plus limit. The h command can then be used to return to 0 and the – cmd use to move if reveres to the position the motor at the minus limit. Again use the l cmd to set the minus limit. Note the positions of the plus and minus limits and update the setup() method's setPlusLimit and setMinusLimit statements with these values.
When the limits are set use the x cmd to return to the SETUP menu and then you can use the r cmd to open the RUN menu
RUN MENU pos:0 sp:3.31 +Lim:500000 -Lim:-500 LATENCY: stepper:944uS loop:5796uS + -- Speed up - -- Speed down h -- goHome . -- hardStop <else> -- freeze Speed >+ pos:4 sp:9.49 +Lim:500000 -Lim:-500 LATENCY: stepper:792uS loop:5664uS pos:42 sp:29.15 +Lim:500000 -Lim:-500 LATENCY: stepper:792uS loop:5664uS pos:120 sp:49.09 +Lim:500000 -Lim:-500 LATENCY: stepper:792uS loop:5664uS pos:238 sp:69.06 +Lim:500000 -Lim:-500 LATENCY: stepper:792uS loop:5664uS
The + cmd starts accelerating in the forward direction and prints out the position and speed every 2 seconds. When the motor reaches the speed you want you can stop the acceleration with any other key (or an empty input). You can reduce the speed using the – cmd down to stop. If stopped the – cmd will accelerate in reverse.
This RUN menu provides manual control of your project. For auto control you will need to add some other sensors.
The stepper motor control depends on the software commanding every step. To maintain the set speed, your sketch needs to call the stepper.run() method often enough to fire the next step at the right time for the current speed. For control via sensors you need to be able to promptly process new measurements. The position/speed print out includes two LATENCY measurements to let you check your sketch is fast enough.
The stepper latency measures the maximum delay between successive calls to the stepper.run() method. In order to run the stepper motor at 1000 steps per sec, the stepper latency needs to be less then 1000uS (1mS). The first version of this sketch had a latency of many milliseconds. To overcome this extra calls to the runStepper() method (which calls stepper.run()) where added through the code. This did not completely solve the problem because the menu and output print statements blocked the sketch once the small Serial Tx buffer was full. To avoid this blocking, pfodBufferedStream from the pfodParser library was used to add a 360 byte output print buffer that the print statements could quickly write to. Then pfodBufferedStream releases the bytes at the baud rate specified 115200 in this case. pfodBufferedStream has to option to either block when the buffer is full or just drop the overflow chars. Here it is set to drop any extra chars when the buffer is full so that the sketch is not blocked waiting for Serial to send chars.
The loop latency measures the maximum delay between successive calls to the loop() method. This sets how fast you can process new sensor measurements and adjust the motor set speed. How fast then needs to be depends on what you are trying to control.
The delays due to the print statements was removed by using pfodBufferedStream above, but to process the user's input you need to take the just first char of the input and ignore the rest of the line. The NonBlockingInput class in pfodParer library is used to return a non-zero char when there is input, using readInput(), and to clear and discard the following characters, using clearInput(), until no chars are received for 10mS without blocking the loop()
Of course the loop latency will be increased by the extra code you add to read the sensors and calculate the new set speed. Many sensor libraries take the sort cut of just using delay(..) between starting a measurement and retrieving the result. You will need to re-write these libraries to use millisDelay instead, to pick up the measurement after a suitable non-blocking delay.
To run the SpeedStepperSetup sketch for real you will need a stepper motor, driver and power supply and in this example SparkFun Redboard Turbo.
The wiring diagram below (pdf
version) shows the connections. In the SpeedStepperSetup sketch
change the SERIAL define to
#define SERIAL Serial1
There are many types and sizes of stepper motors. Here a two coil 12V 350mA stepper motor is used for testing. To power this stepper you need a power supply of 12V or more and greater than 350mA.
This library only provides a direction and step output so you need a driver to interface with the stepper motor. The Easy Driver and Big Easy Driver control the current to the motor's coils so you can use a power supply of a higher voltage safely, for example using 6V supply for a 3.3V motor. The Easy Driver can supply between 150mA/coil and 700mA/coil. For higher currents, the Big Easy Driver can supply up to 2A per coil. Read the FAQ's at the bottom of the Easy Drive page.
These examples use D6 and D7 as the Step and Direction outputs. You can change the output pins to any digital output by changing the STEP_PIN and DIR_PIN settings near the top of the sketch.
Programming the Redboard Turbo is problematic. If it fails to program, first press the reset pushbutton once and reselect the COM port in Arduino Tools menu and retry. If that does not work, double press the reset push button and try again.
Two coil stepper motors have 4 wires. Use a multimeter to find the pairs that connect to each coil and then wire one coil to the Easy Driver A terminals and the other coil to B terminal. It does not matter which way round you wire them because you can use the s cmd in the setup menu to swap the direction of movement.
The motor power supply is wired to the M+ and GND
Set the logic level of the board with the 3/5V link. Short the link together for 3.3V microprocessor outputs, like the SparkFun Redboard Turbo (if you leave it open it is suitable fo 5V digital signals, e.g. UNO, Mega)
Connect the GND, STEP, DIR pins to the microprocessor GND and the step and dir output pins.
No other connections are necessary to drive the motor.
When moving the SpeedStepperSetup sketch from the
Uno/Mega to the Redboard Turbo you might naïvely just replace
#define SERIAL Serial with #define SERIAL SerialUSB to suit the
Redboard Turbo usb serial connection, however you would find that the
resulting stepper latency is about 10mS. That is 10x slower then for
the UNO. This due to how the Redboard cpu handles the USB connection.
To over come this, connect a USB to TTL Serial Cable to D0/D1 and
#define SERIAL Serial1
to use the hardware serial connection to control the stepper motor. Using Serial1 gives LATENCY: stepper:345uS loop:2016uS which is 3 time faster then the UNO for the stepper and loop latency
The Arduino Serial Monitor is a little harder to use to control the stepper motor as you have to enter the char in the cmd line and then press Enter to send it. A quicker more responsive means is to open a terminal window, TeraTerm for PC (or CoolTerm Mac), connected to the USB to TTL cable COM port. Then in that window pressing a cmd key sends it immediately. Pressing Enter just send a empty line.
As wired up above, the Easy Drive is configured for 1/8th steps, so 1000 step/sec will turn the motor at 1000 / 8 / 200 step/revolution = 0.625 revs per sec or 37.5 rpm maximum. By changing the inputs to MS1/MS2 you can switch between 1/8, ¼, ½ and full steps. For full steps connect both MS1 and MS2 to GND. This will allow speeds of up to 300 rpm. Choosing the appropriate MS1/MS2 settings allows you to adjust for installed gear ratio between the motor and the driven part.
While the SpeedStepper library allows you to set position limits on the motor movement, the tacking of the position is done by counting the steps output by the software. If the motor stalls, i.e. the torque is insufficient to drive the motor the next step then the software position will be out of sync with the motor position. Then when you use the 'goHome' command the motor will overshoot the home position. To prevent damage to the hardware you should fit limit switches at the hard limits to disconnect the motor power supply.
First, set it to the lowest setting of the potentiometer. i.e. voltage at TP1 is minimum. The potentiometer is delicate, so don't force the potentiometer past the mechanical stops. Set the motor driving at a slow steady speed a slow, then slowly turn the potentiometer until the motor doesn’t skip or jerk between steps.
This project shows how to use the SpeedStepper library in a practical application. While the AccelStepper library provides good position control, speed control was needed for the Prototype Ice-Melting Probe for Collecting Biological Samples on Europa so the AccelStepper library was re-written to provide speed control with end limits and a goHome function.
AndroidTM is a trademark of Google Inc. For use of the Arduino name see http://arduino.cc/en/Main/FAQ
The General Purpose Android/Arduino Control App.
pfodDevice™ and pfodApp™ are trade marks of Forward Computing and Control Pty. Ltd.
Contact Forward Computing and Control by
©Copyright 1996-2018 Forward Computing and Control Pty. Ltd. ACN 003 669 994