Stepper Motor Driver
Sample ASM and Schematics
Overview:

In this section you will find the essential knowledge you require to get you started with stepper motors. The example illustrated here does not serve any purpose other then to educate but is built on a platform where you can do anything you wish, from simply spinning up to 8-steppers to controlling the exact movement of your steppers via the serial port on your computer. The Atmel chip used is extremely powerful and versatile.


Electronics:

As you may already know, microcontrollers are only the brains of a circuit, and no muscle. What this means is that alone they cannot drive such a large load as a stepper motor, an incandescent lamp, a solenoid or anything with a low impedance, usually they barely have enough power to drive an LED. The Atmel AT90S8515 is good in the sense that it can drive an LED without any problem, but if you try to drive the motor directly, you will burn the internal pull-up circuit and then you'll have a crippled microcontroller on your hand that can only pull down or not use that port at all. This is why you need to design a driver circuit that can power the steppers and is itself controlled by the microcontroller. Below is a very simple schematic of how you'd do this.

Transistor Wiring

To help place an overall picture of how things should loko like in the end, here are a two pictures of the finished circuit.

Single Motor Driver Single Motor Driver

The transistor used was a MPS2222A, which is a general purpose NPN transistor, capable of sinking up to 600mA DC. Each one of these transistors can drive ONE coil of the stepper motor, so for the motor used in this example, 4 identical circuits are required. Your other option is to use a driver, which was specially design for this, but I believe this is more constructive and easier to work with. The driver is basically just an array of circuits like the one above, all built into an IC.


Programming:

Here I assume you have a programmer (hardware not you) and also are using AVR Studio 4.0. If you don't know what I'm talking about, then consult the Atmel website for information and to get your free AVR Studio.
Before you go on, you need to understand how a stepper works, and why it is different then a regular motor. Firs of all, you should know that you cannot just spin a stepper by hooking it up to a battery, simply because it requires the driving circuit. What this circuit does, is it 'times' the coils inside the motor and by doing so (timing them properly is key) the shaft or the core of the motor advances and spins, the faster the timing the faster it spins. Each timing 'click' is a step, and the size of the step can tell you how smooth the motor can spin and also how slowly you can spin if before it starts jumping, rather then spinning. The motor used here, has a 1.8 deg step size, or it requires 200 steps to make one full revolution. The next thing you absolutely need to know about your motor is the stepping sequence, which is a table showing you which coil is powered, and when it is powered. This information is provided by the manufacturer or you need to figure it out somehow. (there are ways, but it is beyond the scope of this section)
The stepping sequence for the motor used here is shown in the table bellow.


Coil Coil 1 Coil 2 Coil 3 Coil 4
Step 0 OFF ON OFF ON
Step 1 OFF ON ON OFF
Step 2 ON OFF ON OFF
Step 3 ON OFF OFF ON
Step 4 OFF ON OFF ON

Although the code is documented it can look a little intimidating if this is your first ASM program, but keep in mind that just like in C or BASIC the CPU goes through it one line at a time and so you can read it just like the CPU does, so don't let it scare you. If you do not know the syntax, then go to Atmel.com and download the specs for the ATMEL AT90S8515 and look on the Instruction Set Table.
The code really has two sections, the first and the most important when working with microcontrollers are the initializations and getting everything set up. In this case, you need to first set the port that drives the motors as an output using the DDR (data direction register) register. Then, you have to initialize the stack pointer, this is required if you do function or sub calls, such as RCALL. Once that is done, you get down to the real programming, first you need to understand that the microcontroller is much much too fast for the motor, so you need to write a delay function that just waists time, and gives the motor time to move and the coils stabilize. Then you need to write the code that 'steps' through the sequence table, this is just a 4 step loop, and really does nothing but go from step 1 to 3 and starts again, if you need to make the motor go backwards, you step through the table backwards, step 3 to 1.

Here is the code, you can just cut and paste it into AVR Studio.

;#################################
;Ptepper Motor Driver/Sequencer
;    2 Phase Stepper Motor 
;        5.3V     0.17A
;        31.5 R/1.8 deg
;#################################

;***** Includes
.include "8515def.inc"

;***** Global Register Variables
.equ	Step0	=0b00000101	; This is the steping sequence CW
.equ	Step1	=0b00000110 ; You can alter this for diff motors
.equ	Step2	=0b00001010	; should obtain this from the specs.
.equ	Step3	=0b00001001

.equ	STable	=0x0060		;Start of step table (uses up 4 bytes)

.equ	delayCNT=0x12FF		;0AFF ~ 132.8 Hz @4.096MHz -- max
				;0BFF ~ 120.8 Hz @4.096Mhz
				;0CFF ~ 110.8 Hz @4.096MHz -- smooth
				;1FFF ~ 42.88 Hz @4.096MHz ~ 70 RPM

.def	temp	=r17		;temporary storage register
.def	temp2	=r16		;temporary register 2

;***** Interrupt Vectors or Handles
	RJMP	RESET


;***** CODE *****
RESET:
;***** Initialize Stack
	ldi 	temp, HIGH(RAMEND)
	out 	SPH, temp
	ldi 	temp, LOW(RAMEND)
	out 	SPL, temp
	CLR 	temp

;***** Initialize Ports
	clr 	temp		; Set everything as input (high inp.)
	out	DDRA, temp
	out	DDRB, temp
	out	DDRC, temp
	out	DDRD, temp
	ldi 	temp, 0x0F
	out	DDRB, temp		; Set Port B as output (careful with loading)

;***** Initialize Steping Table
; Please obtain this table from the manufacturers specs.
	ldi 	XL, low(STable)	; Point X to the begining of the step table
	ldi	XH, high(STable)
	ldi	temp, Step0
	st	X+, temp		; Now the sequencing is in SRAM
	ldi	temp, Step1
	st	X+, temp		; Fast and easy to extract.
	ldi	temp, Step2
	st	X+, temp
	ldi	temp, Step3
	st	X,  temp
	clr	XL
	clr	XH


;***** MAIN CODE *****
ldi R18, 200			; Make 20 Full Rotations CW
loop: 
	rcall CW
	dec R18
brne loop

ldi R18, 200			; Make 20 Full Rotations CCW
loop2: 
	rcall CCW
	dec R18
brne loop2

done: rjmp done			; Start and End in the exact same spot

;*********************




;***** Delay
delay:
push	temp
push	temp2

ldi temp,  LOW(delayCNT)	; Load how many interations
ldi temp2, high(delayCNT)	; the delay rutine should do.
keepgoing:
	dec temp
	brne keepgoing
	dec temp2
brne keepgoing

pop 	temp2
pop		temp
ret


;***** CW
; Spin the motor Clock Wise
; How many deg. depends on how many steps
CW:
push 	temp
push 	temp2
push 	XL
push 	XH

ldi		XH, high(STable)
ldi		XL,  low(STable)
ldi		temp2, 20	; Make a 1/4 turn and exit 
	stepCW:
		ld	temp, X+
		out	PORTB, temp
		cpi	XL, STable+4
		brne	not4yet
			subi	XL, 4
		not4yet:
		rcall 	delay
		dec 	temp2
	brne	stepCW

pop 	XH
pop 	XL
pop		temp2
pop		temp
ret


;***** CCW
; Spin the motor Counter Clock Wise
; How many deg. depends on how many steps
CCW:
push 	temp
push 	temp2
push 	XL
push 	XH

ldi	XH, high(STable+4)
ldi	XL,  low(STable+4)
ldi	temp2, 20		; Make a 1/4 turn and exit 
	stepCCW:
		ld	temp, -X
		out	PORTB, temp
		cpi	XL, STable
		brne	not4yet2
			subi	XL, -4
		not4yet2:
		rcall 	delay
		dec 	temp2
	brne	stepCCW

pop 	XH
pop 	XL
pop	temp2
pop	temp
ret
Troubleshooting:

If the motor does not spin, and just vibrates, then you have to check your wiring and make sure that pin0 goes to coil 1 pin1 to coil 2 and so on. If the motor does not do anything, put an LED between GND and the microcontroller pins and check to see if they blink, if they do not, check you are looking at the correct port. If the LEDs blink but the motor does nothing, then make sure the transistors are wired properly. Check MPS2222A to find wiring and specs. If nothing works, something has gone terribly wrong and you need to go through the whole thing from beginning to end, and you have to check that the microcontroller is programmed properly. Also check to make sure the clocking is done properly and the XTAL is actually resonating and working properly.

The Code above, was tested and it works, it spinns the motor clock wise and the nit reverses and stops where it started from, this may not be true for motors with a different stepping size.