My Version of the Crealab MotorLib.
Fork of MotorLib by
motor.cpp
- Committer:
- sepp_nepp
- Date:
- 2018-11-01
- Revision:
- 15:88fecbdd191c
- Parent:
- 13:4563244c4071
- Child:
- 16:d818c1a4dafb
File content as of revision 15:88fecbdd191c:
#include "motor.h" void MotStatus::set(motorCommands aCmd, motorDir aDir, int32_t aNSteps) { cmd = Acmd; dir = Adir; NSteps = NSteps; }; Motor::Motor(PinName _MPh[4]) { initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US); } Motor::Motor(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3) { PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3}; initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US); } Motor::Motor(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t aStepTime_us) { PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3}; initialization( _MPh, aStepTime_us); } //void Motor::initialization(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t aStepTime_us) { void Motor::initialization(PinName _MPh[4], uint32_t aStepTime_us) { for (int ph=0; ph<4; ph++) { MPh[ph] = new DigitalOut(_MPh[ph]); } /*MPh[0] = new DigitalOut(_MPh0); MPh[1] = new DigitalOut(_MPh1); MPh[2] = new DigitalOut(_MPh2); MPh[3] = new DigitalOut(_MPh3);*/ MotorOFF(); // Default state is all phases are OFF StepPhase = 0; // initial phase is Zero Status.set(MOTOR_nop, CLOCKWISE, 0);// Default command is NOP, clockwise direction, 0 steps Status.TickIsAttached = false; StepTime_us = aStepTime_us;// duration in micro second for one step Steps_FullTurn = MOTOR_STEPS_FOR_A_TURN; // Default Calibration value _callback = NULL; // No default Callback // itOnStop = true; // tuneTimings.reset(); // tuneTimings.start(); } //Attaching and removing Callbacks void Motor::removeMotorCallback() { _callback = NULL; } void Motor::setMotorCallback(void (*function)(void)) { _callback = function; } uint32_t Motor::getStepsFullTurn() { return Steps_FullTurn; } void Motor::setStepsFullTurn(uint32_t StepsFullTurn) { Steps_FullTurn = StepsFullTurn; } void Motor::RunInfinite(motorDir direction) { Status.set(MOTOR_run, direction, -1); StartTick(); } void Motor::RunSteps(motorDir direction, uint32_t steps) { if (steps>0) { Status.set(MOTOR_run, direction, steps); StartTick(); } } void Motor::Pause() { if (Status.cmd==MOTOR_run) Status.cmd = MOTOR_pause; } void Motor::Restart() { if (Status.cmd==MOTOR_pause) Status.cmd = MOTOR_run; } void Motor::Stop() { Status.cmd = MOTOR_stop; } MotStatus Motor::getStatus() { return Status; } void Motor::TestMotor() // Just to check that it make a full turn back and forth { int i; MotorON(); for (i=0; i<Steps_FullTurn; i++) { wait(0.005); StepRight(); } wait(0.5); for (i=0; i<Steps_FullTurn; i++) { wait(0.005); StepLeft(); } MotorOFF(); } /******************************************************* ** Ticker / Timing procedures *******************************************************/ void Motor::setRotationPeriodSec(float Seconds_Per_Turn) { // rescale to usec and pass on to the next handler. setStepTime_us(1000 * Seconds_Per_Turn / Steps_FullTurn) ; } void Motor::setStepTime_us(uint32_t aStepTime_us) { if(StepTime_us == aStepTime_us) return; // avoid futile activity if (StepTime_us < MOTOR_STEP_TIME_MIN_US) // filter too small values StepTime_us = MOTOR_STEP_TIME_MIN_US; else StepTime_us = aStepTime_us; // or if OK then assign value // if ticker already running recreate a new ticker; if(Status.TickIsAttached) { StopTick(); StartTick(); } } void Motor::StartTick() { if(!Status.TickIsAttached) { // Connect Interrupt routine in which the motor and all the state machine is performed MotorSysTick.attach_us(callback(this, &Motor::ProcessMotorStateMachine), StepTime_us); // last=tuneTimings.read_us(); Status.TickIsAttached=true; } } void Motor::ProcessMotorStateMachine() { switch(Status.cmd) { case MOTOR_run: { switch(Status.state) { case Motor_OFF: MotorON(); // First only turn on the motor .. break; case Motor_ZERO: case Motor_ON: Status.state = Motor_RUN; case Motor_RUN: if (Status.NSteps==0) // No more steps to go { Status.cmd = MOTOR_stop; if (_callback) _callback.call(); } else // More steps to go { StepOnce(); Status.NSteps--;} break; } // switch(Status.state) } // case MOTOR_run case MOTOR_stop: StopTick(); Status.cmd = MOTOR_nop; MotorOFF(); break; case MOTOR_nop: case MOTOR_pause: default: break; } // switch(Status.cmd) } void Motor::StopTick() { if(Status.TickIsAttached) { MotorSysTick.detach(); Status.TickIsAttached=false; } } /******************************************************* ** all the low level direct motor HW access *******************************************************/ /** Turn off all motor Phases, no more current flowing */ void Motor::MotorOFF() { for (int ph=0; ph<4; ph++) *MPh[ph] = 0; Status.state=Motor_OFF; } /** Turn on the motor Phase, In the last used phase, memorized in StepPhases * Equivalent to what previously the function "void Start();" did */ void Motor::MotorON() { SetPhases(); // attention, does not change StepPhase! if (StepPhase==0) Status.state=Motor_ZERO; else Status.state=Motor_ON; } /** Motor phases turned on and put to Zero Position*/ void Motor::MotorZero() { StepPhase = 0; // sets the phases to 0 SetPhases(); Status.state=Motor_ZERO; } void Motor::StepOnce() // Move the Motor in the used 'direction' { if (Status.dir == CLOCKWISE) StepRight(); else StepLeft(); } void Motor::StepRight() // Move the Motor one step Right { if (StepPhase<7) StepPhase++; else StepPhase = 0; SetPhases(); } void Motor::StepLeft() // Move the Motor one step Right { if (StepPhase>0) StepPhase--; else StepPhase = 7; SetPhases(); } static const int MotPh[4][8] = { {1, 1, 0, 0, 0, 0, 0, 1}, {0, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1}}; void Motor::SetPhases() // Engage Motor Phases according to StepPhase { for (int ph=0; ph<4; ph++) { *MPh[ph] = MotPh[ph][StepPhase]; } }