CONTROL OF STEPPING MOTORS By Douglas W. Jones University of Iowa jones@cs.uiowa.edu COPYRIGHT 1990 originally posted on rec.railroad REVISED 1995 All rights reserved. Permision is hereby given to make copies for personal use and to archive or distribute copies of this material on the Internet and connected networks. All other copying of this material is prohibited. Introduction Stepping motors can be viewed as electric motors without commutators. Typically, all windings in the motor are part of the stator, and the rotor is either a permanent magnet or, in the case of variable reluctance motors, a toothed block of some magnetically soft material. All of the commutation must be handled externally by the motor controller, and typically, the motors and controllers are designed so that the motor may be held in any fixed position as well as being rotated one way or the other. Most stepping motors can be stepped at audio frequencies, allowing them to spin quite quickly, and with an appropriate controller, they may be started and stopped "on a dime" at controlled orientations. Stepping motors come in two varieties, permanent magnet and variable reluctance (there are also hybrid motors, which are permanent magnet motors from the controller's point of view). Lacking a label on the motor, you can generally tell the two apart by feel when no power is applied. Permanent magnet motors tend to "cog" as you twist the rotor with your fingers, while variable reluctance motors almost spin freely (although they may cog slightly because of residual magnetization in the rotor). You can also distinguish between the two varieties with an ohm meter. Variable reluctance motors usually have three (sometimes four) windings, with a common return, while permanent magnet motors usually have two independent windings, without center taps in bipolar motors, with center taps in unipolar motors. Variable Reluctance Bipolar Unipolar | ---/\/\/\- | | ---/\/\/\--- ---/\/ \/\--- ---/\/\/\-|-- | ---/\/\/\--- ---\/\_/\/--- ---/\/\/\- | | Stepping motors come in a wide range of angular resoluation. The coarsest motors typically run around 90 degrees per step, while high resolution permanent magnet motors are commonly able to handle 1.8 degrees per step. With an appropriate controller, a permanent magnet motor can be run in half-steps, and some controllers can handle "microsteps", smaller fractional steps. Alternatives For some applications, there is a choice between using servomotors and stepping motors. Both types of motors offer similar opportunities for precise positioning, but a servomotor with analog feedback control, using a potentiometer to sense the rotor position, can give high positioning accuracy and high speed. Stepping motors have a positioning accuracy limited by the spacing of the motor poles, but they allow direct digital control over motor position with an open loop control system. If you look at the head positioning mechanisms used in computer disk drives, you will find that stepping motors are generally used for floppy disks, while voice-coil based servo systems are frequently used for fast, high performance disks. Physics Given a permanent magnet stepping motor with just one winding energised, the rotor (under no load) will snap to a fixed angle and then hold that angle until the torque exceeds the holding torque of the motor, at which point, the rotor will rotate, trying to hold at each successive equilibrium point. Variable reluctance motors behave similarly, although the details differ slightly from those presented in the following brief discussion. For a motor that steps T degrees per step, the plot of torque versus the angular position of the rotor relative to some initial equilibrium position will generally approximate a sinusoid: -- --- | --- \ / \ | / \ \ / \| / \ --+----\----+----/----+----\----+----/----+----\----+-- -3T \ -3T / 0 -T |\ +T / +3T \ \ / | \ / \ --- | --- -- As a consequence of this behavior, as long as the torque remains below the holding torque of the motor, the rotor will remain within one step of the equilibrium position. Each time you step the motor, you electronically move the equilibrium position T degrees. This moves the entire curve illustrated above T degrees. If the motor was exerting the maximum holding torque, the torque after the field is stepped T degrees will be zero and any elasticity in the linkage being controlled will cause the rotor to move the wrong way! As a result of this, a stepping motor should never be asked to deliver more than about 70% of the maximum holding torque! The maximum practical torque is the torque that will cause the motor to deviate T/2 degrees from the equilibrium position; the 70% figure is based on the assumption that the torque versus position function is a perfect sinusoid. Note that, when the rotor is held at a displacement of -T/2 and then the motor is stepped +T degrees, the torque after stepping will be the same as the torque prior to stepping! Basic Control Circuits I see no advantage to using many of the stepping motor controllers available on the commercial market. I've had an easy time with the direct software control of the 3 or 4 windings in the typical stepping motor, using an 8 bit parallel output port to run two motors. What follows is a simple plan for computer control of a stepping motor. First, we'll assume that the DC resistance of the windings is all you need to limit the current through the motor. Some motors have very low resistance windings and need external current limiters, for example, series resistors or (better yet) current limiting power transistors. The following circuit, duplicated once per winding, will generally suffice to control even a fairly large unipolar stepping motor. + motor power | ( 5 to 24 volts ) ------| poorly regulated diode | | logic power to kill | ----- +5 inductive - | one of the | surge ^ | motor windings | 1N4002 | ----- | pull up | | ----------- R resistor ------| | Open | | 470 ohm | C Logic in | Collector | | ----- -----| Buffer |--------------------------| power darlington | (SN7407) | B | transistor (NPN) | | ----- RCA SK 3180 ----------- | E | | - system ground Each winding in the motor requires one darlington transistor, one diode, one resistor, and one sixth of the SN7407 chip. The same circuit will work solenoids, model railroad uncoupling magnets, and other similar things. Because the transistors are being used for switching, they don't dissapate much heat, and I just bolted all of them to a single aluminum bar as a heatsink (with insulating washers where needed). This is not expensive! For small low-current motors (below a few hundred milliamps per winding), consider using the Signetics ULN2003 chip. This eliminates the need for the darlington transistor, and can be directly driven by TTL or CMOS logic. If your motor has three windings, typically with 4 wires because one wire is common to all three windings, it is probably a variable reluctance stepping motor. The common wire goes to the positive supply. Assuming positive logic, when the input is 1, the winding is on, and the following outputs would rotate the motor: Winding 1 100100100100100100100100100 Winding 2 010010010010010010010010010 Winding 3 001001001001001001001001001 time ---> There are also variable reluctance stepping motors with 4 windings and 5 wires. The principle for driving these motors is the same as that for the three winding variety, but it becomes important to work out the correct order to energise the windings to make the motor step nicely. If your motor has two center tapped windings, typically with 6 wires, it's probably a unipolar permanent magnet stepping motor. The center taps are connected to the positive supply (possibly through a current limiter), and we'll call the windings 1a, 1b, 2a, and 2b, where each of the two windings has ends a and b. Assuming positive logic on the 4 outputs needed to control this motor: Winding 1a 1000100010001000 11000001110000011100000111 Winding 1b 0010001000100010 00011100000111000001110000 Winding 2a 0100010001000100 01110000011100000111000001 Winding 2b 0001000100010001 00000111000001110000011100 time ---> Note that the two halves of each winding are never energized at the same time. The left sequence shown above will rotate a permanent magnet one step at a time, while the right sequence will rotate the motor one half step at a time. Half stepping works because if two windings are energized at the same time, the motor will stop in a position midway between the two. Things are more complex with bipolar permanent magnet motors that have two windings with no center taps. You can distinguish such a 4 wire motor form the 3 pole 4 wire variable reluctance motors with an ohmmeter. In that case, the simple drive circuit outlined above won't work, but the control logic outlined above is still applicable. Antonio Raposo (ajr@cybill.inesc.pt) suggested the following circuit for each winding of such a motor: 0------0----0----------------0----0------0------ positive bus | | | | | | 2K2 R |C | | |C R 2K2 | B --- - - --- B | BD679 0----|NPN| ^ 1N4007 1N4007 ^ |NPN|----0 BD679 | --- | | --- | | |E | | |E |C +5 | | | --------- | | | +5 | 0--|<--0----0--| Winding |---0----0-->|--0 | 2K2 R | 1N5408 | --------- | 1N5408 | R 2K2 | C| | | |C | | B --- - - --- B | a -0--|NPN| ^ 1N4007 1N4007 ^ |NPN|--0- b --- | | --- E| BD679 | | BD679 |E | | | | 0-----------0----------------0-----------0------ negative bus and logic ground The a and b inputs to the above circuit can be driven by open collector TTL outputs as in the first and simpler circuit. The motor winding will be energised if exactly one of the a and b inputs is high and exactly one of them is low. If both are low, both pull-down transistors will be off. If both are high, both pull-up transistors will be off. The a and b ends of the control circuit can be driven exactly like the a and b ends of the center tapped winding documented above. Note the 4 diodes connecting the ends of the motor windings to the positive and negative bus. These are normally reverse biased, but when the motor winding is turned off or reversed, they will be forward biased for as long as it takes to kill the current through the winding. The UDN2998W Dual full bridge chip gives you an H-bridge circuit such as the above in a power SIP package. Another chip some people recommend is the L298 (given the similarity in numbers, these may be the same chip from different sources). This is rated at up to 2 amps at 48 volts. The companion L297 contains drive logic. The one warning when using this chip set is that the switching times are fast enough that commonplace protection diodes (1N400X) aren't fast enough. Instead, use a diode such as the BYV27. Current Limiting Before talking about software, a note on powering stepping motors is in order. Small stepping motors, such as those used for head positioning on floppy disk drives, are usually driven at a low DC voltage and the current through the motor windings is usually limited by the internal resistance of the winding. High torque motors, on the other hand, are frequently built with very low resistance windings; when driven by any reasonable supply voltage, these motors usually require external current limiting circuitry. Microstepping, where the control system positions the motor rotor between half steps, also requires external current limiting circuitry. For example, to position the rotor 1/4 of the way from one step to another, it might be necessary to run one motor winding at full current while the other is run at approximately 1/3 of that current. Another reason to run a motor from a supply voltage higher than that needed to produce the rated current in the motor windings is to obtain faster rise times when a motor winding is turned on. The rates of current rise and fall when a winding is turned on and off limit the speed at which the motor can be stepped, and as a result, higher operating voltages are required for higher stepping rates. The easiest to understand current limiter is a series resistor. Most motor manufacturers recommended this approach in their literature up until the early 1980's. The typical circuit used was as follows (illustrated with one center-tapped motor winding): + 24 _____|_____ | | | R1 limits the current through the motor | R1 | _|_ | _|_ Diodes allow current to flow when /|\ | /|\ transistors are turned off | | | R2 /\/\/\/ R3 R2 and R3 (optional) help drop current |__| |__| on turn-off | | X X Transistors to control which side of winding is powered. Given the rated maximum current through each winding and the supply voltage, the resistance and wattage of R1 are easy to compute. R2 and R3, if they are included, pose more interesting problems. The resistance of these depends on the maximum voltage the control transistors can handle. For example, if your supply voltage is 24 volts, and your transistors are rated at 75 volts, the drop across R2 and R3 can be as much as 51 volts without harming the transistors. If the operating current through the motor is 1.5 amps, R2 and R3 can be 34 ohm resistors. Note that an interesting alternative would be to use zener diodes in place of R2 and R3. Figuring the average wattage of R2 and R3 is a wonderful exercise in dynamics, particularly when you consider that the inductance of the motor windings is generally undocumented and varies with the rotor position (which determines the reluctance of the magnetic circuit). A couple of high wattage power resistors can cost more than a pair of power transistors plus a heat sink plus a small fan for forced air cooling! Furthermore, it is easy to design a linear current regulator that will give faster rise times than a current limiting resistor. Consider the following: + ________________| | | Zener (Vref) R1 | | |__________|/__|/ PNP Power transistor to control | |\ |\ current through winding. | diode | R4 | | /\/\/\/ One center tapped winding of motor | | | gnd X X Transistors to control which side of winding is powered. If R1 is 0.5 ohms and the forward voltage drop across the diode and emitter is 0.6 volts, a 1.7 volt zener diode will give a current of 1 amp through R1. Zener diodes in this voltage range are available, and can be connected as shown to provide the required reference voltage for a fixed current regulator. R4 in the above figure must be sized in terms of the current gain of the PNP transistor so that sufficient current flows through R1 and R2 in series to allow the transistor to conduct the rated motor current. Alternatively, Vref can be provided by an ADC for a variable current application, as required for microstepping. In this case, things are complicated by the fact that Vref is measured relative to the motor supply, and this is typically only minimally regulated. Note that the protection diodes have been omitted from the above figure, and also note that series resistors (R2 and R3 in the previous figure) are extremely useful in this context. Without these resistors, the fall time of the current when a motor winding is turned off is determined only by the low internal resistance of the winding plus the 0.5 ohm series resistor. Linear current regulation wastes energy, and for high current motors, it requires expensive power transistors, heat sinks and forced air cooling. In the above example, assuming that the DC resistance of the stepping motor winding is on the order of 4 ohms, the transistor will be dropping 20 volts at 1 amp, requiring it to dissapate 20 watts. Even R1 gets hot; for a 1 amp motor, half an ohm will dissapate 0.5 watts, but this loss is harder to avoid than the large loss in the transistor itself. Use of a switching regulator can avoid dissapating large amounts of power in the transistor. Such a regulator works by sensing the current through the winding and turning the control transistor off when the current is over the set point. When the control transistor is off, the current coasts back to the supply through the protection diodes until it falls enough that the control circuit can turn it back on. In the abstract, the necessary circuit looks like this: + 24 _______| | | Vref R1 | | b|_ __|a Comp | _____| | | | | /\/\/\/ One center tapped winding of motor Motor | | | Control - And --- X --- X Transistors to control which side Signals of winding is powered. The protection diodes and any additonal dropping resistors R2 and R3 have been omitted from the above diagram, but they are necessary! The comparitor compares the voltage at point a (the downstream side of R1) with the voltage at point b, the reference voltage, provided by a zener diode or DAC. When Va > Vb, the current is too low, so the output of the comparitor allows the control transistors to turn on, if required by the motor control signals. When Va < Vb, the current is too high, so the comparitor, through the and gate, turns off both transistors. This circuit must oscillate, so there must be some time delay and possibly some hysteresis in the feedback loop. In this circuit, the RL time constant of R1 and the motor winding, in series, provides the necessary delay. It may be necessary to add hysteresis, for example, by using the comparitor output to perturb the reference voltage. The sizes of the dropping resistors R2 and R3 pose interesting problems when a switching regulator is used. If no dropping resistor is used with a motor with very low internal resistance, a switching regulator can be an extremely efficient way to run a stepping motor, but it doesn't allow fast stepping because the current through the windings will take a long time to decay. If R2 and R3 are high, fast stepping is possible, but large amounts of power will be dissapated in R2 and R3, leading to inefficient operation. Computing the wattage of R2 and R3 is quite easy compared to the previous examples. Given the two RL time constants that govern the current rise and fall through R1, the duty cycle for current in either R2 or R3 can be computed, and as long as the current through R1 varies only slightly, this lets you compute the peak average power dissapated in R2 and R3. Note that the switching control system can be quite simple. Neither the comparitor nor the and gate imply the use of integrated circuits! The following outline illustrates how simple things can get: + ______________| | | | R1 Vref | | ________| |_|/_|/ | PNP transistor to do comparison |\ |\ | diode | | Open R4 /\/\/\/ One center tapped winding of motor Collector | | Control ____|__|/ NPN Darlington pair to control half the winding. Signal |\ | Gnd I haven't actually built a circuit based on the above, and I don't know if the switching delays in the transistors plus the RL time constant of the coil will be enough to guarantee that it oscillates! If it doesn't, Vref will need to be perturbed by a small amount depending on the state of the PNP transistor. Unfortunately, straight resistive feedback won't do because the sign is wrong. Control Software Now, here's the code to make your motor run as if you had one of those fancy stepper controllers. I've used Pascal for no particular reason. This code assumes only one motor, and it assumes it's attached to the least significant bits of one parallel output port. In practice, it's nice to have one parallel output port per motor, although with a bit of care, you can use the high bits of a port for another motor or other applications, and you can multiplex one port to handle multiple motors. (The July 1993 issue of Model Railroader has plans for a parallel port multiplexer circuit for IBM PC systems in it). Assume these declarations and values for a three winding variable reluctance motor: const maxstep = 2; steps = 3; var steptab: array [0..maxstep] of integer; step: integer; motor: file of integer; { this is the I/O port for the motor } begin step := 0; steptab[0] = 1; { binary 001 } steptab[1] = 2; { binary 010 } steptab[2] = 4; { binary 100 } write( motor, steptab[step] ); Assume these declarations and values for a permanent magnet motor, whether the windings are center tapped (allowing a simple drive circuit) or not (requiring a messy drive circuit like the one outlined above): const maxstep = 3; steps = 4; var steptab: array [0..maxstep] of integer; step: integer; motor: file of integer; { this is the I/O port for the motor } begin step := 0; steptab[0] = 1; { binary 0001 } steptab[1] = 4; { binary 0100 } steptab[2] = 2; { binary 0010 } steptab[3] = 8; { binary 1000 } write( motor, steptab[step] ); Assume these declarations and values for half-step control of a permanent magnet motor: const maxstep = 7; steps = 8; var steptab: array [0..maxstep] of integer; step: integer; motor: file of integer; { this is the I/O port for the motor } begin step := 0; steptab[0] = 1; { binary 0001 } steptab[1] = 5; { binary 0101 } steptab[2] = 4; { binary 0100 } steptab[3] = 6; { binary 0110 } steptab[4] = 2; { binary 0010 } steptab[5] = 10; { binary 1010 } steptab[6] = 8; { binary 1000 } steptab[7] = 9; { binary 1001 } write( motor, steptab[step] ); The remainder of the code is the same and doesn't depend on the motor. The following procedure will advance the motor one step in either direction, where the direction parameter must be either +1 or -1 to indicate the direction. procedure onestep( direction: integer ); begin step := step + direction; if step > maxstep then step := 0 else if step < 0 then step := maxstep; write( motor, steptab[step] ); end; Software control of a stepping motor is a real-time task, and you need at least a bit of feedback. One bit is enough; typically, this will be a bit indicating that a cam on the turntable (or whatever the motor is driving) is interrupting a light beam or closing a microswitch. To avoid hysteresis problems in reading the position from this cam, you should only read zero to one transitions as indicating the home position when the motor is spinning in one direction. Especially with switches or where gear trains are involved between the motor and the turntable, the one to zero transition in the other direction won't usually occur at exactly the same position. Given that you can read the sense bit and that you have a programmable interval timer interrupt on your system, it is easy to make the timer interrupt service routine operate the motor as follows: const maxpos = 11111; { maxpos + 1 is calls to onestep per rev } var position: integer; { current position of motor } destination: integer; { desired position of motor } direction: integer; { direction motor should rotate } last: integer; { previous value from position sensor } sensor: file of integer; { parallel input port } begin read( sensor, last ); position := 1; setdest( 0, 1 ); { force turntable to spin on power-up until it finds it's home position } procedure timer; { interval timer interrupt service routine } var sense: integer; begin read( sensor, sense ); if (direction = 1) and (last = 0) and (sense = 1) then position = 0; last := sense; if position <> destination then begin onestep( direction ); position := position + direction; if position > maxpos then position := 0 else if position < 0 then position := maxpos; end; if position <> destination then settimer( interval_until_next_step ); end; The following procedure is the only procedure that user code should call. This procedure sets the destination position of the turntable and sets the direction of rotation, then sets the interval timer to force an immediate interrupt and lets the timer routine finish rotating the turntable while the applications program does whatever else it wants. procedure setdest( dst,dir: integer ); begin destination := dst; direction := dir; if position <> destination then settimer( min_interval ); { force a timer interrupt } end; If you want to control multiple stepping motors, it is easiest if you have one interval timers and one parallel port per motor. If you hardware has only one timer, then you can use it to simulate multiple interval timers, but this is most of the way to the job of writing a real-time executive. A final note: If you try to step a motor too fast, it will slip and your software will lose track of the motor position. Motors typically come with a rating that indicates a maximum number of steps per second, but you may not be able to accelerate the motor to that number of steps per second from a dead start without running it at a lower speed first. This is especially true if the inertia of the load is fairly large, and in fact, with appropriate acceleration sequences, you can usually excede the maximum rated speed. In the above code, interval_until_next_step is shown as a constant. If you are dealing with high-inertia loads or very short intervals, you'll have to make this a variable, using longer intervals during starting and stopping to take care of accelerating and decelerating the motor.