Care to step with me a moment? For I have stepped upon a splendid stepper driver for the stepping connoisseur!
In this project I’ve built a MegunoLink interface panel to move a linear stage with a stepper motor. I used an X-NUCLEO-IHM03A1 shield to drive the motor and an Arduino Uno to run the show.
- 1 Built with MegunoLink
- 2 The X-NUCLEO-IHM03A1: a super stepper shield
- 3 The MegunoLink Stepper Driver Interface Panel
- 4 powerSTEP01 Arduino Library
- 5 Hardware
- 6 Stepper Interface Panel Software
- 7 Conclusion
I wanted to move the stage quickly so I got the largest stepper I could find from Open Builds and a grunty X-NUCLEO-IHM03A1 stepper driver shield to run it. It works with the Arduino Uno, drives motors up to 10A and has a load of features for around $11 from Digikey. The NUCLEO stepper driver is quite a bargain!
I couldn’t find an Arduino library for the X-NUCLEO-IHM03A1 shield, but the L6470 stepper driver is quite similar. So I was able to adapt SparkFun’s AutoDriver library to work with the Nucleo shield and the powerSTEP01 Arduino library was born.
Since the powerSTEP01 and SparkFun’s AutoDriver library are so similar, the MegunoLink interface panel I built should work with SparkFun’s AutoDriver board with only with minimal changes. Post a message in our forum if you’ve any trouble getting it going.
Read-on to learn about the interface panel I built to test the driver and control the stage from MegunoLink and the library itself!
The X-NUCLEO-IHM03A1: a super stepper shield
There are 3 common ways to control stepper motors from an Arduino:
- Direct drive of the stepper coils. Cheapest hardware, but hardest to program. You have to turn each coil on and off at just the right time to make the motor work.
- Step/direction control. Easiest to program for simple control; you just supply step and direction signals. Harder to get smooth acceleration and motion going though.
- Separate microcontroller to look after the stepper. The microcontroller smoothly speeds up and slows down the motor and keeps track of its position. We just send it commands like take 1000 steps.
The X-NUCLEO-IHM03A1 high power stepper driver shield fits option 3.
The SPI interface on the X-NUCLEO-IHM03A1 board lets the NUCLEO’s micro handle the motor while the Arduino is busy doing other things. For example, the Arduino can tell the NUCLEO to move the motor 3,100 steps. Then get on with processing serial commands, making sensor measurements or controlling a LED strip. The NUCLEO will take care of starting the motor, counting each step and stopping the motor when it gets to the right place.
So although its a little harder to make it take a single step with the X-NUCLEO-IHM03A1 than the other options, it is hardly any more difficult to have it accelerate smoothly to a constant speed, run for 2,000 steps then slow to a gentle stop.
This makes the NUCLEO an asynchronous driver because the program on the Arduino can tell the stepper micro to do something then go off and do its own thing. The other options normally require the Arduino program to run in step with the motor.
You could use the X-NUCLEO-IHM03A1 for nearly anything with a stepper motor in it. It supports:
- large motors up to 10A, 50V
- 1/128 microstepping
- automatic acceleration and deceleration
- digital power control
- over-current, over-temperature, under-voltage protection
The boards can even be stacked to control many stepper motors from a single Arduino. What more could you want?
In this case I’m using it atop a SparkFun RedBoard to drive the NEMA23 stepper motor on our linear actuator from OpenBuilds C-Beam™.
The MegunoLink Stepper Driver Interface Panel
I built a MegunoLink stepper interface panel and matching Arduino sketch for this project. So you can control the motor manually and try out different configurations without having to write any code.
Clicking buttons in the interface panel sends serial commands to the Arduino sketch. The Arduino talks to the X-NUCLEO-IHM03A1 to carry out these commands.
Building interfaces in MegunoLink is as simple as dropping controls into the designer and assigning the serial command you’d like sent. For detailed guides on MegunoLink interfaces, check out the following links:
- Build an Arduino Interface: an introduction to building user interfaces with MegunoLinks interface panel visualizer
- Arduino user interface walk-through
- Interface panel documentation
I’ve used MegunoLink’s expressions to automatically convert between millimeters and steps of motion. The conversion factor is set in the “General Configuration” section. And it is applied in each message sent to the Arduino. For example, the motor position is set with the command:
The 8 mm lead on the lead screw of the OpenBuilds C-Beam™ Linear Actuator run by a 1.8° step motor at 1/128 microsteps gives: (360°/1.8°) * 128 microsteps / 8 mm = 3200 microsteps/mm. This value is stored in the
nudStepsMM number control and its value used in the expression above (
powerSTEP01 Arduino Library
The powerSTEP01 Arduino library is based on SparkFun’s AutoDriver library for the L6470, another stepper driver that uses SPI commands. With a maximum drive current of 3A, the L6470 is more suitable for smaller stepper motors than the X-NUCLEO-IHM03A1.
Changes to the AutoDriver Library
The main changes made to the library to suit the powerSTEP01 rather than the L6470 were the length of some registers, and a different method of setting of the slew rate.
I also had to change the over-current implementation. The NUCLEO board has a voltage-limit (?!!) for over-current protection while the L6470 has a current setting.
To get an approximate setting for the voltage-limit setting on the NUCLEO board you can use this equation:
over-current limit [A] = ((OCThreshold + 1)*31.25mV/RDSon)*(KVAL/255)
- RDSon is the drain-source resistance of the motor drivers FETs. It is between 16 to 23 mOhm according to the NUCLEO’s datasheet
- KVAL is the power level you set in the later motor configuration section
X-NUCLEO-IHM03A1 powerSTEP01 Library Functions
I’ve kept the function names the same in the powerSTEP01 library as the the AutoDriver library wherever possible. The two libraries are pretty much interchangeable with only minor changes needed to switch between the two. This will make it easier to write Arduino programs that will work with either stepper driver.
More details, including data types, can be found in the main library header file
powerSTEP01ArduinoLibrary.h. Here is a list of the motor movement functions that the library implements:
|run()||direction, speed||Runs continuously at the specified speed in the specified direction until given a stop command|
|move()||direction, distance||Moves the specified relative distance in the specified direction and stops|
|goTo()||position||Moves to the specified absolute position via the shortest direction|
|goToDir()||direction, position||Moves to the specified absolute position via the specified direction|
|goUntil()||action, direction, speed||Runs continuously at the specified speed in the specified direction until the limit switch is triggered, can set home position|
|releasesSw()||action, direction||Runs continuously at a low speed in the specified direction until the limit switch is released|
Several commands are available for stopping the motor as shown in the table below.
softStop() is good for non-emergency stops while
hardHiZ() is great at stopping everything if things go wrong; it instantly shuts off power to the motor.
powerSTEP01 Arduino library functions to stop the stepper motor:
|softStop()||none||Decelerates and holds the motor stationary|
|hardStop()||none||Immediately holds the motor stationary|
|softHiZ()||none||Decelerates and cuts power to the motor|
|hardHiZ()||none||Immediately cuts power to the motor|
Configuring the Motor
If you’re using a different motor to the one in the store bought OpenBuilds C-Beam™ Linear Actuator then you’ll first need to configure the running and holding power levels to avoid damaging or underutilising your motor.
I recommend lowering the holding power and clicking “Soft Stop” to energize the motor. Then you can increase the power level slowly while monitoring the motor temperature without having to make the motor move all the time.
If you want as much torque or speed as you can, find the point where the motor doesn’t get ‘too hot’ over time and use this as your running power. I typically consider ‘too hot’ to be a bit less that ‘too hot touch’ to but find whatever point you’re comfortable with. Set the final value of the holding power as however much you need, if there’s no forces the motor is holding against when resting then a half or a quarter of the running power should be fine.
If you’re happy with lower torque and speed then go low. You’ll have less noise, less chance of blowing your motor, and a lower power bill.
Set an over-current threshold as instructed in the interface for peace of mind and protection against shorts. If you don’t care for that kind of thing then set it to the maximum value to effectively disable over-current protection.
X-NUCLEO-IHM03A1 powerSTEP01 Library Example
A example sketch named
powerSTEP01SimpleTest.ino is included in the powerSTEP01 library.
This simple example illustrates configuration of the library, in the
setup function and runs the motor back and forwards 2,000 steps each way, in the
// Program demonstrating how to control a powerSTEP01-based ST X-NUCLEO-IHM03A1
// stepper motor driver shield on an Arduino Uno-compatible board
// Pin definitions for the X-NUCLEO-IHM03A1 connected to an Uno-compatible board
#define nCS_PIN 10
#define STCK_PIN 9
#define nSTBY_nRESET_PIN 8
#define nBUSY_PIN 4
// powerSTEP library instance, parameters are distance from the end of a daisy-chain
// of drivers, !CS pin, !STBY/!Reset pin
powerSTEP driver(0, nCS_PIN, nSTBY_nRESET_PIN);
// Start serial
Serial.println("powerSTEP01 Arduino control initialising...");
// Prepare pins
// Reset powerSTEP and set CS
// Start SPI
// Configure powerSTEP
driver.SPIPortConnect(&SPI); // give library the SPI port (only the one on an Uno)
driver.configSyncPin(BUSY_PIN, 0); // use SYNC/nBUSY pin as nBUSY,
// thus syncSteps (2nd paramater) does nothing
driver.configStepMode(STEP_FS_128); // 1/128 microstepping, full steps = STEP_FS,
// options: 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128
driver.setMaxSpeed(1000); // max speed in units of full steps/s
driver.setFullSpeed(2000); // full steps/s threshold for disabling microstepping
driver.setAcc(2000); // full steps/s^2 acceleration
driver.setDec(2000); // full steps/s^2 deceleration
driver.setSlewRate(SR_520V_us); // faster may give more torque (but also EM noise),
// options are: 114, 220, 400, 520, 790, 980(V/us)
driver.setOCThreshold(8); // over-current threshold for the 2.8A NEMA23 motor
// used in testing. If your motor stops working for
// no apparent reason, it's probably this. Start low
// and increase until it doesn't trip, then maybe
// add one to avoid misfires. Can prevent catastrophic
// failures caused by shorts
driver.setOCShutdown(OC_SD_ENABLE); // shutdown motor bridge on over-current event
// to protect against permanant damage
driver.setPWMFreq(PWM_DIV_1, PWM_MUL_0_75); // 16MHz*0.75/(512*1) = 23.4375kHz
// power is supplied to stepper phases as a sin wave,
// frequency is set by two PWM modulators,
// Fpwm = Fosc*m/(512*N), N and m are set by DIV and MUL,
// options: DIV: 1, 2, 3, 4, 5, 6, 7,
// MUL: 0.625, 0.75, 0.875, 1, 1.25, 1.5, 1.75, 2
driver.setVoltageComp(VS_COMP_DISABLE); // no compensation for variation in Vs as
// ADC voltage divider is not populated
driver.setSwitchMode(SW_USER); // switch doesn't trigger stop, status can be read.
// SW_HARD_STOP: TP1 causes hard stop on connection
// to GND, you get stuck on switch after homing
driver.setOscMode(INT_16MHZ); // 16MHz internal oscillator as clock source
// KVAL registers set the power to the motor by adjusting the PWM duty cycle,
// use a value between 0-255 where 0 = no power, 255 = full power.
// Start low and monitor the motor temperature until you find a safe balance
// between power and temperature. Only use what you need
driver.setParam(ALARM_EN, 0x8F); // disable ADC UVLO (divider not populated),
// disable stall detection (not configured),
// disable switch (not using as hard stop)
driver.getStatus(); // clears error flags
Serial.println((int)driver.getStatus(), HEX); // print STATUS register
driver.move(FWD, 2000); // move forward 2000 microsteps
while(driver.busyCheck()); // wait fo the move to finish
driver.softStop(); // soft stops prevent errors in the next operation
driver.move(REV, 20000); // reverse back
while(1); // do nothing for all time
The X-NUCLEO-IHM03A1 by STMicroelectronics is available from several electronics distributors as detailed on its ST product page. As of writing those operating worldwide include STMicroelectronics X-NUCLEO-IHM03A1 at Digi-Key for USD$10.64 and STMicroelectronics X-NUCLEO-IHM03A1 at Mouser Electronics for USD$15.76.
You should be able to use the interface and matching Arduino sketch with the SparkFun AutoDriver – Stepper Motor Driver (v13) with little difficulty. Just change the library in the sketch to the SparkFun AutoDriver library, change the over-current threshold slider in the interface to have a maximum value of 15 rather than 31 and change the slew-rate constant in the setup of the sketch. I think that should do it, compare the datasheets and examples if you have trouble.
You’ll need to find a power supply suitable for your motor to connect to the X-NUCLEO-IHM03A1. An old laptop power supply may be a good option if you find one with an output voltage in the range of your motor and not above the 50V of the board. The current is controlled by the powerSTEP01 so a power supply with an output current higher than the motor needs should be fine.
OpenBuilds C-Beam™ Linear Actuator
The C-Beam™ Linear Actuator used in this project is an open source design anyone can build themselves if they want. Those people a wanting a more convenient option can buy all the parts in a C-Beam™ Linear Actuator Bundle from the OpenBuilds Parts Store in one of three lengths, either with or without the NEMA 23 Stepper Motor also available separately.
Stepper Interface Panel Software
To use the stepper interface panel to drive a stepper motor you’re going to need a bunch of software:
- Arduino IDE: the Arduino software
- MegunoLink: our Arduino companion software that hosts the interface panel
- MegunoLink Arduino library: a standard Arduino library that includes support for handling serial commands, saving data to the eeprom and plotting data with MegunoLink
- powerSTEP01 Arduino library: the library, described above, that interfaces to the X-NUCLEO-IHM03A1 stepper driver. This library includes the
MegunolinkdriverInterface powerSTEP-1 sketch, the Arduino sketch that MegunoLink uses to control the stepper motor from the interface panel.
powerSTEP01 Arduino Library
You can find the stepper control library on GitHub: powerSTEP01 Arduino Library on GitHub.
Download the library and install it into a folder named
powerSTEP01/ in the
libraries folder of your Arduino installation. After you restart the IDE, the
powerSTEP01 library will be available to your program.
Open the Arduino sketch which communicates with MegunoLink from the Arduino IDE’s
File→Examples menu. The example is named
You’ll need to install MegunoLink’s Arduino library before you’ll be able to compile the sketch. This library is most easily installed by setting up MegunoLink’s Arduino integration. The powerSTEP01 interface panel uses MegunoLink’s Arduino library to:
- Process serial commands sent from MegunoLink using the Serial Command Handler library.
- Save stepper configuration into the Arduino EEPROM using the EEPROM data library
Once you have all the libraries installed, compile the sketch and upload it onto your Arduino.
The MegunoLink interface shown in this article is included in the powerSTEP01 Arduino library. After you install the library, you’ll find the MegunoLink project in the
libraries/powerSTEP01/examples/MegunolinkDriverInterface_powerSTEP-1_/ folder of your Arduino installation.
If you don’t already have MegunoLink, you can download a free-trial.
Open the demo project in MegunoLink then, select the COM port of your Arduino board and hit connect to enable the interface.
In the interface panel it you can access nearly all the functions to control the stepper motor and some shortcuts for moving the motor fixed amounts and homing.
Hey, we reached the end! If you enjoyed this article on the X-NUCLEO-IHM03A1 stepper driver, give us a like on Facebook.
Post a comment below and tell us how you’re using stepper motors in your projects. If you’d like some help getting the stepper going in your project, head on over to the forums.
And don’t forget to subscribe if you’d like to hear about more snazzy Arduino projects.
I have to say, that was some very useful info 🙂 I have a hard time finding anything about the powerstep chip, and still am a bit of a beginner with motor control.
I am planning to build a force feedback rig, and was wondering if this board could be used. The main difference between this usage and the usual stepper usage is that in an FFB rig, the motor mostly never moves; it is mainly used to create torque to oppose the user’s own force. It does sometimes move, but mostly at a quarter turn.
I have read that when the motor is stalled, i could approximate torque control = current control, and it seems this board can do current control.
Now the motor of choice is a 2 phase stepper, each phase having a 6A current rating, 0.55ohm, and 8.4mH inductance, and i have a 24V 20A capable power supply that i plan to use.
Do you think this board could be used to control this motor with that kind of usage ? I did read it can do 10A per phase so the current could be fine, but again i am a bit of a newbie in motor control. I plan to use a smaller motor first since that one is expensive, i’d rather fry a cheap one if something bad happens !
Thanks a lot, your input is appreciated 🙂
Hi Cyril, sorry but we don’t have enough experience with steppers to answer that question. Maybe some of the guides or application notes online might? i.e. https://www.nxp.com/docs/en/application-note/AN2974.pdf