Circuits > PC related > A Worked Stepping Motor Example
A Worked Stepping Motor Example
Perhaps some of the most commonly available stepping motors, for the experimenter,
are the head positioning motors from old diskette drives. These can be found at
electronics swap meets, in computer surplus outlets, and even in trash dumpsters.
In addition to a stepper, a typical full-height 5.25 inch disk drive includes a
12 volt DC motor with tachometer and motor control circuit board, two microswitches,
and a matched LED-photosensor pair.
A common stepper to find in a full-height IBM or Tandon 5.25 inch diskette drive
is the type KP4M4 made by either Japan Servo Motors or Tandon; this is a permanent
magnet motor with 3.6 degrees per step and 150 ohms per winding, with the center-taps
of each winding tied to a common lead. Many half-height 5.25 inch diskette drives
use very similar motors, although there is much more variety in newer drives, including
some that use bipolar steppers.
Another stepper sometimes found in half-height drives is the `pancake format'
motor from a 1/2 height 5.25 inch diskette drive; for example, a permanent magnet
motor made by Copal Electronics, with 1.8 degrees per step and 96 ohms per winding,
with center taps brought out to separate leads. The leads on these motors are brought
out to multipin in-line connectors, laid out as follows:
Figure 6.1

When the center-taps of these motors are connected to +12 and one end of either
winding is grounded, the winding will draw from 170 mA to 250 mA, depending on the
motor, so any of a number of motor drive circuits can be used. The original IBM
full-height diskette drives used a pair of UDN3612N or UDN5713 chips; these are
equivalent to chips in the SN7547X series (X in 1,2,3). The
ULN2003 darlington arrays
from Allegro Microsystems is probably
the most widely available of the applicable chips, so it will be used in this example.
Consider the problem of controlling multiple steppers comparable to those described
above from an IBM compatible DB25-based parallel output port. The pinout of this
connector is given in Figure 6.2, as seen looking at the face of the female connector
on the back of an IBM PC (or equivalently, as seen from the back of the male connector
that mates with this):
Figure 6.2

The IEEE 1284 standard gives the best available definition of the parallel port,
but as an after-the-fact standard, nonconformance is common.
Some documentation of this standard
is available in the net. There is an extensive set of
tutorial
material available on the web discussing the IBM PC Parallel port. Another index
of parallel port information is available from
Ian Harries.
There is some confusion in the documentation of this connector about the labels
on the SLCT and SLCTIN lines (pins 13 and 17); this is because these names date
back to a Centronics printer design of the early 1970's, and the name SLCTIN refers
to an input to the printer, which is to say, an output from the computer.
The names of some of these lines are relics of the original intended purpose
of this I/O port, as a printer port. Depending on the level at which you wish to
use the printer, some may be ignored. If the BIOS printer support routines of the
IBM PC or the parallel port driver under various versions of UNIX sare to be used,
however, it is important to pay attention to some of these signals:
The BIOS handles reinitializing the printer by producing a negative pulse on
INIT (pin 16). We can use this as a reset pulse, but otherwise, it should be ignored!
In the reset state, all motor windings should be off.
When no output activity is going on, the BIOS holds the output signal lines as
follows:
- STROBE (pin 1) high, data not valid.
- AUTOFD (pin 14) high, do not feed paper.
- INIT (pin 16) high, do not initialize.
- SELCTIN (pin 17) low, printer selected.
To print a character, the BIOS waits for BUSY (pin 11) to go low, if it is not
already low, and then outputs the new data (pins 2 through 9). Following this (with
a delay of at least 0.5 microsecond), STROBE (pin 1) is pulsed low for at least
0.5 microsecond. The BIOS returns the inputs ACK, BUSY, PE and SLCT (pins 10 to
13) to the user program after printing each character.
The computer is entitled to wait for ACK (pin 10) to go low for at least 5 microseconds
to acknowledge the output strobe, but apparently, IBM's BIOS does not do so; instead,
it relies on device to set BUSY to prevent additional outputs, and it leaves the
output data unmodified until the next print request. While neither MS/DOS nor the
BIOS use the interrupt capability of the parallel port, OS/2 and various versions
of UNIX use it. A rising edge on ACK (pin 10) will cause an interrupt request if
interrupts are enabled. This interrupt design is only useful if, in normal operation,
the trailing edge of the ACK pulse happens when BUSY falls, so that finding BUSY
high upon interrupt signals an error condition.
Note that all input output to the parallel port pins is done by writing to various
I/O registers; so as long as interrupts are disabled and the I/O registers are directly
manipulated by application software, all 5 input pins and all 12 output pins may
be used for any purpose. To maintain compatibility with existing drivers, however,
we will limit our misuse of these pins.
If we only wanted to support a single motor, it turns out that the logic on the
standard 5.25 inch diskette drive can, with an appropriate cable, be driven directly
from the parallel port. Documentation on this approach to recycling motors from
old diskette drives has been put on the web by
Tomy Engdahl.
Since we are interested in supporting multiple motors, we will use DATA lines
4 to 7 to select the motor to control, while using the least significant bits to
actually control the motor. In addition, because almost all stepping motor applications
require limit switches, we will use the PE (12) bit to provide feedback from limit
switches. The IEEE 1284 standard defines the PE, SLCT and ERR signals as user defined
when in either Enhanced Parallel Port or Compatibility mode, so this is not a bad
choice. Unfortunately, the BIOS occasionally checks this bit even when it is aware
of no printer activity (for example, when the keyboard type-ahead buffer fills);
thus, it is a good idea to disable the BIOS when the parallel port is used for motor
control!
Note that fanout is not a problem on the IBM PC parallel port. The IEEE 1284
standard defines the parallel port outputs as being able to source and sink 14 milliamps,
and older IBM PC parallel ports could sink about 24 milliamps. Given that a standard
LS/TTL load sources only 0.4 milliamps and some devices (comparitors, for example)
source 1.2 milliamps, an IEEE 1284 port should be able to handle up to 10 of motor
interfaces in parallel.
A Minimal Design
As mentioned above, we will use the ULN2003 darlington array to drive the stepping
motor. Since we want to drive multiple motors, the state of each motor must be stored
in a register; while many chips on the market can store 4 bits, careful chip selection
significantly reduces the parts count and allows for a single-sided printed circuit
card!
With appropriate connections, both the 74LS194 and the 74LS298 can use a positive
enable signal to gate a negative clock pulse; we will use the 74LS194 because it
is less expensive and somewhat simpler to connect. Finally, we will use the 74LS85
chip to compare the 4 bit address field of the output with the address assigned
to the motor being driven.
Figure 6.3 summarizes the resulting design:
Figure 6.3

The 74LS194 was designed as a parallel-in, parallel-out shift-register with inputs
to select one of 4 modes (do nothing, shift left, shift right, and load). By wiring
the two mode inputs in parallel, we eliminate the shift modes, converting the mode
input to an enable line. The unused right and left shift input pins on this chip
can remain disconnected or can be grounded, tied to +5, or connected to any signal
within the loading constraints.
Here, we show the 74LS194 being loaded only when bits 4 to 7 of the output data
match a 4-bit address coded on a set of address switches. The comparison is done
by a 74LS85, and the address switches are shown in Figure 6.3 as an 8-position DIP-switch.
The cost of a DIP switch may be avoided in production applications by substituting
jumpers.
One interesting aspect of this design is that the LS-TTL outputs driving the
ULN2003 chip are used as current sources -- they pull up on the inputs to the darlington
pairs. This is a borderline design, but careful reading of the LS-TTL spec sheets
suggests that there is no reason it should not work, and the ULN2003 is obviously
designed to be driven this way, with more than enough forward current gain to compensate
for the tiny pull-up capacity of an LS-TTL output!
The Zener diode connected between pin 9 of the ULN2003 and the +12 supply increases
the reverse voltage on the motor windings when they are turned off. Given the 50
volt maximum rating of the ULN2003, this may drop as much as 50-12 or 38 volts,
but note that power dissipation may actually be an issue! At high frequency with
unconventional control software, the power transfer to this diode can be quite efficient!
With the stepping motors from old diskette drives, it may be possible to push a
12 volt zener to on the order of 1 watt. I used a 15 volt 1 watt zener, 1N3024.
If this motor is to be driven by software that directly accesses the low-level
parallel port interface registers, directly loading data and then directly raising
and lowering the strobe line, no additional hardware is needed. If it is to be driven
through the BIOS or higher level system software, additional logic will be needed
to manipulate ACK and BUSY.
Although the 74LS85 and the 74LS194 are no longer stocked by some mass-market
chip dealers, they are still in production by Motorola, TI, Thompson SK and NTE.
If over-the-counter availability of chips is your primary concern, adding a chipload
of inverters or 2-input nand gates will allow just about any 4-bit latch to be used
for the register, and address decoding can be done by a quad XOR chip and a 4-input
nand gate.
If over-the-counter chips are of no concern, you can reduce the chip count even
further! The Micrel MIC5800 4-bit parallel latch/driver can easily handle the loading
of small unipolar steppers and combines the function of the ULN2003 and the 74LS194
used here! The resulting design is very clean.
Adding One Bit of Feedback
Surprisingly, no additional active components are needed to add one bit of feedback
to this design! There are 3 spare darlington pairs on the ULN2003 driver chip, and,
with a pull-up resistor for each, these can serve as open-collector inverters to
translate one or two switch settings into inputs appropriate for the PC!
The ULN2003 includes pull-down resistors on each input, guaranteeing that the
corresponding output will be turned off if left disconnected. Thus, connecting a
ULN2003 input to a positive enable signal (pin 5 of the 74LS85 chip for example)
will turn the output on only if it is both enabled and the switch is closed. It
may be necessary to add a 1K pull-up to the LS-TTL output because, in addition to
driving the ULN2003, it is also driving two normal LS-TTL inputs. Adding this pull-up
will do no harm if it isn't needed (an LS-TTL output should be able to handle even
a 300 ohm pull-up).
Since the ULN2003 is an open-collector inverter, the output needs a pull-up.
We could rely on the PE input of the IBM PC parallel port to pull this line up (an
open TTL input usually rises of its own accord), but it is better to provide a pull-up
resistor somewhere. Here, we provide a 10K pull up on each stepping motor drive
card; these pull-ups will be in parallel for all motors attached to a single parallel
port, so if fewer than 10 motors are in use, proportionally smaller resistors may
be substituted or the pull-ups may be omitted from some of the controller cards.
Figure 6.4 summarizes these additions to the design:
Figure 6.4

Something You Can Build
Figure 6.5 shows a single-sided PC board layout for a 2.5 inch square board that
incorporates all of the ideas given above. I have etched and tested the 7/8/1996
version of this artwork.
Figure 6.5
(What's that about copyright notices? Well, put simply, if you're going to sell
my design, please get in touch with me about it. You're free, however, to make a
handful of boards from this design to control your own motors.)
This version of the board includes a jumper to ground the BUSY signal on the
parallel port (pin 11) and it brings out the STROBE, ERROR, ACK and SELECT signals
to allow for possible jumpering. These changes make it slightly more likely that
this board can be hacked to work with native operating system drivers for the parallel
port. As is, with no special jumpering other than the grounding of BUSY, it works
under Linux.
To use the artwork in Figure 6.5 for etching a board, reproduce it at 100 pixels
per inch . Both versions are positive images of the foil side of the board; depending
on how you transfer the image to the resist for etching, you may need to flip it
left-to-right and/or invert the black and white. Most GIF viewers allow for such
transformations.
Figure 6.6 shows the component side of this board, with jumpers and parts in
place.
Figure 6.6

Note that this layout does not show mounting holes for the board, but that 4
corner pads are provided in appropriate locations. The layout also doesn't show
a power connector, but the standard 4-pin Molex connectors used with 5.25" diskettes
will fit the pads provided. The 26 pin header is wired so that it can be directly
wired to a 25 pin DB-25 plug using ribbon cable and insulation displacement connectors.
If multiple motors are to be used, a single ribbon cable can be made with multiple
26 pin connectors on it, one per motor.
Figure 6.6 shows 4 capacitors, 3 between +5 and ground, and 1 between +12 and
ground. The two capacitors farthest from the power input connector can be .01 or
.1 microfarad capacitors; it may be better to use larger capacitors at the power
input pins, 1 microfarad or more.
The plug from the stepping motor goes on the the top header shown in Figure 6.6,
with the center-tap lead(s) topmost. The board is arranged so that either a 5 or
6 pin header may be used here, compatable with the plugs on the motors shown in
Figure 6.1. The limit switch goes on the bottom header. The latter is wired so that
it can be used with either microswitch salvaged from a full-height Tandon 5.25 inch
diskette drive.
The address may be hard-wired using 4 jumpers, or it may be set using a DIP-switch,
as shown in Figure 6.6. Each bit of the address is set by two switches or jumper
positions, the topmost pair of these sets the most significant of the 4 bits. To
set a bit to 1, close the top switch and open the bottom switch in the corresponding
pair (or put the jumper in the top position of the pair); to set a bit to 0, close
the bottom switch and open the top one (or put the jumper in the bottom position
of the pair). If it is at all likely that someone will change the address switches
while power is applied to the board, use a 47 ohm resistor in place of the jumper
directly above the switches! This will protect your power supply from the accidental
short circuits that can result from improper switch settings.
Testing the Board
Under Linux
The standard Linux line printer driver attaches the device /dev/lp0 to the standard
parallel port found on most PCs, and /dev/lp1 and /dev/lp2 to the optional additional
parallel ports. The line printer driver has many operating modes that may be configured
and tested with the tunelp command. The default mode works, and the following tunelp
command will restore these defaults:
tunelp /dev/lp0 -i 0 -w 0 -a off -o off -c off
This turns off interrupts with -i 0 so that the board need not deal with the
acknowledge signal, and it uses a very brief strobe pulse with -w 0, sets the parallel
port to ignore the error signal with -a off, ignores the status when the port is
opened with -o off, and does not check the status with each byte output with -C
off. The settings of the tunelp options -t and -c should not matter because this
interface is always ready and thus polling loop iteration is never required.
Given a correctly configured printer port, the C routines allow output of motor
control bytes to the port:
/****
* ppaccess.c *
* package for Linux access to the parallel port *
****/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/lp.h>
#include <stdio.h>
#define paper_empty 0x20
static int pp; /* parallel port device descriptor */
void ppsetup()
/* setup access to the parallel port */
{
pp = open("/dev/lp0",O_WRONLY, 0);
if (pp < 0) {
printf( "can't open, %s\n",
_sys_errlist[errno] );
exit( 0 );
}
}
int ppput(int b)
/* put b to the parallel port, return the status */
{
char cbuf = (char) b;
int ibuf;
/* begin critical section */
if(write( pp, &cbuf, 1 ) != 1){
printf( "write error, %s\n",
_sys_errlist[errno] );
exit( 0 );
}
if(ioctl( pp, LPGETSTATUS, (char*)&ibuf ) < 0){
printf( "/dev/lp0 ioctl error, %s\n",
_sys_errlist[errno] );
exit( 0 );
}
/* end critical section */
return ibuf & paper_empty;
}
The comments above indicate a critical section! This is only a concern if the
parallel port is shared by multiple processes, perhaps with one process in charge
of each of a number of motors. In that case, a semaphore must be used to guard the
critical section (see the UNIX semctl() kernel call), or a file lock using F_LOCK
and F-ULOCK fcntl() commands, preferably through the lockf() function with a very
large size. The latter approach (file locking using lockf()) is probably preferable.
Given these routines, the following main program should spin the motor at a few
steps per second in a direction that depends on the sense switch setting:
/****
* spin.c
* Linux program to spin a permanent magnet motor *
the sense switch gives forward/reverse control *
****/
#include <unistd.h>
#define motor_number 15
#define microsec 1
#define millisec (1000*microsec)
int steptab[] = { 9, 10, 6, 5 };
main()
{
int step = 0;
ppsetup();
for (;;) {
if (ppput(steptab[step]|motor_number<<4)) {
step = (step + 1)&3;
} else {
step = (step - 1)&3;
}
usleep( 100 * millisec );
}
}
Under Quasic
To test your board, use the following little basic program. This was developed
under Microsoft's Qbasic (C:DOS/QBASIC on a typical off-the-shelf PC) under bare
MS/DOS (no version of windows running). This code has been tested with the prototype
hardware for the design given above.
The first subroutine in this program outputs the data D to motor M attached to
printer port P, and reads the status into S.
100 OUT P, D + (16 * M)
OUT P + 2, &HD
OUT P + 2, &HC
S = INP(p + 1)
RETURN
The second subroutine updates D, the motor control output, to rotate the motor
one step, then uses the first subroutine to output D.
200 IF D = 9 THEN
D = 10
ELSEIF D = 5 THEN
D = 9
ELSEIF D = 6 THEN
D = 5
ELSEIF D = 10 THEN
D = 6
END IF
GOSUB 100
RETURN
The main program connects the second subroutine to the real-time clock and uses
it to step the motor once per second, then repeatedly prints the status reported
by the motor.
P = &H378
M = 15
D = 10
ON TIMER(1) GOSUB 200
TIMER ON
305 LOCATE 5, 5
PRINT "STATUS: "; S; " "
GOTO 305
Unfortunately, QBASIC doesn't give you access to the high resolution of the hardware
real-time clock, so this prototype code is only good for testing the hardware. While
this code is running, the status of the microswitch (if connected) will be displayed
on the screen, embedded in the rest of the I/O port status word.
Title: A Worked Stepping Motor Example
Source: www.electronics-lab.com
Published on: 2005-02-03
Reads: 572
Print version:  Circuits > PC related > A Worked Stepping Motor Example |