Tarek Lule / MotorLib

Fork of MotorLib by CreaLab

motor.h

Committer:
sepp_nepp
Date:
2018-10-31
Revision:
14:f0667bfc2e98
Parent:
13:4563244c4071
Child:
15:88fecbdd191c

File content as of revision 14:f0667bfc2e98:

// -------------------- Motor ---------------------------
#ifndef MOTOR_H
#define MOTOR_H

#include "mbed.h"

#define MOTOR_STEP_TIME_MIN_US 700      // was MOTOR_STEP_TIME_MIN
#define MOTOR_STEP_TIME_DEFAULT_US 5000 // was MOTOR_STEP_TIME_DEFAULT
#define MOTOR_STEPS_FOR_A_TURN 4096

typedef enum {  
/** Possible Motor States that the motor state machine can be in;
    Motor_CALIB is deprecated, was removed from the states
    Motor_OFF   replaces Motor_STOP, a state where all current is off
    Motor_ON    replaces Motor_PAUSE, a state where phases are engaged but motor is not running
    Motor_ZERO  is the motor at phase position 0, only reached at init and call of Zero command 
    Motor_RUN   is deprecated, the motor running is simply represented 
                by being in ON state, and the motor-command == MOTOR_run */
    Motor_OFF = 0,
    Motor_ON,
    Motor_ZERO,
    Motor_RUN
    } motorStates;
    
typedef enum { // Define Motor State Machine Commands
/** Possible Motor Commands that the state machine handles:
    MOTOR_nop   is no active command to execute
    MOTOR_run   run for requested direction, speed, duration
    MOTOR_stop  stops immediately all, turns off motor
    MOTOR_pause is the motor is paused from the state run
    MOTOR_restart was replaced by MOTOR_run  
    OFF and STOP commands do not go through the ticker command handler. */
    MOTOR_nop = 0,
    MOTOR_run,
    MOTOR_stop,
    MOTOR_pause
    } motorCommands;

typedef enum motorDir { 
/** Define Motor direction to be Clockwise or Anticlockwise */
    CLOCKWISE = 0,
    COUNTERCLOCKWISE
    } motorDir;
    

typedef struct {
    /** Structure of Motor Status registers 
    Used inside Motor Class. Can be passed back by Motor.getStatus() */
    /** state = the general state that the moter state machine is in: 
    * can be either of:     Motor_OFF = 0, Motor_ON, Motor_ZERO, or Motor_RUN  */
    motorStates  state;
    /** cmd = the current command being executed */
    motorCommands cmd; 
    /** dir = the direction that the motor is asked to run*/
    motorDir      dir;
    /** NSteps = the number of steps left for the motor to run 
    NSteps=0 indicates all steps finsihed; NSteps<0 indicates to run "forever" */
    int32_t       NSteps;
    /** TickIsAttached = True while the Ticker is attached */
    bool         TickIsAttached;
    void set(motorCommands Acmd, motorDir Adir, int32_t  ANSteps);
    } MotStatus;
    
/** Class of a Four Phase Stepper Motor 
*Handles single steps but also running a number of steps, or given amount angle. 
*
*Higher level function rely on ticker and a state-machine evaluating now incoming commands versus the motor state at every tick. 
*
*Lower level functions directly talk to the hard ware without ticker. 
*  Call it for example like this:
* @code
*    PinName MotPhases[] = {PB_1, PB_15, PB_14, PB_13};
*    Motor MotorName(MotPhases);
* @endcode
*/
class Motor {
    
  public:
    /** Class Creator: receives the names of the 4 Digital Pins in an array of PinNames.
    *  the time in between two steps defaults here to MOTOR_STEP_TIME_DEFAULT_US=5000usec.
    *  Uses Ticker callback to handle step times. 
    */ 
    Motor(PinName _MPh[4] );
    /** Class Creator: receives the names of the 4 Digital Pins. 
    *  Uses Ticker callback to handle step times. 
    *  the time between two steps defaults here to MOTOR_STEP_TIME_DEFAULT_US=5000usec. */
    Motor(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3);
    /** Class Creator: receives the names of the 4 Digital Pins. 
    *  Uses Ticker callback to handle step times. 
    *  aStepTime_us is the time in usec between two steps, thats used initially. */
    Motor(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t aStepTime_us);
  private:
    // void initialization(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t aStepTime_us);
    void initialization(PinName _MPh[4], uint32_t aStepTime_us);
  public:
    /** Attaching a basic Callback function, not member of a class.
     *  It is only called when a Run Command reaches it's target.
     *  It is not called when the Motor is stopped by calling Stop Function, or any other events.
     * Attention: the attached Callback is called within a Ticker Callback. 
     *    Your code you execute in the Callback should be short, must not use waits, or any long routines. 
     *    Do not call any motor run commands in the callback, as it creates conflicting situations. 
     *    Long Callback code may impair this and any other Ticker functions that are running in your application.
     */
    void setMotorCallback(void (*mIT)());
    /** Attaching a Callback function, member of a class.
     *  It is only called when a Run Command reaches it's target.
     *  It is not called when the Motor is stopped by calling Stop Function. 
     * Attention: the attached Callback is called within a Ticker Callback. 
     *    Your code you execute in the Callback should be short, must not use waits, or any long routines. 
     *    Do not call any motor run commands in the callback, as it creates conflicting situations. 
     *    Long Callback code may impair this and any other Ticker functions that are running in your application.
     */
    template<typename T>
        void setMotorCallback(T *object, void (T::*member)(void))
            {  _callback = callback(object,member);  }
        
    /** Removing the Callback function that may have been attached previously. */
    void removeMotorCallback();
    
    /** RunSteps Main Motor Running Function. 
    * Runs motor for a number Nsteps>0 of steps; Nsteps<=0 will not be executed.
    * Given Direction can be: CLOCKWISE, or COUNTERCLOCKWISE. 
    * Call Pause() or Stop() to pause or end the motor running prematurely.
    * While running: Uses ticker; State = first Motor_ON then Motor_RUN; cmd=MOTOR_run.
    * At the end: calls the Callback, stops ticker; State = Motor_OFF. */
    void RunSteps    (motorDir direction, uint32_t Nsteps);
    
    /** RunDegrees = Main Motor Running Function. 
    * Runs motor for a given angle>0 in degrees; Angles<=0 will not be executed.
    * Given Dicection can be: CLOCKWISE, or COUNTERCLOCKWISE. 
    * Call Pause() or Stop() to pause or end the motor running prematurely.
    * While running: Uses ticker; State = first Motor_ON then Motor_RUN; cmd=MOTOR_run.
    * At the end: calls the Callback, stops ticker; State = Motor_OFF; cmd=MOTOR_stop then MOTOR_nop. */
    void RunDegrees  (motorDir direction, float angle);

    /** RunInfinite = Main Motor Running Function: 
    * Runs motor "unlimited", more precisely it runs 4Billion Steps. 
    * Dicection can be: CLOCKWISE, or COUNTERCLOCKWISE. 
    * While running: Uses ticker; State = first Motor_ON then Motor_RUN; cmd=MOTOR_run.
    * Call Pause() or Stop() to pause or end the motor running.*/
    void RunInfinite (motorDir direction);
    
    /** Pause puts Motor into Pause state, stepping is suspended.
     * Only effective if Status.cmd=MOTOR_run.
     * Retains the number of steps that remain to be run. 
     * While pausing: still uses ticker; State = Motor_RUN; cmd=MOTOR_pause.
     * Use Restart(); to continue. */
    void Pause();
    
    /** Restart continues with the paused stepping activity. 
     * Only effective if Status.cmd=MOTOR_pause, otherwise no action. 
     * Status afterwards is same as afterRun commands. */
    void Restart();
    
    /** Stop completely ends any running/stepping activity.
    * Does not call the Callback function. 
    * Emits first cmd=MOTOR_stop then cmd=MOTOR_nop.
    * Aftewards: ticker is detached; State = Motor_OFF; */
    void Stop();
    /** getSTatus allows direct access to all motor status registers.
    See documentation of MotStatus Structure.
    */
    MotStatus getStatus();
  public: // All the ticker timing related parameters    
    /** Get number of Steps per Full turn. 
     *  Defaults to MOTOR_STEPS_FOR_A_TURN = 4096. 
     *  Needed to translate from degrees to number of steps. 
     *  Old Name was: getCalibration, but not good explicit name. */
    uint32_t getStepsFullTurn();    
    
    /** Set number of Steps per Full turn. 
     *  Defaults to MOTOR_STEPS_FOR_A_TURN = 4096. 
     *  Needed to translate from degrees to number of steps. 
     *  Old Name was: setCalibration, but not good explicit name. */
    void setStepsFullTurn(uint32_t StepsFullTurn);
    
    /** Set the time in microseconds between two motor steps. 
     *  Was previously called setStepTime(), but was not clear which units.   */
    void setStepTime_us(uint32_t aStepTime_us); 
    
    /** Set the time in seconds to get one full turn, rotation of 360°. 
     * e.g. setRotationPeriodSec( 20.0 ); then motor will do 360° in 20 seconds.
     * was previously called setSpeed().  */
    void setRotationPeriodSec(float Seconds_Per_Turn) ;
    
  private: 
    // all the  Ticker and Timing procedures, used to run the motor for a duration
    void StartTick();
    void ProcessMotorStateMachine();
    // The call back function pointer that is called when the Processor
    // State Machine reaches its end. 
    Callback<void()> _callback;
    void StopTick();
    MotStatus Status;       
    //now part of Status: motorCommands command;
    //now part of Status: motorDir direction;
    //now part of Status: int32_t    NumSteps;    
    //now part of Status: bool        TickIsAttached;
    //now part of Status: motorStates state;
    timestamp_t StepTime_us;  // Time in µs for one motor step
    Ticker      MotorSysTick;    // System Timer for Motor
    
  public: // all the low level direct motor HW access, States are immediately reached
    /** Turn off all motor Phases, no more current flowing. 
     *   Equivalent to what previously the function "void Stop();" did .  */
    void MotorOFF();
    /** Turn on the motor Phase, In the last used phase, memorized in StepPhases 
     *  Equivalent to what previously the function "void Start();" did.  */
    void MotorON();
    /** Motor phases turned on and put to Zero Position. */    
    void MotorZero();
    void TestMotor();
  private:
    /** Motor advances one step rotating in direction of variable direction. */
    void StepOnce();
    /** Motor advances one step rotating left. */
    void StepLeft();
    /** Motor advances one step rotating right. */
    void StepRight();
    /** Engage Motor Phases according to MotorIndex. */
    void SetPhases(); // Engage Motor Phases according to StepPhase

    DigitalOut *MPh[4];       // Digital outputs, one per phase
    int        StepPhase;     //  Motor Phase Variable, counts up and down with every step
    uint32_t   Steps_FullTurn;// Number of step for a complete turn
   
  private: /* Deprecated, unused members of the class
    void SetDirection(motorDir direction); // direction is set anyway by all the other commands
    Timer tuneTimings;
    uint32_t last;
    */ 
};

#endif