For driving stepper motor driver with traditional (step/dir) control pins Based on "Generate stepper-motor speed profiles in real time" from "David AUSTIN - December 30, 2004"

Dependents:   VAM_reliability VAM_REV2 VAM_DAX VAM_DAX_RELIABILITY ... more

Fork of Stepper by Mederic Melard

Files at this revision

API Documentation at this revision

Comitter:
mederic
Date:
Mon Apr 15 11:29:15 2013 +0000
Child:
1:a456aa3935ca
Commit message:
Published as library

Changed in this revision

Stepper.cpp Show annotated file Show diff for this revision Revisions of this file
Stepper.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Stepper.cpp	Mon Apr 15 11:29:15 2013 +0000
@@ -0,0 +1,169 @@
+#include "Stepper.h"
+
+//***********************************/************************************
+//                         Constructors                                 //
+//***********************************/************************************
+Stepper::Stepper(PinName clk, PinName dir): _clk(clk) , _dir(dir)
+{
+    _state = STOP;
+    _pos = 0;
+    _steps = 0;
+    _spd = 400;
+}
+
+//***********************************/************************************
+//                                Get Set                               //
+//***********************************/************************************
+void Stepper::setSpeed(float speed)
+{
+    _spd = (speed<0) ? -speed : speed;  //speed must be unsigned
+    if(_spd)_dtmin = 1000000/_spd;      //fin min delay (max spd)
+}
+
+float Stepper::getSpeed(void)
+{
+    return _spd;
+}
+
+void Stepper::setAcceleration(float acc)
+{
+    _acc = (acc<0) ? -acc : acc;            //acceleration must be unsigned
+    if(_acc)_dt0 = 676000 * sqrt(2.0/_acc); //Equation 15 [µs] instead Equation 7
+}
+
+float Stepper::getAcceleration(void)
+{
+    return _acc;
+}
+
+void Stepper::setDeceleration(float dec)
+{
+    _dec = (dec<0) ? -dec : dec;        //deceleration must be unsigned
+}
+
+float Stepper::getDeceleration(void)
+{
+    return _dec;
+}
+
+void Stepper::setPositionZero(void)
+{
+    _pos = 0;
+}
+
+int Stepper::getPosition(void)
+{
+    return _pos;
+}
+
+bool Stepper::stopped(void)
+{
+    return (_state == STOP) ? true : false;
+}
+
+//***********************************/************************************
+//                             Public Methods                           //
+//***********************************/************************************
+void Stepper::stop(void)
+{
+    _timer.detach();    //detach step generator thread
+    _state = STOP;      //update state machine 
+    _steps = 0;         //reset total steps per move
+}
+
+void Stepper::rotate(bool direction)
+{
+    if(!_spd)return;    //spd must > 0
+    _dir = direction;   //set output pin direction value
+    _steps = 0;         //rotate until stop() by user
+    run();              //start thread
+}
+
+void Stepper::move(int steps)
+{
+    if(!steps || !_spd) return;
+    if(steps<0) //fin direction
+    {
+        _dir = CCW;         //set output pin direction value
+        _steps = -steps;    //total steps per move must be unsigned
+    }
+    else
+    {
+        _dir = CW;          //set output pin direction value
+        _steps = steps;     //total steps per move
+    }
+    run();
+}
+
+void Stepper::goesTo(int position)
+{
+    move(position-_pos);    //absolute to relative transformation   
+}
+
+//***********************************/************************************
+//                          Protected Methods                           //
+//***********************************/************************************
+void Stepper::run(void)
+{
+    static float dtn;                           //delay for next step
+    static unsigned int nStartDec;              //steps to start decelerate
+    static unsigned int n;                      //steps counter
+  
+    switch(_state)
+    {
+        case STOP:
+            n = 0;                      //reset setp counter (motor stopped)
+  
+            if(_dt0 <= _dtmin || !_acc) //if first step faster than max speed step
+            {
+                dtn = _dtmin;       //delay = delaymin
+                _state = CRUISE;    //no acceleration needed
+            }
+            else
+            {
+                dtn = _dt0;         //set first delay
+                _state = ACCEL;     //acceleration phase
+            }
+
+            if(_steps)  //if finite mov required
+            {
+                unsigned int nToSpeed = nTo(_spd,_acc);      //Equation 16 How many steps to reach max speed 
+                nStartDec = (_steps * _dec) / (_dec + _acc);   //Equation 19 after how many step we must start decelerate  
+                if(nStartDec > nToSpeed)nStartDec = _steps - ((nToSpeed*_acc)/_dec);  //if speed can be reach Equation 17                
+            }    
+        break;
+        
+        case ACCEL:
+            dtn -=  (dtn*2) / ((n<<2)+1);   //Equation 20 find next delay
+            if((unsigned int)dtn <= _dtmin) //if max speed reached
+            {
+                 dtn = _dtmin;
+                _state = CRUISE;    //constant phase
+            }
+            if(_steps && _dec && n >= nStartDec)_state = DECEL; //chech when must start decelerate
+            
+        break;
+        
+        case CRUISE:
+            if(_steps && _dec && n >= nStartDec)_state = DECEL; //chech when must start decelerate
+        break;
+        
+        case DECEL:
+            dtn +=  (dtn*2) / (((_steps-n)<<2)+1);  //Equation 20 find next delay
+        break;    
+    }
+
+    n++;                    //increment step counter
+    _pos += (_dir<<1)-1;    //set new position +1 if cw; -1 if ccw
+    _clk = !_clk;           //toggle step out pin
+    _timer.attach_us(this,&Stepper::run,(unsigned int)dtn); //set next delay
+    if(_steps && n >= _steps)stop();    //check for motor stop
+}
+
+unsigned int Stepper::nTo(float speed,float acc)
+{
+    if(speed<0)speed = -speed;
+    if(acc<0)acc = -acc;
+    
+    return (!acc || !speed) ? 0 : (speed * speed) / (2 * acc); //Equation 16 step number n as a function of speed & acceleration
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Stepper.h	Mon Apr 15 11:29:15 2013 +0000
@@ -0,0 +1,132 @@
+#ifndef STEPPER_H
+#define STEPPER_H
+
+#include "mbed.h"
+/** Stepper class.
+ *  Used for drive Stepper motor
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "Stepper.h"
+ *
+ * DigitalIn home(p20);
+ * Stepper mot(p21,p22);
+ *
+ * int main()
+ * {
+ *    mot.setSpeed(1200);
+ *    mot.setAcceleration(4000);
+ *    mot.setDeceleration(4000);
+ *
+ *    mot.rotate(CW);
+ *    while(!home);
+ *    mot.stop();
+ *    mot.setPositionZero();
+ *
+ *    mot.goesTo(1600);
+ *    while(!mot.stopped());
+ *
+ *    while(1)
+ *    {
+ *
+ *    }
+ * }
+ * @endcode
+ */
+class Stepper
+{
+public:
+    /** Create Stepper instance connected to pin clk & dir
+    * @param clk pin to connect at clk/step output
+    * @param dir pin to connect at dir output
+    */
+    Stepper(PinName clk, PinName dir);
+    
+    /** Moving the motor relative to a reference position (set by setPositionZero())
+    * @param position steps from position zero 
+    */
+    void goesTo(int position); 
+    
+    /** Moving the motor for given steps
+    * @param steps number of steps to go(>0 CW ; <0 CCW)
+    */
+    void move(int steps);
+    
+    /** Moving the motor until user stop
+    * @param direction rotation Stepper::CC or Stepper::CCW
+    */
+    void rotate(bool direction);
+    
+    /** Stop the motor as fast as possible
+    */
+    void stop(void);
+    
+    /**Set Rotation Speed
+    * @param speed [steps/sec]
+    */
+    void setSpeed(float speed);
+    
+    /**Set Acceleration ramp
+    * @param acc acceleration [steps/sec²] (0 = infinite acceleration 1st step @ max speed)
+    */
+    void setAcceleration(float acc);
+    
+    /**Set Deceleration ramp
+    * @param dec deceleration [steps/sec²] (0 = infinite deceleration last step @ max speed)
+    */
+    void setDeceleration(float dec);
+    
+    /**Give Origin for motor absolute movement
+    */
+    void setPositionZero(void);
+    
+    /**Check if motor is stopped
+    * @returns true if motor stopped
+    */  
+    bool stopped(void);
+    
+    /**Get absolute position from origin
+    * @returns position [steps] from origin set by setPositionZero()
+    */
+    int getPosition(void);
+    
+    /**Get Acceleration
+    * @returns acceleration [steps/sec²]
+    */
+    float getAcceleration(void);
+    
+    /**Get Deceleration
+    * @returns deceleration [steps/sec²]
+    */
+    float getDeceleration(void);
+    
+    /**Get Speed
+    * @returns speed [steps/sec]
+    */
+    float getSpeed(void);
+    
+    /**Enum for direction
+    *   CW=true or 1; CCW=false or 0
+    */
+    typedef enum {CW=1,CCW=0} direction;
+    
+protected:
+    void run(void);         //step generator thread
+    unsigned int nTo(float speed,float acc);
+      
+private:
+    float _acc;                         //Acceleration [step/s²]
+    float _dec;                         //Decceleration [step/s²]
+    float _spd;                         //Speed [step/s]
+    unsigned int _steps;                //nbr total of steps per mov
+    DigitalOut _clk;                    //output clock pin 
+    DigitalOut _dir;                    //output dir pin
+    Timeout _timer;                     //step timer
+    enum {STOP,ACCEL,CRUISE,DECEL}_state;  //Motor state
+    unsigned int _dt0;                  //initial delay [µs]
+    unsigned int _dtmin;                //delay minimum [µs]
+    int _pos;                           //motor position
+};
+
+#endif
\ No newline at end of file