Simple, Low Cost and Accurate Stepper Motor Driver




Introduction: Simple, Low Cost and Accurate Stepper Motor Driver

About: Engineer, retired. Have always had an interest in electronics, often related to radio control. This evolved into a part time business that I still practice. I do some voluntary work in schools to encourag...

I built this to drive the stepper motor on a telescope mount. The requirement was for an accurate 12rpm that would make the telescope mount rotate to counter the earth’s rotation. The mount had a motor and gears installed but the commercial electronic ‘tracker’ was hugely more expensive than the system here. I tried to write the code in a way that could be easily modified for other speeds, and could be used as a starting point for more complicated systems. The ‘rpm = 12;’ line is right at the start so in many cases you will just need to change this number. It should work on most Ardunio boards. I started on a Uno and then went for a Nano for the final unit. It is set up for an Arduino with crystal frequency of 16Mhz and hence will need the timer pre-scaler code adjusting for other frequencies.

You will need:

· Arduino, e.g. Uno or Nano

· EasyDriver board

· Power supply – 4 AA batteries used here

· Stepper motor

The EasyDriver board takes a lot of hard work out of the Ardunio. It just needs two inputs – direction and step. It can be setup for single, half or ¼ or 1/8 microstepping with the latter being the default. It can drive up to 700ma per phase, up to 30v. I wanted the extra torque of the half step mode and hence set it up for this. Although designed for two bipolar windings it can also drive unipolar motors by ignoring the middle tap in each winding. In some cases the middle taps of the two windings are connected (as was the case here). If so this connection has to be removed. In this case it just required a cut in a track on the motor connection PCB.

Step 1: Connections


· On EasyDriver board – EN2 to GND (next to +5V) (to set half stepping)

· Positive supply to EasyDriver M+ PWR IN and wire from here to Vin on the Nano

· Negative supply to EasyDriver GND PWR IN

· Three wires from EasyDriver GND, STEP, DIR to the Arduino GND, D12 and D11 respectively.

Check using the wire colours and photos above.

I found that 6v was enough for the stepper motor. If you need to go higher check the voltage regulator chips on both boards to make sure they don’t get too hot.

Step 2: Firmware (sketch)

The normal ‘void Loop()’ function does not work well when trying to get precise timings. One can add and tune ‘delay();’ statements but this gets very complicated once one adds additional functionality that does not run every time – e.g. code associated with a button being pressed. A better way is to use one of the internal timers to trigger an interrupt routine. A very good explanation on how to do this is at: . A very nice feature of the ATMEL microcontrollers is a the ability to set a trigger value for a timer that both runs the associated interrupt code and resets the timer to zero for the next interrupt. Ideally the interrupt function should have minimum code. The code here takes some beating. It also does all the work necessary for this application so no code is needed in the ‘void Loop()’ function. However code is likely to be needed in ‘void Loop()’ if additional options were needed such as changing the speed or sending information to a display.

The interrupt routine just uses an ‘exclusive or’ statement to toggle the step output. Hence a nice, equal mark– space square wave is produced, using two interrupts to give a high and low to input one ‘step’ to the EasyDriver board. The use of the PORTB and PINB functions gives much smaller machine code than the alternative of digitalRead(); , if statement and digitalWrite();

The direction is set in 'void Setup()'.

The code as written goes down to 1rpm. It can go less if ‘rpm’ is made a ‘float’ or the code adjusted so integer rpm number represents say 0.1 rpm increments. The number that ends up in the ‘settmr1()’ call must be less than 65535 as the timer is 16 bit. This may need the timer pre-scaler adjusting. For the best accuracy the pre-scaler should be set so that the ‘settmr1()’ number is a close as possible to 65535 without ever being greater.

For those who might be interested the detail of the timer calculation is as below.

First find how frequently the interrupt routine has to operate.

Motor is 48 steps/rev with the driver doing half stepping. So there are 96 steps per rev. We also need two interrupt calls per step (one to high and one back to low) so we need 96*2 interrupt calls/rev.

For x rpm we have 1/x mins/rev, or 60/x seconds/rev.

The interrupt timing must then be 60/ (x*96*2) seconds

Second we need to find what timer count gives the required interrupt timing.

The system clock is 16Mhz or every 1/16000000 seconds.

The timer prescaler is 256 so the clock is incremented every 256/16000000s or every 16 us.

So for the timer to give the required interrupt timing it must count to 60*1000000/(x*96*2*16).

This factors down to the formula in the sketch = 312500/(x*16).

For 12 rpm the count is 1628 (rounded).

For 1 rpm the timer count needs to be 19531 (rounded).

Both of these numbers are lower than the max count of 65535 and hence this prescale is suitable for rpms >1. A lower prescaler of 8 could be used for increased accuracy at 12 rpm. The prescale value can only be 1, 8, 64, 256, 1024.

I hope this gets you started with accurate stepper motor operation. Please ask if you feel I have missed anything.



    • Tiny Home Contest

      Tiny Home Contest
    • Water Contest

      Water Contest
    • Metalworking Contest

      Metalworking Contest

    16 Discussions

    This can prove to be a handy tool while taking apart old electronics stuff like printers and scanners to check the retrieved stepper motors for their performance.


    4 months ago


    Thanks for the code and explanation. I am a beginner with stepper motors and havent used arduino (or coding...) for a (long) while so sorry for the dumb question. But I didnt quite understand where in the code (which works great) does it "tell" the stepper motor to rotate (or "step"). From what I understood you have to tell it to turn on and off the power to the coils but I cant see a line doing this in the code (in your example pin 12 controls stepping, but I cant understand whats going on, since in your sample it is only declared as output and thats it). I will be happy to get an explanation for this.


    4 replies

    The easydriver board deals with driving the coils. So the Arduino just has to send two signals - one for direction and one for step. Also note that the easydriver board can be set (by hardware connections) to do a full, half, 1/4 or 1/8 step for each step input. Here it is using half step - that delivers greater torque. I hope this helps. Mike

    Thanks Mike, but still, I couldn't understand which line in the code tells the arduino to send a "step" command to the easy driver, I can understand where you set direction, and I can see you define pin 12 as step pin, but cant understand where you send a command to "step". aren't you supposed to send some sort of a "step" command?


    The 'step' is done with line 39. This small interrupt service routine (ISR lines 37-41) is called by the timer that triggers an interrupt every set number of clock cycles. Hence the precision. The code in line 39 is assembler rather than Arduino 'C' as this single instruction is much simpler and faster. It is a 'bitwise exclusive or' that toggles pin 12 that is PORTB,4 in processor speak. So each interrupt pin12 changes from high to low or vice versa - delivering a nice square wave to deliver the step pulses. I hope this helps. Mike

    Awesome! Do you happen to have more information on the rest of your mount? I'd really like to use this driver as part of my Dob to equatorial tracking conversion.

    1 reply

    It sounds like the telescope this is meant for has an EQ mount, so only one axis needs to be driven (and that at a constant speed to counteract earth's rotation).
    For a Dob you have two options: an equatorial platform, which tilts the scope to match your latitude. This lets you drive a single motor just like a traditional EQ mount.
    The other option is driving both axes, simulating polar motion by varying the horizontal and vertical axes at varying rates depending on where the scope is pointed.

    The first option involves more elaborate hardware but simpler software; the second option vice-versa.

    Great idea. Who is the stepper motor supplier or specs?

    5 replies

    The stepper motor was one that had been in my 'will be useful sometime box' for a decade or so! It is a unipolar (4 coil, 5 or 6 lead). Most of these smaller motors are 48 step with the larger motors being 200 step. The individual coil resistance is 37ohms. The coils are in two connected pairs. I had to separate the mid coil connections as mentioned. I then drove the motor using the bipolar driver (EasyDriver) connected to the ends of the pairs of coils (no connection to mid point). The driver can handle a wide range of stepper motors. Just keep within the driver voltage and current specs.

    My dad's entire garage is filled with "Will be useful sometime stuff". hah! Loved that. :)

    Well you can guarantee that the day you throw something away is the day before you find a great use for it.....

    100% agree - ditched an old bathroom fixture last week - this week the parts would have been useful to fix the new leak :)

    neat idea, Money saver too thanks