Introduction: Arduino Hardware PWM for Stepper Motor Drives
With our new project, JustAddSharks, we are very keen to support the development of open source control software for laser cutters. We are more than happy for people to modify our laser cutters, replace the control system with something suitably open source and then let us know how it goes. Realistically though we're going to have to figure these things out for ourselves so we can guide other people through the process.
There are a lot of tutorials online detailing the hardware PWM features of the arduino and how it relates to servo motor control. This instructable will show you how to use the hardware PWM to control a stepper motor instead. We'll start with the basics of PWM, show briefly how it relates to servo motors and then show the differences for use with stepper motors.
Step 1: Pulse Width Modulation
- Amplitude - The amount the signal changes between On and Off states
- Frequency - The number of times the signal repeats in a given time frame
- Duty Cycle - The proportion of On time to Off time usually expressed as a percentage
In it's simplest form a PWM square wave can be created with a few lines of code. The following code would produce a signal with a 1 second Frequency and a 10% duty cycle. This would be functional but the Arduino would be dedicated to producing this signal the whole time and would not do anything else. This is why the blink without delay example is so important to learn.
With a software generated signal any variation in the code execution time can cause variations in the output. Conditional statements may not execute on every loop so it is hard to guarantee that each loop will take exactly the same amount of time. Modern microcontrollers have dedicated hardware modules to generate a code independent square wave. Values for Duty cycle and Frequency are written to registers within the controller and the hardware generates the appropriate signal on the desired output pin.
The registers for the Hardware PWM module can be written to directly as described here, but the joy of the Arduino environment is that somebody is likely to have written a library to simplify that process. The TimerOne library provides control over the HardwarePWM module connected to timer 1 (aptly). This library has easy functions for setting the frequency and duty cycle of the square wave being generated
- pwm(pin, duty, period) - Generates a PWM waveform on the specified pin.
Step 2: PWM for Servo Control
For servo control the Frequency of the signal is fixed, and the duty cycle varies.
Servos accept a common control signal, a square wave with a repeat frequency of 20ms and an on period of 1ms (5%) to 2ms (10%). It is the width of the on pulse that indicates what angle the servo should be at.
Here is the code to set up the two extreme signals using the Timer one libraries
- pwm(9, 51, 20000);
- pwm(9, 102, 20000);
Step 3: PWM for Stepper Motors
For stepper motor driver control the duty cycle can be fixed and the Frequency varied.
The stepper motor driver expects a series of input pulses to move the motor to any given angle. The driver moves the motor one step for each input pulse. The direction of the motor is set by the second input.
Here is the code to set up the two different speeds using the Timer one libraries
- pwm(9, 512, 20000);
- pwm(9, 512, 40000);
Step 4: Putting It Into a Project
I discovered all this information with a goal in mind. I wanted to drive the stepper motor connected to the Z axis of my laser cutter. Manually generating a software PWM signal on an Arduino pro mini just wasn't making the axis move fast enough and the occasional jitter in code had a habit of making the motor stall. I needed this clean output signal to drive the motor faster and more reliably, the results were pretty promising.
There is one major drawback to this method of control over stepper motors. A stepper motor uses open loop control to determine where it is, this is done by counting the number of steps the motor has made in any given direction. When using the hardware module to generate the PWM like this, nothing is actually counting the steps. This method of control is only really suitable when there is another feedback mechanism. In my case the Z axis travels to the end switches and stops when it gets there. I don't care how many steps it takes to do that.
I have another project in development that will use this same control method, in that system the user will provide the feedback and will stop the motor when it is in the correct position. This method is not really suitable for controlling the laser cutter as it traces out a design so I will move on to look at the next thing, expect more ibles in the future.
Participated in the
Full Spectrum Laser Contest
5 years ago
want to know pls
step pulse width maximum and minium msec
step idle delay maximum and minium please reply
6 years ago
Very useful instructable. But, how to stop the pwm? Just initializing the timer leave the motor vibrating. Thank in advance.
6 years ago
Thank you for posting this very interesting Instructable.
The very best.
7 years ago
I'm new in the arduino world and I'm developing a project where i use an encoder do from a running machine to set my stepper speed, but my motor is vibrating to much using the stepper library, can you help me with a code for pwm?
7 years ago on Introduction
good and useful ! PWM wave controls stepper motor with perfect angle of rotation!!
8 years ago on Step 4
I found this while looking for others who thought that PWM was a good way to run stepper controllers. Losing the count might be a good trade off in many situations. Even printers use other ways to position the head than counting pulses. Pulse counting in printers and so many other things can fall short of expectations when the motor skips, stutters, or slips. I don't mean a lot, I mean just a tiny bit, just enough so the count is wrong, and that error will be cumlative, and increase over time. I expect that I could use the interrupts to control limits. My thought on using PWM to control Steppers is that it offloads the process from the processor, and gives it time to do other things faster than it would if it was counting pulses, as well as generating them. This is a great instructable. I downloaded the library too, Thanks
9 years ago on Introduction
I need to convert 2 PWM inputs (RC signal) and turn it into 2 analog outputs 5VDC. (0v-to 5 Vdc).
9 years ago on Introduction
im sure you know it but frequency idoes not mesure time, i think that would be the period, frequency is the number of occurrences of a repeating event per unit time
9 years ago on Introduction
Recently i had to make a much faster PWM for a project but still preserve the capability of 1%-steps in the duty.
In fact, i had to reach FULL speed --> 16MHz clock of the Arduino --> 160kHz frequency with 1% stepping of dutycycle.
A lot of forums and boards said: No dice. That wont work, too fast.
I fiddled around a bit and got it finally working as intended.
The important parts are those setting of Timer1 and registers to it:
I hope this code helps some people who need to make a FAST pwm.