Dual Stepper Motor Driver for a Robot Differential Drive




Introduction
This article describes the hardware and the software used to control two stepper motors suitable for a robot differential drive.The circuit accepts two 2-bit words that command each of the motors to go forward, backward, hold a position, or to idle. It also provides an output signal when a step is being taken. It is a flexible design allowing for unipolar and bipolar motors and being microcontroller based the winding excitations, motor speed, control word format, and other parameters can be tailored in software. The software is provided in C and in assembly language.
Hardware Circuit
The circuit consists of three ICs, a PIC16F84 and either two L293D H-bridge drivers for bipolar steppers (shown in the figure below) or two ULN2803 for unipolar steppers. Aside from the power supplies, the only other components are a 4 MHz. resonator, a 10K pull-up resistor, and some connectors. In the current implementation a pack of 6 x 1.2V batteries, supplying 7.2V, is linearly regulated to 5V to supply the logic voltage and the raw unregulated power is applied to the 5V steppers. The 7.2V do not overdrive the motors due to the voltage-drop across the bipolar transistors in the drivers.

PROGRAM:

Constants
EXCITATION_TABLE_SIZE = 4 // number of excitations in sequence
TMR0_CNT_UP = 100 // 256 - duration (motor speed)

// Motor states
RIGHT_FORWARD = 0 // These can be re-ordered
RIGHT_BACKWARD = 1
RIGHT_HOLD = 2
RIGHT_IDLE = 3

LEFT_FORWARD = 0 // Above states shifted 2 bits left (multiplied by 4)
LEFT_BACKWARD = 4
LEFT_HOLD = 8
LEFT_IDLE = 12


GlobalVariables
leftExcitationCntr // current left motor excitation number
rightExcitationCntr // current right motor excitation number
motorState // 4 bit function word for both motors

excitations[] = {11000000b, // Excitation table - if the table is changed in size,
01100000b, // then the EXCITATION_TABLE_SIZE constant
00110000b, // must be changed
10010000b}
Functions
motorISR // Motor Interrupt Service Routine
// Modifies global variables leftExcitationCntr and rightExcitationCntr as a function of motorState.
// It uses these counters as indices to read the motor excitation from the table and outputs it to PORTB.
LocalVariables leftExcitation, rightExcitation
if (motorState is RIGHT_FORWARD)
if (rightExcitationCntr = EXCITATION_TABLE_SIZE-1)
rightExcitationCntr = 0
else
increment rightExcitationCntr
rightExcitation = excitations[rightExcitationCntr]
else if (motorState is RIGHT_BACKWARD)
if (rightExcitationCntr = 0)
rightExcitationCntr = EXCITATION_TABLE_SIZE-1
else
decrement rightExcitationCntr
rightExcitation = excitations[rightExcitationCntr]
else if (motorState is RIGHT_HOLD)
rightExcitation = excitations[rightExcitationCntr]
else // RIGHT_IDLE
rightExcitation = 0
shift rightExcitation 4 bits right
if (motorState is LEFT_FORWARD)
if (leftExcitationCntr = EXCITATION_TABLE_SIZE-1)
leftExcitationCntr = 0
else
increment leftExcitationCntr
leftExcitation = excitations[leftExcitationCntr]
else if (motorState is LEFT_BACKWARD)
if (leftExcitationCntr = 0)
leftExcitationCntr = EXCITATION_TABLE_SIZE-1
else
decrement leftExcitationCntr
leftExcitation = excitations[leftExcitationCntr]
else if (motorState is LEFT_HOLD)
leftExcitation = excitations[leftExcitationCntr]
else
leftExcitation = 0
PORTB = leftExcitation + rightExcitation
end motorISR


interrupt // Main interrupt service routine gets control when TMR0 overflows
if (TMR0 overflowed causing an interrupt)
bit 4 of PORTA = 1 // signal motor step on
call motorISR // call motor interrupt service routine
bit 4 of PORTA = 0 // signal motor step off
TMR0 = TMR0_CNT_UP; // reset TMR0 to proper count
end interrupt


main
set TMR0 prescaler = 64 // divides clock by value set
bit 4 of PORTA = 0 // signal motor step off
leftExcitationCntr = 0
rightExcitationCntr = 0
TMR0 = TMR0_CNT_UP;
enable TMR0 interrupts
while (1) // continuously update motorState (and wait
motorState = PORTA // for a TMR0 interrupt)
end main

Conclusion
A general, albeit rudimentary, micro-controller based stepper motor driver has been designed and successfully built. Since only 124 of the 1024 words of PIC16F84 memory is currently being used (in the assembly version) features could be added such as acceleration and deceleration. All 13 I/O lines are currently being used and so additional external control signals may require a PICmicro® upgrade. The PIC16F876 with Pulse Width Modulation and Analog to Digital conversion may also allow a chopper-drive design.