Go Down

Topic: S-Curve for EasyDriver v3 Stepper Motor Driver (Read 18978 times) previous topic - next topic

Chris E.

I have an Arduino project where I'd like to control a stepper motor.  Unfortunately, the Arduino library for stepper motors is very limited.  I'd like to define parameters for the acceleration, deceleration, and total displacement and have the Arduino take care of the rest.  Poking around on this forum, I surprised that no one seems to have posted anything relating to this - so I figured it was incumbent on me to get something started.  I've attached my first iteration.  Seems to be working well in my tests.  Comments and suggestions will be greatly appreciated.

In my current setup, I'm using the EasyDriver stepper driver from sparkfun Electronics - though any driver that used pulse and direction should work fine.

Quote


/*
=============================================================
=       Project: S curve
=      Language: Arduiino r12
=          Date: January 2008
=        Author: C. Eckert
=============================================================
*/

// Givens
long ta = 3e6;     // acceleration time (microsec)
long td = 3e6;     // decelleration time (microsec)
long Vm = 3200;    // steady state velocity (pulse/sec)
long Pt = 12800;    // total number of pulses for move (1600 steps per rev)

// Other variables
long dly;           // stepper pulse delay (microsec)
long t = td/9;      // current time (microsec)  -  You need to seed the initial time with something > 0
                   //                             so you don't calculate to long of a delay
long t12;           // time during constant velocity (microsec)

int count = 0;      // count the number of pulses
int Perr = 0;       // error in position

// Arduino pins
#define dirPin 3
#define stepPin 12

void setup() {
 Serial.begin(9600);
 pinMode(dirPin, OUTPUT);
 pinMode(stepPin, OUTPUT);
 
 // Calculate the time at constant velocity
 t12 = (Pt/(Vm/1e6))-0.5*(ta+td);
 Serial.println(); Serial.println();

 Serial.println("Setup Done");
}
void loop()
{
 digitalWrite(dirPin, LOW);  // Set the stepper direction

 // Decide which part of the velocity curve your at
 if (t<ta) {                                       // Acceleration
   //Serial.println ("Acceleration Curve");
   dly = (ta)/(2*(Vm/1e6)*t);
 }
 else if (t>=ta && t<(ta+t12)){                    // Constant velocity
   //Serial.println ("Constant Velocity");
   dly = 1/(2*(Vm/1e6));
 }
 else if (t>=(ta+t12) && t<(ta+t12+td)){          // Deceleration
   //Serial.println ("Deceleration Curve");
   dly = 1/(2*((Vm/1e6)-(Vm/(1e6*td))*(t-ta-t12)));
 }
 
 t = t+2*dly; // update the current time
 //Serial.print("dly: "); Serial.print (dly); Serial.println(" microsec");
 //Serial.print ("Current time: "); Serial.print(t); Serial.println(" microsec");
 
 // Move stepper one pulse using delay just calculated
 digitalWrite(stepPin, HIGH);
 delayMicroseconds(dly);
 digitalWrite(stepPin, LOW);
 delayMicroseconds(dly);
 count ++;
   
 // The move is finished
 if (t>(ta+t12+td)){
   Serial.println ("Move Complete");
   Serial.print ("Total steps indexed: "); Serial.println (count);
   
   // Correct for any position error due to rounding
   Perr = Pt-count;
   if (Perr < 0) {
     digitalWrite(dirPin, 1^digitalRead(dirPin));  // reverse the stepper direction
     delay(50);
     Perr = -1*Perr;
   }
   for (;Perr>0;){
     digitalWrite(stepPin, HIGH);
     delayMicroseconds(dly);
     digitalWrite(stepPin, LOW);
     delayMicroseconds(dly);
     Perr--;
   }
   
   count=0;
   t=td/9;
   
   delay (1000);
 }
 
}




Mike Mc

#1
Jan 14, 2009, 10:17 am Last Edit: Jan 14, 2009, 10:20 am by zooto68 Reason: 1
Thanks for this. I also have the Easydriver v3. Though I have so far only played around with the sample code in the playground.

What is the reason for you needing finer control over the acceleration and deceleration? Making a telescope mount?

Grumpy_Mike

Hi Mike,
The point about acceleration is that you can get the motor to run at a faster top speed if you accelerate up to it than you can if you try and drive it from a standing start. The latter is sometimes called the stall speed. It is due to the mechanical inertia you have.

However, if you get it accelerating too fast then you start skipping steps and so you loose accuracy. I used to use a liner ramp to get up to speed but you really should use a bit of control theory to work out the acceleration profile.
Same goes for slowing down, if you just do a dead stop it can over run if going too fast.

Chris thanks for posting this it should be useful.

Mike Mc

Thanks. That will explain why my telescope mount starts slowly, speeds up, runs at its full slew speed, then decelerates to a stop gradually.

michaelh

Did this project go anywhere?  I'm thinking about replacing my old telescope controller and motors and I'd have more fun replacing it with an arduino setup.

Mike Mc

I've thought about making a whole mount from scratch using an Arduino, but it will no doubt be one of those projects I keep saying 'I must do that one day'.

absolutum

I use the ED too to drive a 2axis panorama head and use a very simple approach: start slow and accelerate until the max and slow down again - done over the range of steps I want to go. It gives a smooth movement and I don't need consider extra time to stabilize the mount before I release the cams shutter.

André S.

absolutum could you show me your code?  :-/  i'm trying to do something like that!

Regards

gen2thomas

Thanks for the code at top of this site!

I will improve the stepper library a little bit to include acceleration and deceleration and also allow a higher max. velocity. At the moment only 300rmp possible at a stepper with 200 steps because using delay() . The name of the new library will be "StepperHQ".

Thomas

jpegfr

Hi,

I just start a telescope controlling project.
I have reading with interest this link :
http://www.open.com.au/mikem/arduino/AccelStepper/

If some of yours have a similar project I interresting !

Thnks

Yankee

I've been playing with the s-curve sketch and it works great in testing using an Easydriver. I'm trying to understand how it all works but I'm puzzled by this:

Code: [Select]
// Calculate the time at constant velocity
t12 = (Pt/(Vm/1e6))-0.5*(ta+td);
Serial.println(); Serial.println();


Why would it not be t12 = (Pt/(Vm/1e6))-(ta+td) ?

Go Up