stepper motor driver

Dependents:   PES2_mbed

Files at this revision

API Documentation at this revision

Comitter:
boro
Date:
Fri Mar 12 13:06:02 2021 +0000
Commit message:
d

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
diff -r 000000000000 -r 510f88bf20c6 Stepper.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Stepper.cpp	Fri Mar 12 13:06:02 2021 +0000
@@ -0,0 +1,183 @@
+#include "Stepper.h"
+
+//***********************************/************************************
+//                         Constructors                                 //
+//***********************************/************************************
+Stepper::Stepper(PinName clk, PinName dir): _clk(clk) , _dir(dir)
+{
+    _clk = 1;
+    _state = STOP;
+    _pos = 0;
+    _steps = 0;
+    _spd = 400;
+    _dt0 = 0;
+}
+
+//***********************************/************************************
+//                                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)
+{   
+    _clk = 1;
+    remove();           //stop timer
+    _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
+    handler();          //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
+    }
+    handler();              //start thread
+}
+
+void Stepper::goesTo(int position)
+{
+    move(position-_pos);    //absolute to relative transformation   
+}
+
+//***********************************/************************************
+//                          Protected Methods                           //
+//***********************************/************************************
+void Stepper::handler(void)
+{
+    static float i;
+    
+    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                
+            }
+            i = _dtn;
+        break;
+        
+        case ACCEL:
+            //_dtn -=  (_dtn*2.0) / ((_n<<2)+1);   //Equation 20 find next delay
+            i-= i*2.0 / ((_n<<2)+1);
+            _dtn = i;
+            
+            if((unsigned int)_dtn <= _dtmin) //if max speed reached
+            {
+                 _dtn = _dtmin;
+                 i = _dtn;
+                _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
+            i+= (i*2.0) / (((_steps-_n)<<2)+1);
+            _dtn = i;
+        break;    
+    }
+    
+    _clk=0;
+    
+    if(!_n) insert(_dtn + us_ticker_read());   //start timer @ first delay
+    else insert(event.timestamp+(unsigned int)_dtn);
+    
+    _n++;                                   //increment step counter
+    _pos += (_dir<<1)-1;                    //set new position +1 if cw; -1 if ccw
+    _clk = 1;                              //toggle step out pin
+
+    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
+}
+
+
diff -r 000000000000 -r 510f88bf20c6 Stepper.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Stepper.h	Fri Mar 12 13:06:02 2021 +0000
@@ -0,0 +1,135 @@
+#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 TimerEvent
+{
+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:
+    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
+    enum {STOP,ACCEL,CRUISE,DECEL}_state;  //Motor state
+    unsigned int _dt0;                      //initial delay [µs]
+    unsigned int _dtmin;                    //delay minimum [µs]
+    unsigned int _dtn;                             //current delay
+    int _pos;                               //motor position
+    unsigned int _n;                        //steps counters
+    unsigned int _nStartDec;                //steps to decelerate
+    virtual void handler();
+
+};
+
+#endif
\ No newline at end of file