update
Diff: Stepper.cpp
- Revision:
- 0:f2a3b0be279d
- Child:
- 1:a456aa3935ca
diff -r 000000000000 -r f2a3b0be279d Stepper.cpp --- /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 +}