Arduino chip as Stepper Controller

A unipolar stepper driver controller.
At this point Pins 2 & 3 are Step and Direction Inputs.

Motion programs like Mach3 and other CNC programs provide the step and direction signals, and this would then take those signals and use the outputs to drive the 4 phases of a stepper motor.

There are dedicated chips for doing this, but this would give me more ability to control the function of my stepper controller. THis is just 1:1 stepping, but minor programming would give 2:1 and other ratios could be done by using analog outputs or a device other than a transistor for the final output device.

Now i am confused. Do you use the dedicated chip to drive the stepper or the Arduino.
If you use the PC to send Direction and Step commands what does the Arduino do?

A stepper motor is 4 sets of coils that you power in sequence to cause the motor to rotate. Most programs that want to do motion supply a step and a direction signal.

Now there are various ways to do this. A circuit can be made using a counter and a 2 to 4 decoder, various stepper driver chips and all require some higher power dice to actually feed power to the motor windings.

One solution is a PIC based Stepper controller, but as I have no experience with PICs no programming tools, no other pic hardware...

So - I wondered what it would take to do this with a AVR. Program size is 1560 bytes, so I could do this with something with only 2K, but would it have enough pins to do the other functions? ( ATtiny2313 might work, but I need programming hardware 2.88 for 3 = 8.64, 14.95 for programmer total 23.50 + shipping, Arduino chip - 5.50 for 3 = 16.50)

So - I need a chip that will - at the least - take 2 inputs, 1 STEP and 1 DIRECTION. Depending on the state of the direction pin Step causes a counter to be either incremented or decremented. And base on the value of the counter (which has limits of 0 to 3) turn on the proper output(s). Simple stepping means that winding 1, winding 2, winding 3, or winding 4 will be on at any one time. (looks like 1, 2, 3, 4, 1, 2, 3, 4,..) or I could program in another sequence (I think it is called wave mode) would look like 12, 23, 34, 41, 12, 23,34,.... Halfstepping - 1, 12, 2, 23, 3, 34, 4, 41, 1, 12, 2, 23, 3,...

I can hook up whatever output transistors I want based on my current requirements an amp or 2, or 8 to 10 amps.

So - I have my Arduino, a resonator, 4 transistors and 4 diodes, hook 3 of them up to my computer (Mach3) and have a 3 axis CNC or Robot. Or hook 3 of them to an Arduino and have a 3 axis, all Arduino CNC.

So you have ONLY 4 transistors. In all my circuitry i am using the example given here:
http://vimeo.com/6972843

But if you need to connect 3 steppers to the Arduino there are not enough outputs to work with.
Then one has to use a dedicated chip that only uses 2 or 3 inputs eg STEP, DIRECTION and mayby als ENABLE.

But there are even circuits somewhere on the net that uses the PC's printerport and then you dont need the Arduine.

I know - I can buy a dedicated chip to drive the transistors to in turn drive a stepper motor.

Those chips all have their limitations and requirements. I was attempting to use an Arduino/AVR chip in a similar way to the PICStepper.

I have the logic working and I now need to see how fast it will function.

By using a programmable chip I can easily use standard stepping (1, 2, 3 ,4 ,1...)
or I can use wave stepping (12, 23, 34, 41, 12...)
or I can use Half Stepping (1, 12, 2, 23, 3, 34, 4, 41, 1...)

I can use an Arduino, a resonator, 4 transistors and 4 diodes and 4 resistors and a small piece of perfboard.

Some-one else has created a version that has microstepping abilities.

The Arduino doe not have to be the primary brain in a circuit to be use appropriately. Some times it can be an auxiliary circuit.

What i am looking at is this - can I put together a multi-axis system and could the Arduino be a useful part of the circuit? I have to get a few driver transistors and see just how fast the Arduino will switch and how fast I can run a motor using the Arduino as a stepper controller.

1 Arduino with 2 inputs to the interrupt pins, and 4 pins outputting for the 4 phases of a unipolar stepper motor, to start. A couple H bridges and it would work with unipolar steppers.

Just because someone has already created a circuit for a function doesn't mean that we can't try to do it a different way. Using the logic that says that there are already chips out there to drive a stepper would also suggeswt that one should not bother trying to create a computer because someone else has already done that.

gharryh -
And how do you hook it up to a computer? I don't see any IO going on.
Read the code - interrupts are inputs. If nothing happens on the interrupt pins (pins 2 & 3 ) then nothing happens in the program. Interrupts are fast, non-polled (interrupt) inputs. When the pin meets the conditions in the interrupt definition line, the currently executing code is INTERRUPTED, and the appropriate routine is executed.
Now i am confused. Do you use the dedicated chip to drive the stepper or the Arduino.
The Arduino becomes the dedicated chip that drives the stepper motor.
If you use the PC to send Direction and Step commands what does the Arduino do?
It takes the step and direction signals and drives the outputs to the transistors that power the stepper motor. The Arduino is the STEPPER CONTROLLER CHIP.
But if you need to connect 3 steppers to the Arduino there are not enough outputs to work with.
No, I use 3 arduinos setup as stepper controllers and each Arduino drives 1 stepper motor. Later I can add limit switch inputs or other functionality that I think I might want. In software it is rather cheap to try things. I can create a different version of my stepper controller and I don't have to use a soldering iron, instead I use my keyboard...
Then one has to use a dedicated chip that only uses 2 or 3 inputs eg STEP, DIRECTION and mayby als ENABLE.
If you would have read my comments you would have seen that I am not trying to hook more than 1 stepper to the Arduino - I am trying to use the arduino as the stepper controller.
But there are even circuits somewhere on the net that uses the PC's printerport and then you dont need the Arduino.
The I guess we should all scrap our Arduinos because we are all recreating stuff that is already out there, but in a different form than we might wish to use. And it would appear that you feel I have an obligation to fund these other projects, even if they are not quite what I want? You need to (to use an over-used phrase) think outside the box. In other words, try something different, just because, and see if maybe you can come up with a better, faster, cheaper, more personally satisfying solution for what you wish to do. After all - that is what the Arduino is all about.
I want a stepper controller as part of a system, Not a standalone Arduino making 2 stepper motors move. The arduino is probably overkill, but the chip is cheap, is easy to work with and I have them in hand. Maybe later I will get the stuff and try it with an ATtiny2313, but then I will have to learn a few different tools and I am just a bit lazy...

kfqtd - Please follow up with future posts on your progress. The thought of using the ATtiny2313 as a component is appealing to me. I used to do similar stuff back in the Z80 days (I am a retired engineer) and the Arduino has sparked my interest anew. It has been fun to knock the dust off of my old soldering iron and tinker again. I used to use the Z80 in lots of interrupt driven situations and I am eager to see more sophisticated uses for the Arduino/ATtiny2313.


****** This code has a problem... the interrupts don't function the way I wrote it. Can't have 2 interrupt routines on one interrupt...
But if you look farther down I have some cleaner code that does work...


Here's the latest code -
I chose to use 2 interrupts on the direction pin as I could simplify the code, and thus make it run faster.
OOPS... That didn't work to well, only got the second one of the 2...

There are 3 step procedures - 2 are commented out, the active one is for half stepping.
Here it is -

/*
Step & Direction Stepper Driver
Pins 9, 10, 11, 12 are tied to transistors
for each of the motor phases.
Pins 2 & 3 are used as interrupts,
Pin 2 as Step and 3 as Direction.
*/

int pin1 =9;
int pin2 = 10;
int pin3 = 11;
int pin4 = 12;
int pinDir = 3;
volatile int ctr;
volatile int dir;
void setup()
{
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(2, INPUT);
  ctr=0;
  dir = 0;
  attachInterrupt(0, Step, RISING);
  attachInterrupt(1, DirPos, RISING);
  attachInterrupt(1, DirNeg, FALLING);
}

void loop()
{
  
}

/* This pattern for simple stepping */  
/*
void Step()
{
 if (dir)
 {
   ctr-- ;
 }
 else
 {
   ctr++ ;
 }
 ctr = ctr & 3;

 switch (ctr){
 case 0:
   digitalWrite(4,HIGH);
   digitalWrite(5,LOW);
   digitalWrite(6,LOW);
   digitalWrite(7,LOW);
   break;
 case 1:
   digitalWrite(4,LOW);
   digitalWrite(5,HIGH);
   digitalWrite(6,LOW);
   digitalWrite(7,LOW);
   break;
 case 2:
   digitalWrite(4,LOW);
   digitalWrite(5,LOW);
   digitalWrite(6,HIGH);
   digitalWrite(7,LOW);
   break;
 case 3:
   digitalWrite(4,LOW);
   digitalWrite(5,LOW);
   digitalWrite(6,LOW);
   digitalWrite(7,HIGH);
   break;
 }
}
*/
/* use this sequence for wave stepping */  
/*
void Step()
{
 if (dir)
 {
   ctr-- ;
 }
 else
 {
   ctr++ ;
 }
 ctr = ctr & 3;

 case 0:
   digitalWrite(4,HIGH);
   digitalWrite(5,HIGH);
   digitalWrite(6,LOW);
   digitalWrite(7,LOW);
   break;
 case 1:
   digitalWrite(4,LOW);
   digitalWrite(5,HIGH);
   digitalWrite(6,HIGH);
   digitalWrite(7,LOW);
   break;
 case 2:
   digitalWrite(4,LOW);
   digitalWrite(5,LOW);
   digitalWrite(6,HIGH);
   digitalWrite(7,HIGH);
   break;
 case 3:
   digitalWrite(4,HIGH);
   digitalWrite(5,LOW);
   digitalWrite(6,LOW);
   digitalWrite(7,HIGH);
   break;
 }
}
*/  
/* Use this sequence for half stepping */

void Step()
{
  if (dir)
  {
    ctr-- ;
  }
  else
  {
    ctr++ ;
  }
  ctr = ctr & 7;
  switch (ctr){
  case 0:
    digitalWrite(4,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    break;
  case 1:
    digitalWrite(4,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    break;
  case 2:
    digitalWrite(4,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    break;
  case 3:
    digitalWrite(4,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,HIGH);
    digitalWrite(7,LOW);
    break;
  case 4:
    digitalWrite(4,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
    digitalWrite(7,LOW);
    break;
  case 5:
    digitalWrite(4,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
    digitalWrite(7,HIGH);
    break;
  case 6:
    digitalWrite(4,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
    digitalWrite(7,HIGH);
    break;
  case 7:
    digitalWrite(4,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
    digitalWrite(7,HIGH);
    break;
  }  
}  

void DirPos()
{
    dir = 0;
}
void DirNeg()
{
    dir = -1;
}

I went looking for the necesary pieces to program the ATtiny2313 with the Arduino GUI and found the arduino-tiny-0100-0010 library (Google Code Archive - Long-term storage for Google Code Project Hosting.) and select downloads near the top. You copy the libraries into the Hardware directory of the Arduino-1.0 install and it adds a number of the ATtiny chips. You then program them using the Arduino as ISP setting. I am gong to order some pieces parts and see what I can do with this code.

Here is the readme file that comes with the package -

Arduino-Tiny is an open source set of ATtiny "cores" for the Arduino platform.

The Arduino platform currently supports Atmel ATmega processors. There is a need
for the Arduino platform to work with physically smaller DIP package processors.
The intent of this project is fulfill that need. Specifically, our goal is to
provide a core that enables Arduino users to work with the ATtiny 84 (44/24),
ATtiny 85 (45/25), and ATtiny 2313 processors.

For more information about Arduino, see the website at: http://www.arduino.cc/

INSTALLATION

First ensure the Arduino software is correctly installed.

Next...

  • Ensure the Arduino IDE is NOT running.

  • Download the Arduino-Tiny archive (ZIP-file).

  • Locate the Arduino Sketch folder. This is the folder where the Arduino IDE
    stores Sketches.

  • Ensure the "hardware" folder exists under the Arduino Sketch folder. For
    example, if the Arduino Sketch folder is...

C:\Projects\Arduino\

Ensure this folder exists...

C:\Projects\Arduino\hardware\

  • Extract the contents of the archive into the "hardware" folder. For example,
    if the Arduino Sketch folder is...

C:\Projects\Arduino

After extracting, the following two files should exist...

C:\Projects\Arduino\hardware\tiny\boards.txt
C:\Projects\Arduino\hardware\tiny\bootloaders\attiny84\empty.hex

And the following folder should contain the Arduino-Tiny core...

C:\Projects\Arduino\hardware\tiny\cores\tiny\

  • Open the "boards.txt" file and change both of the "upload.using" entries to
    the appropriate value for your setup. Following from the examples above, the
    file would be here...

C:\Projects\Arduino\hardware\tiny\boards.txt

  • Start the Arduino IDE and ensure there are two new boards listed under the
    [Tools] [Board] menu...

"ATtiny84 @ 8 MHz"
"ATtiny84 @ 1 MHz"

You are now ready to use Arduino-Tiny!

CREDITS

Arduino is an open source project, supported by many.

The Arduino team is composed of Massimo Banzi, David Cuartielles, Tom Igoe,
Gianluca Martino, and David A. Mellis.

Arduino uses the GNU avr-gcc toolchain, avrdude, avr-libc, and code from
Processing and Wiring.

Arduino-Tiny is based on work by David A. Mellis, René Bohne, R. Wiersma,
Alessandro Saporetti, and Brian Cook.


I previously had tried to have a single interrupt do 2 things. Didn't work, then I looked at how I had been processing the
Direction interrupt and it hit me - I was going to get either a 1 or a zero from input 3, and I needed a 0 or -1 SO -
dir = digitalRead(3) would give me 0 or 1, and dir = -digitalRead(3) with minimal effort would give me 0 or -1.

I am getting ready to order a batch of components so, in a week or so, I should have a ATtiny2313 programming
board built to plug into my Arduino board for programming, along with a few other components to play with.

Awhile back I did about the same thing with a 2313. I drove four TIP120's with the four pwm outputs but on the 16bit timer I drove that in 8 bit mode so it was only a matter of building a 4 wide 8bit table for the compare registers. Did it with a tiny24 also (same timer setup).

Pretty simple to get smaller steps - I only did a 1/4 step table. In essence it was just a sine table.

Less than 48 hours and I should have some chips in my hands...

Thinking of direct port output to speed up the output to the driver transistors. Something to study...

Okay - Now I've done it :D...

Got looking for Direct Port I/O and found a part of the Arduino documentation that doesn't seem to have a direct link.
Here's the link - Arduino Reference - Arduino Reference
It explains some of the problems and some of the uses. In a general Arduino project you might not want to use this approach as there are a few pitfalls that the Arduino IDE hides from you, and that is not always a bad thing. As i intend to use this in a dedicated chip it should cause me no problems.

Port B on the Arduino/ATMege328 is pins 8, 9, 10, 11, 12, 13, with the 2 remaining pins used by the crystal/resonator
DDRB is the Data Direction Register. Assigning 1 to a bit makes it an output, 0 makes it an input.
PORTB is the predefined variable that lets you read or write port B.
PORTB = B0001 turns on pin 8 and turns off pin 9, 10 & 11.

I also used pre-initialized arrays to set up the step patterns.

Down to 1232 bytes.

Here's the last version of the code -

/*
Step & Direction Stepper Driver
 Pins 8, 9, 10, 11 are tied to transistors 
 for each of the motor phases.
 Pins 2 & 3 are used as interrupts,
 Pin 2 as Step and 3 as Direction.
 */
// the following 3 arrays contain the bit patterns to drive the transistors to in turn drive each of the phases of the stepper
int patSimple[] = {B0011,B0010, B0100, B1000, B0001, B0010, B0100, B1000};
int patWave[] = {B0011, B0110, B1100, B1001, B0011, B0110, B1100, B1001};
int patHalf[] = {B0001, B0011, B0010, B0110, B0100, B1100, B1000, B1001};
int pinDir = 3;
volatile int ctr;
volatile int dir;
void setup()
{
  DDRB = B1111 ;  // this enables Port B Bits 0 - 3, Arduino I/O 8, 9, 10, 11 as outputs
  pinMode(pinDir, INPUT);
  ctr=0;
  dir = 0;
  attachInterrupt(0, Step, RISING);  // Depending on the application FALLING might be a better choice.
  attachInterrupt(1, Direction, CHANGE);
}

void loop()
{
// Nothing to see here...  
}

void Step()
{
  if (dir) 
  {
    ctr-- ;
  }
  else 
  {
    ctr++ ;
  }
  ctr = ctr & 7;
// 2 of the following 3 lines must be commented.
//  PORTB = patsimple[ctr];  // Simple Stepping
//  PORTB = patWave[ctr];    // Wave Stepping
     PORTB = patHalf[ctr];      // Half Stepping
}  

void Direction()
{
    dir = -digitalRead(pinDir);    // Direction is 0 (zero) or -1 (minus one)
}

Got my chips and parts on Monday and Tuesday night I put together a board for programming ATMega328 and ATTiny2313 chips. I didn't order any 120Ohm resistors so I had to wait til yesterday to test it out.

Used AVRDude to program the chips and had to add a section to the avrdude.conf file for the ATMega328 as it only had the ATMEga328P. I could have added the -F argument to the command string, but it was just as easy to add a section for the 328. Copied the whole 328P section and made 3 changes - in the 2 locations where 328P appeared I erased the P and I changed the System Descriptor bytes (avrdude reports what it finds if it doesn't agree) from 1E 95 0F to 1E 95 14 and everything worked. Took the chip out of the programming socket and swapped it for the chip in my Arduino board and loaded it with Blink.

I also put one of my ATTiny2313 chips in the and used the Arduino IDE to load the code to the 2313 and it seems to have loaded just fine. Have to hook up a circuit and test out the chip. Will probably be Sunday night before I get the chance as I have too much in my schedule between now and then.

I will post a picture of my programmer board and a schematic the first of the week.

Just so you know, you are on the right track. I drive a unipolar stepper using 1/16 step microstepping driving 4 TIP110s's from PORTB and C of my ATMEGA168 using 8-bit fast PWM. You can either store the sine wave values in an array or in a table/switch statement.

IMPORTANT: this works for me because 1. I use ~5kHz PWM, not the standard arduino 500Hz PWM and 2. I only need to rotate slowly.

To microstep using PWM you have to use a PWM frequency several times higher than the fastest microstepping rate you anticipate. This means that at the standard Arduino PWM rate of ~500Hz you will only be able to meaningfully microstep at about 100Hz--even that is only 5 PWM cycles per microstep--which at full step for a 1.8* motor is only 30RPM and for 1/8 microstepping (1600steps/rev) you will only be able to meaningfully microstep at 1/4RPM. Which might be fine if you are making a rotisserie; I only need 10RPM myself.

To be able to output small microsteps at high microstepping rates, you have to crank up the PWM frequency; this is basic sampling theory. There is no problem in principle; commercial microstepping drivers run their PWM at about 30kHz, but I assume we would run into trouble with our discrete TIPs and have to write very tight code (maybe assembly) to use PWM rates that high. I don't know, but I do know that my 5kHz is going fine.

Well it works. (almost didn't, hooked the chip up upside down and generated a little heat...) plugged the chip in and hooked up to my led drivers and it works.

Got a few things to take care of before I can play with it too much so ... The first of the week i should have a stepper driver working.

So - It is really rather easy to hook up an ATTiny2313 to an Arduino programmed as an ISP and load the code into the 2313. I did have to use version 0.22 of the Arduino Environment to have teh ArduinoISP work properly, but I stumbled across that little piece of info somewhere along the way.

Worked on the board for my first driver. Got it mostly soldered up and got to thinking that I would have to change the bleeder resistor as 56Ohms wold draw too much current from the 328, so I will have to pull them and get some resistors in the 120 to 220 range. Oh well, minor setback.

Got to playing with assembly language - took my code size from 1200 bytes to 86 bytes.

Out of necesity, Arduino adds a lot of overhead to interrupt routines. Saves all the registers and such, but it would take a lot more power to analyze the code and reduce that overhead. Writing in assembler means I had to do the optimizing and I am responsible for what can go wrong...

I am using AVRStudio 4 to write and test the code (has a simulator built in)(even has a disassembler that will load the hex files and list them )
I recommend AVR Studio 4 over 5 as 5 is just to S-L-O-W...

Here's what the code looks like in assembler.

.NoList
.INCLUDE "tn2313Adef.inc" ; Header for ATTINY2313A
.List
; ============================================
;   R E G I S T E R   D E F I N I T I O N S
; ============================================
.DEF Conf = R16 ; Multipurpose register
.DEF StepCt = R17
.DEF StepMask = R18
.DEF Direction = R19
.DEF PortBHold = R20
.DEF PortDHold = R21
.DEF PortDMask = R22
.DEF SeqBase = R23
; ============================================
;   R E S E T   A N D   I N T   V E C T O R S
; ============================================
.CSEG
.ORG $0000
	rjmp Main ; Reset vector
	rjmp Step ; Int vector 1
	rjmp Dir ; Int vector 2
	reti ; Int vector 3
	reti ; Int vector 4
	reti ; Int vector 5
	reti ; Int vector 6
	reti ; Int vector 7
; ============================================
;     I N T E R R U P T   S E R V I C E S
; ============================================
Step: add StepCt,Direction
      and StepCt,StepMask
      mov ZL,SeqBase
	  add ZL,StepCt
	  Lpm PortBHold,Z
	  out PORTB,PortBHold
	  reti
Dir:  ldi PortDMask,8
      in  PortDHold,PIND
      and PortDHold,PortDMask
      breq SinNeg
	  ldi Direction ,1
      rjmp DirEx
SinNeg:	  ldi Direction ,-1
DirEx:reti
; ============================================
;     M A I N    P R O G R A M    I N I T
; ============================================
Main:
; Init stack
	ldi Conf, LOW(RAMEND) ; Init LSB stack
	out SPL,Conf
; Init Port A
	ldi Conf,0 ; Direction Port A
	out DDRA,Conf
; Init Port B
	ldi Conf,(1<<DDB0)|(1<<DDB1)|(1<<DDB2)|(1<<DDB3) ; Direction Port B
	out DDRB,Conf
; [Add all other init routines here]
	ldi Conf,(1<<SE)|(0<<ISC00)|(1<<ISC01)|(1<<ISC10)|(0<<ISC11) ; enable sleep
	out MCUCR,Conf
	ldi StepCt,0
	ldi StepMask,7
	ldi Direction,1
	ldi SeqBase, StepSeq
	add SeqBase,SeqBase
 	sei
; ============================================
;         P R O G R A M    L O O P
; ============================================
Loop:
	rjmp loop ; go back to loop

StepSeq: .DB 1,3,2,6,4,12,8,9,0,0
; End of source code

Finally can say I have an ATMel chip - the ATtiny2313 functioning as a stepper driver.
I got it working in Arduino, the assembler version still has some strange behavious (and the assembler version of the code is hareder to troubleshoot in hardware. In the Simulator it works just fine, but in hardware.....

Here's the Arduino version.
By my count it will run in excess of 140RPM running in Half Step mode when driven by a simple Arduino program.

/*
Step & Direction Stepper Driver
 Pins 8, 9, 10, 11 are tied to transistors 
 for each of the motor phases.
 Pins 2 is used as interruptfor the steps
 and 3 is the Direction.
 */
// the following 3 arrays contain the bit patterns to drive the transistors
// to in turn drive each of the phases of the stepper
int patSimple[] = {
  B0011,B0010, B0100, B1000, B0001, B0010, B0100, B1000};
int patWave[]   = {
  B0011, B0110, B1100, B1001, B0011, B0110, B1100, B1001};
int patHalf[]   = {
  B0001, B0011, B0010, B0110, B0100, B1100, B1000, B1001};
int pinDir = 5;
volatile int ctr;
volatile int dir;

void setup()
{
  DDRB = B1111 ;  // this enables Port B Bits 0 - 3, Arduino I/O 8, 9, 10, 11 as outputs
  pinMode(pinDir, INPUT);
  ctr=0;
  dir = 0;
  attachInterrupt(0, Step, FALLING);  // Depending on the application FALLING might be a better choice.

}

void loop()
{
  // Nothing to see here...  
}

void Step()
{
  if (digitalRead(5)) 
  {
    ctr++ ;
  }
  else 
  {
    ctr-- ;
  }
  ctr = ctr & 7;
  // 2 of the following 3 lines must be commented.
  // PORTB = patsimple[ctr];  // Simple Stepping
  // PORTB = patWave[ctr];    // Wave Stepping
  PORTB = patHalf[ctr];      // Half Stepping
}

And I was testing it with code that looks like this in my Arduino-

int steps;

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT);   
  digitalWrite(3,HIGH);  
}

void loop() {
  for (steps=0;steps<400;steps++)
  {
    digitalWrite(2, HIGH);   // set the LED on
    digitalWrite(2, LOW);    // set the LED off
    delay(1);              // wait for a second
  }
}

Still want to crack the assembly code...

Hi, I am experimenting with the code you posted ( Reply #15 on: January 15, 2012, 05:19:57 PM ) with 4 IRF530's, an Arduino Uno, a small unipolar stepper and solder-less board and It works really well with EMC2 linux. My goal is to drive a homebrew CNC router table with the above components. I have very little (NO) experience with port manipulation and am somewhat apprehensive about adding another axis to the code, as I recall reading that I could bugger up the TX RX ports? does the UNO have enough ports available to control 3 axes? I would still be happy with 2! In any case, great work on this elegant code so far!

I am using the ATtiny2313 for this application. It has a few extra pins, It turns out I need 1 interrupt pin, 1 input and 4 outputs. I would also like to add 1 more input as an enable and possibly a Ready output. The problem with trying to run more than one stepper in this application is the Interrupt inputs. Because of priority of interrupts the second interrupt would get missed if it occurred at the time as the first.

Look into some ATtiny2313 chips and use the Arduino as the programmer. That circuit is abut as inexpensive and simple as an Arduino circuit can be. If yuwant more info to use that approach I can point you to the few pieces you need to put together to do that.