HowTo: control 3 steppers with a arduino

Your source for all things Atmel.

Moderator: phalanx

Post Reply
nelsontb
Posts: 2
Joined: Thu Apr 22, 2010 1:17 pm

HowTo: control 3 steppers with a arduino

Post by nelsontb » Thu Apr 22, 2010 1:32 pm

This is a reply for louisef on the site but maybe it can be useful to someone else

this is for 3 steppers but easily adapted/ignored...
just ignore the PwrON and PwrOff as those are for controlling a pc PSU (to feed the motors only when needed)... you will also need to fix the DirPinX, StepPinX and so forth to comply with your setup, note that i am connecting the MS1 and MS2 from the stepper controllers to the analog pins hence the pin numbers 14-19 .
To move the steppers just send m200.200.200. via console and it will move to that position (absolute position so if you send another m200.200.200. it will not move has it is already at that position)
the code tries to change the controllers for full step and sets the StepDelay to 1900 for 1/8 step (default) use 320
this is not a finished program (it doesn't check for PwrOK from the PSU for example) but it is already at a "working state" so you may find some bugs in it (heck i haven't even started building the CNC machine structure yet)

Code: Select all

#define DirPinX 3
#define StepPinX 2
#define XMS1 14
#define XMS2 15

#define DirPinY 5
#define StepPinY 4
#define YMS1 16
#define YMS2 17

#define DirPinZ 7
#define StepPinZ 6
#define ZMS1 18
#define ZMS2 19

#define PwrPin 13
#define PwrOK 12

#define StepDelay 1900  //320 for 1/8 step
#define DirDelay 100
#define AutoOffDelay 10000

#define DirRight false
#define DirLeft true

long CurX, CurY, CurZ, rcState, rcX, rcY, rcZ;

unsigned long autoOFF;

void setup()   {
  Serial.begin(115200);
  
  CurX=CurY=CurZ=0;
  
  autoOFF=0;
  
  pinMode(DirPinX, OUTPUT);     
  pinMode(StepPinX, OUTPUT);
  pinMode(XMS1, OUTPUT);
  pinMode(XMS2, OUTPUT);
  
  pinMode(DirPinY, OUTPUT);     
  pinMode(StepPinY, OUTPUT);
  pinMode(YMS1, OUTPUT);
  pinMode(YMS2, OUTPUT);
  
  pinMode(DirPinZ, OUTPUT);     
  pinMode(StepPinZ, OUTPUT);
  pinMode(ZMS1, OUTPUT);
  pinMode(ZMS2, OUTPUT);
  
  //steppers in full step
  digitalWrite(XMS1,LOW);
  digitalWrite(XMS2,LOW);  
  digitalWrite(YMS1,LOW);
  digitalWrite(YMS2,LOW);
  digitalWrite(ZMS1,LOW);
  digitalWrite(ZMS2,LOW);
  //****
  
  pinMode(PwrPin,OUTPUT);
  digitalWrite(PwrPin,HIGH);
  
  rcState = rcX = rcY = rcZ = 0;
  
  Serial.println("START");
}

void doStep(int StepPin, int DirPin, bool Dir, long steps) {
  long tmp;
  if (digitalRead(DirPin)!=Dir) {
    digitalWrite(DirPin, Dir);
    delay(DirDelay);
  }
  for (tmp=0;tmp<steps;tmp++) {
    digitalWrite(StepPin, LOW);
    digitalWrite(StepPin, HIGH);
    if (steps>1 )delayMicroseconds(StepDelay); 
  }
}

void calcStep(long X, long Y, long Z, long &tmpX, long &tmpY, long &tmpZ) {
  doStep(StepPinX,DirPinX,(X>0)?DirRight:DirLeft,abs(X-(tmpX-CurX)));
  doStep(StepPinY,DirPinY,(Y>0)?DirRight:DirLeft,abs(Y-(tmpY-CurY)));
  doStep(StepPinZ,DirPinZ,(Z>0)?DirRight:DirLeft,abs(Z-(tmpZ-CurZ)));
  
  tmpX=CurX+X; tmpY=CurY+Y; tmpZ=CurZ+Z; 
}

void gotoXYZ(long X, long Y, long Z) {
  long steps;
  long tmpX, tmpY, tmpZ;
  
  PwrON();
  
  Serial.print("MOVE\tX: "); Serial.print(X);
  Serial.print("\tY: "); Serial.print(Y);
  Serial.print("\tZ: "); Serial.print(Z);
  
  float sX,sY,sZ,stepX,stepY,stepZ;
  
  tmpX=CurX; tmpY=CurY; tmpZ=CurZ;
  
  steps=abs(X-CurX);
  if (steps<abs(Y-CurY)) steps=abs(Y-CurY);
  if (steps<abs(Z-CurZ)) steps=abs(Z-CurZ);

  sX=(X-CurX)/(float)steps;
  sY=(Y-CurY)/(float)steps;
  sZ=(Z-CurZ)/(float)steps;
  //Serial.print("sX: ");  Serial.print(sX);  Serial.print(" sY: ");  Serial.print(sY);  Serial.print(" sZ: ");  Serial.println(sZ);
  //delay(5000);
  
  stepX=stepY=stepZ=0;
  
  for (long tmpLoop=0;tmpLoop<steps;tmpLoop++) {
    stepX+=sX;
    stepY+=sY;
    stepZ+=sZ;
    calcStep(stepX,stepY,stepZ,tmpX,tmpY,tmpZ);
    //Serial.print("tmpX: ");  Serial.print(tmpX);  Serial.print(" tmpY: ");  Serial.print(tmpY);  Serial.print(" tmpZ: ");  Serial.println(tmpZ);
    delayMicroseconds(StepDelay-180); 
  }
  calcStep(X-CurX,Y-CurY,Z-CurZ,tmpX,tmpY,tmpZ);
  CurX=tmpX; CurY=tmpY;CurZ=tmpZ;
  //Serial.print("X: ");  Serial.print(CurX);  Serial.print(" Y: ");  Serial.print(CurY);  Serial.print(" Z: ");  Serial.println(CurZ);
  Serial.println("\tOK");
  
}

void PwrON() { 
  if (digitalRead(PwrPin)==HIGH) {
     digitalWrite(PwrPin,LOW);
     Serial.print("POWER ON");
     delay(2000);
     Serial.println("\tOK");
  }
}

void PwrOff() {
  digitalWrite(PwrPin,HIGH);
  Serial.println("POWER OFF\tOK");
  autoOFF=0;
}

void loop()                     
{
  //waits for a request
  //format: mX.Y.Z.
  //ex: m1600.0.0.
  char tmp;
  if (Serial.available()) {
    tmp=Serial.read();
    if (tmp=='m') {
      rcX = rcY = rcZ = 0;
      rcState=1;
    }
    if (tmp=='p') {
      if (digitalRead(PwrPin)==HIGH) {
        PwrON();
      } else {
        PwrOff();
      }
    }
    switch(rcState) {
      case 1:  //X
        if (tmp>=48 && tmp <= 57) {
          rcX=rcX*10+(tmp-48);
        } else if (tmp=='.') rcState=2;
        break;
      case 2:  //Y
        if (tmp>=48 && tmp <= 57) {
          rcY=rcY*10+(tmp-48);
        } else if (tmp=='.') rcState=3;
        break;
      case 3:  //Z
        if (tmp>=48 && tmp <= 57) {
          rcZ=rcZ*10+(tmp-48);
        } else if (tmp=='.') {
          gotoXYZ(rcX,rcY,rcZ);
          rcState = rcX = rcY = rcZ = 0;
          autoOFF=millis()+AutoOffDelay;
        }
        break;
      default:
        rcState = rcX = rcY = rcZ = 0;
        break;
    }
  }
  if (autoOFF < tmillis() && autoOFF!=0) { PwrOff(); autoOFF=0; }
}

nelsontb
Posts: 2
Joined: Thu Apr 22, 2010 1:17 pm

Re: HowTo: control 3 steppers with a arduino

Post by nelsontb » Thu Apr 22, 2010 2:22 pm

ooopps my bad posted on the wrong place if a moderator can move it please do so

Post Reply