update

Stepper.cpp

Committer:
mederic
Date:
2014-09-22
Revision:
1:a456aa3935ca
Parent:
0:f2a3b0be279d

File content as of revision 1:a456aa3935ca:

#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
}