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

Revision:
0:f2a3b0be279d
Child:
1:a456aa3935ca
--- /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
+}