From news.media.mit.edu!grapevine.lcs.mit.edu!uhog.mit.edu!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!pipex!uunet!hobbes!earth.armory.com!rstevew Tue Mar 15 17:11:03 EST 1994 Article: 8897 of comp.robotics Newsgroups: comp.robotics Path: news.media.mit.edu!grapevine.lcs.mit.edu!uhog.mit.edu!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!pipex!uunet!hobbes!earth.armory.com!rstevew From: rstevew@armory.com (Richard Steven Walz) Subject: Re: Driving Stepper Motors Organization: The Armory Date: Tue, 15 Mar 1994 08:52:06 GMT Message-ID: References: <94071.163022U54136@uicvm.uic.edu> Sender: news@armory.com (Usenet News) Nntp-Posting-Host: deeptht.armory.com Lines: 247 In article <94071.163022U54136@uicvm.uic.edu>, wrote: >I have recently aquired a few 12 volt, 1.8 degree, bipolar step motors, but >I am having trouble getting them to work. I have (1) built a simple computer >interface to drive them, and (2) built a simple logic controller type of >arrangement, but in both cases the stepper motor just kind of jumps around. > >How the heck do I get these things working? Does anyone know of any decent >books on this subject. > >Thanks, Tim ------------------ Have you and others ween the tutorial steppers file to follow? -Steve Walz rstevew@armory.com ----------------- CONTROL OF STEPPING MOTORS By Douglas W. Jones University of Iowa jones@herky.cs.uiowa.edu COPYRIGHT 1990 All rights reserved. Permision is hereby given to make copies for personal use and to distribute copies of this material on the USENET electronic network news service. All other copying of this material is prohibited. I see no advantage to using commercial stepping motor controllers. 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. Here's a simple plan for computer control of a stepping motor, the kind where the DC resistance of the windings is all you need to limit the current through the motor. The control circuitry for other motors gets more complex because of the need to limit the current through the windings with a ballast resistor or better yet, a transistorized curent limiter. + logic power + motor power | ( 5 volts ) | ( 12 or 24 volts ) | ------| | diode | | | to kill | ----- | 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 requires one darlington transistor, one diode, one resistor, and one sixth of the SN7407 chip. The same circuit will work solenoids, uncoupling magnets, and switch machines. 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. This is not expensive! 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 ---> If your motor has two center tapped windings, typically with 6 wires, it's probably a 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. 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. 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: 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 parater 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 r the turntable 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. ------------------------------------------------------------------------