Author Options:

Stuck programming AVR or ARDUINO based 3 axis bipolar stepper controller. Answered

Hello, I am writing a program to control 3 axis bipolar stepper motors using the atmega8 and other hardware (L293).
I am facing a mental block for the part of the program where I must switch the 4 outputs for any bipolar stepper motor.
I guess the program would explain the problem better. I can do this, but some innovative idea would be good.
I am also adding the circuit for the controller for reference. 

/* 3-Axis Bipolor stepper motor controller. Takes 5 inputs
*  based on:
*  1) PD1 - Enable X axis
*  2) PD2 - Enable Y axis
*  3) PD3 - Enable Z axis
*  4) PC4 - Step
*  5) PC5 - Direction (Clockwise if 1)
*  Gives 12 outputs for motor control, defined as:
*  1) PC0 - MX-D
*  2) PC1 - MX-C
*  3) PC2 - MX-B
*  4) PC3 - MX-A
*  5) PD4 - MY-D
*  6) PD5 - MY-C
*  7) PD6 - MY-B
*  8) PD7 - MY-A
*  9) PB0 - MZ-C
*  10) PB1 - MZ-B
*  11) PB2 - MZ-A
*  12) PB3 - MZ-D
*  The uC reads the dir and step for each axis. Whenever step is
*  given a high pulse, step sequence is incremented (or decremented)
*  by one, depending on the direction pin's state.
*        Author: Pranav Sharma
*        Date: April 3rd, 2012
#define STEP_SEQ half_step_seq
#define STEP_PIN PINC&0b00010000
#define DIR_PIN PINC&0b00100000
#define X PIND&0b00000010
#define Y PIND&0b00000100
#define Z PIND&0b00001000
int dir=0;
int currentx=0;
int currenty=0;
int currentz=0;
int currentstep=0;
boolean enx=false;
boolean eny=false;
boolean enz=false;
void setup(){
  DDRB=0B00001111;    //B0-B3 Outputs
  DDRC=0B00001111;    //C0-C3 Outputs
  DDRD=0B11110000;    //D4-D7 Outputs
  PORTB=0;                                                                               //IS THIS NEEDED??


byte half_step_seq[]={

void loop(){
    else if(Y){
    else if(Z){
    byte stepbyte=STEP_SEQ[currentstep];
      //step currentx time the x motor
    else if (eny){
      //step currenty time the y motor
    else if(enz){
      //step currentz time the z motor


It would make a LOT more sense to map the drive channels to nibbles, so PC0,1,2,3 = X 4,5,6,7=Y etc.

Does Arduino have NIbble addressable ports ? If it does, its easy, if it doesn't you need to use logical masking.

Create an array with the step sequence in it, use modulo arithmetic to step/index forwards and backwards through that with your X step etc counter. Use the contents of the array masked onto your signal lines.

Okay.... so much so is sorted out...
I reasoned out that 0b1010 is the same as 0b00001010
This logic works well for X and Z axis with outputs on the lower nibbles of ports C and B respectively. On the other hand I have Y axis on the higher nibble of PORTD...

How do I sort this out now...
Make another step sequence just for Y axis??

I'd've mapped X to the lower part of B, Y to the upper part of B and Z to the lower part of C, leaving the upper part for other stuff.
PortD = Y data << 4 & X data
PortC= Zdata & 0x0F

but if you '...map X to the lower part of B, Y to the upper part of B' then it would become a little more complicated. On the other hand the PCB is already laid out 4 times :P
I didnt want to do that again

Hmmmm.... That makes sense. But I got the program working well enough. I'm waiting for some parts to arrive to check it out properly.

This is going to come as an 'ible.. :)

Thanks for the help steveastrouk..

I don't think it supports nibbles - I've never heard of it and arduino is the only uC environment I've programmed in...

The step sequence is there, its just a matter of applying a binary value to a port based on an index number.

Digitalwrite is okay, but slow when you need to address 4x3 pins one at a time, and the delay propagation might cause problems with the motors.

WHY did you scramble the mapping of the Z port ?????
It was all so easy before :-(


ummmmm... did I? Its the same... Z axis D,C,B,A = Port B 0,1,2,3

In your comments it says

9) PB0 - MZ-C *
10) PB1 - MZ-B *
11) PB2 - MZ-A *
12) PB3 - MZ-D

Oh! Im so sorry, that must have been a mistake.. Its DCBA.

I got the program running good. But one thing that is beyond me is that....

Mach 3 software gives 1 - 5 uSec pulses for Step and DIR.. Is this too short a pulse for my program to run well? I have breadboarded everything here and I seem to not get any pulse at all...

Its AWFUL fast for an arduino to pick up - I suspect its configurable in the Mach setup though

Yes. It is configurable. But only up to 15 uSec.

So this means that I HAVE to use a Stepper translator IC? Like Allegro A3982 or such?
I cant think of any other way for running bipolar steppers using mach3. Steve Baba you surely have some experience on this, dont you? :) I was just going through your workspace. And needless to say, I'm floating in dreams.. :P

Hi Pranav,

He he.
Yes, I know a fair bit about it.
Yes, a proper chip is the way to go here I'm afraid.
You've picked a good one, if it can handle the drive current you need for your steppers.


Yup! 2 Amps is plenty for me. The chip comes cheap. Requires very few components. What else do we need xD

Humph.. I would have loved to get the arduino to do this though. Never mind, maybe I'll think of a complete CNC on an arduino now.

Thanks for all your help! You're as wonderful as always. :) But something I didnt understand, is that observatory that I see on your website, yours?

Stick with the drivers doing what they need to do. The arduino can't compete in this application.

I built the dome and designed and built the doors for it.
This link may be of interest

Thats awesome! Unbelievable. I would love to meet you in person one day when I'm in UK next.

Not too often. Once an year or so.
My dad's family happens to live near Northampton near london. He visits them often.