My Version of the Crealab MotorLib.

Fork of MotorLib by CreaLab

Revision:
24:932ea7bdc850
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CreaMot.h	Thu Apr 18 12:12:48 2019 +0000
@@ -0,0 +1,447 @@
+/**
+ * @file CreaMot.h
+ * \brief File contains Crealab CreaMot Library.
+ 
+ * CreaMot.h contains the class CreaMot, and related enums and structs.
+ * Includes only "mbed.h".
+ *
+ * MotStatus structure is dissolved into the CreaMot Class
+ *
+ * Rotation directions are now consistently called Clockwise, and Counterclockwise (CCW), 
+ * instead of mix them with Left and Right. 
+ * Doxygens Tags are preceeded by either a backslash @\ or by an at symbol @@.
+
+ * @author Tarek Lule, Francois Druilhe, et al.
+ * @date 01. Nov. 2018.
+ * @see https://os.mbed.com/users/sepp_nepp/code/MotorLib/  */
+ 
+ // -------------------- CreaMot ---------------------------
+ 
+#ifndef CREAMOT_H
+#define CREAMOT_H
+
+#include "mbed.h"
+
+#define MOTOR_STEP_TIME_MIN_US 700      /**< Shortest Time between two CreaMot steps = 0.7ms, was MOTOR_STEP_TIME_MIN*/
+#define MOTOR_STEP_TIME_DEFAULT_US 5000 /**< Default Time between two CreaMot steps = 5ms, was MOTOR_STEP_TIME_DEFAULT*/
+#define MOTOR_STEPS_FOR_A_TURN 4096     /**< Default number of CreaMot steps to complete a turn = 4096 steps  */
+#define CLOCKWISE true                  /**< Constant for Clockwise direction */
+#define COUNTERCLOCKWISE false          /**< Constant for Counter-Clockwise direction */
+#define MAX_SPEED_CM_SEC 30.0f    /**< Clamp maximum advancement speed = 30cm/sec, was MAX_SPEED */
+#define MIN_SPEED_CM_SEC 0.001f   /**< Clamp minimum advancement speed = 10um/sec */
+#define PI 3.141592f    /** PI needed to calcuate from angle to distances */
+#define PI_OVER_180 (PI/180.0f)  /** needed to translate from angle to circumference */
+
+/** \enum motStates 
+* \brief Possible States of CreaMot state machine
+* 
+* Motor_CALIB is deprecated, was removed from the enum structure */
+typedef enum {
+    Motor_OFF = 0,  /**< All phase currents is off, replaces Motor_STOP. */  
+    Motor_ZERO,     /**< CreaMot at phase position 0 and ON, only reached by call of Zero() procedure. */  
+    Motor_ON,       /**< Phases are engaged, but CreaMot state machine stopped, replaces Motor_PAUSE. */  
+    Motor_RUN       /**< Phases are engaged, and CreaMot state machine runs*/  
+} motStates;
+
+/** \enum motCmands 
+* \brief Commands that are handled by the CreaMot state machine
+*
+* These Commands are issued asynchonously by calling CreaMot class methods.
+* They are executed in the state machine called by the ticker handler.
+*
+* OFF and STOP commands do not go through the state machine.
+*
+* MOTOR_restart is equivalent to and replaced by MOTOR_run.
+*/
+typedef enum {
+    MOTOR_nop = 0,  /**< No active command to execute. */
+    MOTOR_run,      /**< Run CreaMot until Nsteps are achieved. */
+    MOTOR_stop,     /**< Stop immediately all activity, turn off CreaMot. */
+    MOTOR_pause     /**< CreaMot is temporarily paused from the state run. */
+} motCmands;
+
+/** ATTENTION UNDER CONSTRUCTION, DO NOT YET USE.
+*
+* Class of a Four Phase Stepper CreaMot.
+*
+* Perform Runs for number of steps, or given amount angle, but also Low-Level steps. 
+*
+* High-Level Run functions have 'Run' in their name.
+* They rely on tickers and return immediately after ticker is set up. 
+* A state-machine evaluates the one ongoing command versus the CreaMot state at every tick.
+* When End of Run is detected tickers stop, and CreaMot turns off. 
+*
+* To define the speed of the CreaMot set the variable StepTime_us, either by
+*    a) Using the createor CreaMot(...., uint32_t AStepTime_us);
+*    b) Calling function setStepTime_us(uint32_t AStepTime_us); any time
+*    c) or leave it to the default value MOTOR_STEP_TIME_DEFAULT_US = 5000
+*
+* To be able to run the CreaMot for a given angle, set the number of steps per full turn
+*    with the function "setStepsFullTurn"
+*    That value defaults to MOTOR_STEPS_FOR_A_TURN = 4096
+*
+* To be able to run the CreaMot for a given perimeter distance in centimeters, 
+*    set the wheel diameter with the function setDiamCM( float Adiam_cm); 
+*
+* Callbacks can be attached to react to 'end of run' 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 CreaMot run commands in the callback, as it creates conflict situations.
+*    Long Callback code may impair this and any other Ticker functions that run in your application.
+*
+*Low-Level functions directly talk to the hardware without ticker. 
+*   Use of Low-Level functions while tickers still run may lead to unexpected behavior. 
+*
+* NB: all times are uint32_t, step numbers are int32_t
+*/
+class CreaMot
+{
+public:
+    /** CreaMot Class Creator
+    *
+    * Creates the class, initiallizes all fields, creates Phase Pins.  
+    * Time between two steps defaults here to MOTOR_STEP_TIME_DEFAULT_US = 5000usec.
+    * Pin names are used to create digital outputs: Pin0 = new DigitalOut(_MPh0)
+    *
+    @code
+       PinName MotPhases[] = {PB_1, PB_15, PB_14, PB_13};
+       CreaMot MotorName(MotPhases); // Call this creator for example like this:  
+    @endcode 
+    * 
+    * @param _MPh Array of Names of the 4 Digital Pins of type PinNames 
+    */
+    CreaMot(PinName _MPh[4] );
+    
+    /** CreaMot Class Creator
+    *
+    * Creates the class, initiallizes all fields, creates Phase Pins.  
+    * Time between two steps defaults here to MOTOR_STEP_TIME_DEFAULT_US=5000usec.
+    * Pin names are used to create digital outputs: Pin0 = new DigitalOut(_MPh0)
+    *
+    @code
+      // Call this creator for example like this:
+       CreaMot MotorName(PB_1, PB_15, PB_14, PB_13);
+    @endcode 
+    * 
+    * @param <_MPh0, _MPh1, _MPh2, _MPh3> List of Names of the 4 Digital Pins of type PinNames    
+    */
+    CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3);
+    
+    /** CreaMot Class Creator
+    *
+    * Creates the class, initiallizes all fields, creates Phase Pins.  
+    * Time between two steps is passed as parameter.
+    * Pin names are used to create digital outputs: Pin0 = new DigitalOut(_MPh0)
+    *
+    @code
+      // Call this creator for example like this:
+       CreaMot MotorName(PB_1, PB_15, PB_14, PB_13, 6000);
+    @endcode 
+    *
+    * @param <_MPh0, _MPh1, _MPh2, _MPh3> List of Names of the 4 Digital Pins of type PinNames    
+    * @param <AStepTime_us> the time in usec between two steps, thats used initially.   
+    */
+    CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t AStepTime_us);
+
+private:
+    // deprecated: void initialization(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t AStepTime_us);
+    void initialization(PinName _MPh[4], uint32_t AStepTime_us);
+
+public:
+    /** Attach a basic Callback function.
+    *
+    * A callback is called when the current Command reaches it's requested end.
+    * Not called when the CreaMot is stopped by a call of Stop Function, or any other events.
+    * For use see precautions at Class description above. 
+    * Formerly called setMotorCallback()
+    *
+    @code
+    // Simple callback function, state variable endMove can be polled elsewhere
+    void CallBackFunction()
+    { endMove=true; }
+
+    // main routine
+    void main()
+    {   ...
+        // Attach callback function:
+        MotorInstance->callbackSet(CallBackFunction);
+        ...
+        while (true) {
+            ....
+        if (endMove) // poll the endMove flag
+               { ... } // react to Movement End
+               
+            ....
+        }
+    }
+    @endcode
+    * @param <*CBfunction> Callback function, must not be member of a class.
+
+    */
+    void callbackSet(void (*CBfunction)(void)) {_callback = CBfunction;};
+
+
+    /** Attach a Callback function, member of a class.
+    * Only called when a Run Command reaches it's requested end.
+    * Not called when the CreaMot is stopped by a call of Stop Function, or any other events.
+    * For use see precautions at Class description above. 
+    * @param <*object> Class pointer which possesses callback member.
+    * @param <*CBmember> Pointer to callback function, member of Class.
+    * 
+    @code
+    // Class Creator:
+     AClass::AClass(Class Creation Parameters)
+    {   ...
+        // Attach callback function:
+        MotorInstance->setMotorCallback(this, &AClass::CallBackMemberFunction);
+        ...  
+    }
+
+    // Simple callback function, state variable endMove can be polled by main thread
+    void AClass::CallBackMemberFunction()
+    {  endMove=true;  }
+    @endcode
+    */
+    template<typename T>
+    void callbackSet(T *object, void (T::*CBmember)(void)) {
+        _callback = callback(object,CBmember);
+    }
+
+    /** Remove the Callback function that may have been attached previously. */
+    void callbackRemove() { _callback = NULL; };
+
+public: 
+    // *********************************************************************
+    //  all following functions use wheel diameter to achieve cm distance
+    // *********************************************************************
+
+    /** High Level: Run CreaMot for a given number of centimeters.
+    *
+    * Runs CreaMot for a given wheel circumference in cimeters in given direction. 
+    * You must setup the perimeter and diameter with setDiam(Adiam_cm) in advance, otherwise no reaction.
+    * Call Pause() or Stop() to pause or end the CreaMot run prematurely.
+    * While run: Uses ticker; State: first Motor_ON then Motor_RUN; cmd=MOTOR_run.
+    * At end: calls attached Callback, stops ticker; State: Motor_OFF; cmd=MOTOR_stop then MOTOR_nop.
+    * @param[in] <AClockWise> Given Direction, true for CLOCKWISE, false for COUNTERCLOCKWISE.
+    * @param[in] <Dist_cm> Circumference to rotate for, in cm, Dist_cm<0 are run in opposite direction.
+    */
+    void RunDist_cm  (bool AClockWise, float Dist_cm);
+   
+    /** High Level: Run CreaMot for a given number of centimeters in default direction.
+    * Same as RunDist_cm(AClockWise,Dist_cm) but uses Default diretion.*/
+    void RunDist_cm  (float Dist_cm);
+    
+    /** High Level: Run CreaMot for a turn angle around a turn_radius_cm  in default direction
+    *
+    * Runs CreaMot for a given turn angle in degrees with a given turn radius.
+    *   in default direction. Negative angles are rotated in opposite direction. 
+    *   turn-radius must be positive. Zero or negative radius are not executed. 
+    * You must setup the perimeter and diameter with setDiam(Adiam_cm) in advance, otherwise no reaction.
+    * Call Pause() or Stop() to pause or end the CreaMot run prematurely.
+    * While run: Uses ticker; State: first Motor_ON then Motor_RUN; cmd=MOTOR_run.
+    * At end: calls attached Callback, stops ticker; State: Motor_OFF; cmd=MOTOR_stop then MOTOR_nop.
+    * @param[in] <turn_angle_deg> Given turn angle in degrees that should be run
+    * @param[in] <turn_radius_cm> Given Trun radius that should be run */
+    void RunTurnAngle(float turn_angle_deg, float turn_radius_cm); 
+
+    /** Additional geometric information: set the wheel diameter, also sets perimeter and degrees per cm.*/
+    void setDiamCM( float Adiam_cm); 
+
+    /** Set CreaMot speed in centimeter/sec, based on perimeter in cm */
+    void setSpeed_cm_sec(float speed_cm_sec);
+
+    /** Default rotation direction that serves as local storage, but not as actual direction */
+    bool defaultDirection;
+    
+    /** State value that is used and managed by the class owner.
+    * Used for example by Creabot library to indicate if this is the left or right CreaMot. */
+    char StateValue;
+private:
+
+    /** Additional geometric information: wheel diameter in centimeter */
+    float diam_cm;
+
+    /** Additional geometric information: wheel perimeter in centimeter */
+    float perim_cm;
+
+    /** Additional geometric information: rotation angle in degrees per cm circumference */
+    float degree_per_cm;
+
+public: 
+    // *****************************************************************
+    //  following functions are agnostic of wheel dimensions in centimeters
+    // *****************************************************************
+
+   /** High Level: Run CreaMot for a given angle.
+    *
+    * Runs CreaMot for a given angle in given direction. 
+    * Angles<0 are run in opposite direction.
+    * Call Pause() or Stop() to pause or end the CreaMot run prematurely.
+    * While running: Uses ticker; 
+    * State: first Motor_ON then Motor_RUN; cmd=MOTOR_run.
+    * At end: calls attached Callback, stops ticker; State: Motor_OFF; cmd=MOTOR_stop then MOTOR_nop.
+    * @param[in] <AClockWise> Given Direction, true for CLOCKWISE, false for COUNTERCLOCKWISE.
+    * @param[in] <angle_deg> Angle>0 to rotate for, in degrees, Angles<0 are run in opposite direction.     
+    */
+   void RunDegrees  (bool AClockWise, float angle_deg);
+   
+   /** High Level: Run CreaMot for a given angle in default direction
+   * for details see RunDegrees  (bool AClockWise, float angle_deg);
+   */
+   void RunDegrees  (float angle_deg);
+
+    /** High Level: Run CreaMot for a number of Steps.
+    * 
+    * During Run: Uses ticker; State: first Motor_ON then Motor_RUN; cmd=MOTOR_run.
+    * Call Pause() or Stop() to pause or end the run prematurely.
+    * At the end: calls the Callback, stops ticker; State: Motor_OFF.
+    * @param[in] <AClockWise> Given Direction, true for CLOCKWISE, false for COUNTERCLOCKWISE.
+    * @param[in] <Nsteps> Number of steps to run for; Nsteps<0 are run in opposite direction!    
+    */
+   void RunSteps (bool AClockWise, int32_t Nsteps);
+
+    /** High Level: Run CreaMot "unlimited"
+    *
+    * Runs CreaMot with out limit in given direction, precisely runs 4Billion Steps.
+    * While run: Uses ticker; State: first Motor_ON then Motor_RUN; cmd=MOTOR_run.
+    * Call Pause() or Stop() to pause or end the CreaMot run.
+    * @param[in] <AClockWise> Given Direction, true for CLOCKWISE, false for COUNTERCLOCKWISE.
+    */
+    void RunInfinite (bool AClockWise);
+
+    /** High Level: Pause a CreaMot Run.
+     * Put CreaMot into Pause state, Run is suspended, but only effective if Status.cmd=MOTOR_run.
+     * Retains the number of steps that remain to be run if restarting run.
+     * While paused: still uses ticker; State: Motor_RUN; cmd=MOTOR_pause.
+     * Use RestartRun(); to continue. */
+    void PauseRun();
+
+    /** High Level: Restart a Paused Run.
+     * Restart the Run that was launched before calling PuaseRun. 
+     * Only effective if Status.cmd=MOTOR_pause, otherwise no re/action.
+     * Status afterwards is same as afterRun commands. */
+    void RestartRun();
+
+    /** High Level: End any Run.
+    * Force stop of any ongoing run, but does not call the Callback function.
+    * Only effective if Status.cmd=MOTOR_run, otherwise no re/action.
+    * Emits first cmd=MOTOR_stop then cmd=MOTOR_nop.
+    * Aftewards: ticker is detached; State: Motor_OFF; */
+    void StopRun();
+    
+public: // All the ticker timing related parameters
+
+    /** MidLevel: Get number of Steps per Full turn
+    
+    * Defaults to MOTOR_STEPS_FOR_A_TURN = 4096.
+    * Used by RunDegrees() to translate from angle in degrees to number of steps.
+    * Old Name was: getCalibration, but that was not a good explicit name. 
+    * @return  uint32_t The number of motor steps needed for a full turn. */
+    uint32_t getStepsFullTurn();
+
+    /** MidLevel: Set number of Steps per Full turn.
+    
+    * Defaults is MOTOR_STEPS_FOR_A_TURN = 4096.
+    * Used by RunDegrees() to translate from degrees to number of steps.
+    * Old Name was: setCalibration, but not good explicit name.
+    * @param <StepsFullTurn> Number of steps needed to complete a full CreaMot turn
+    */
+    void setStepsFullTurn(uint32_t StepsFullTurn);
+
+    /** Mid Level: Get the CreaMot step time. 
+    
+    * Step time is time between two CreaMot steps, and is given in microseconds
+    * and is passed to the ticker as delay time. 
+    * So the larger the value the slower the CreaMot speed.  
+    * Defaults to MOTOR_STEP_TIME_DEFAULT_US = 5000.
+    * @return  uint32_t The structure of CreaMot status registers.
+    */
+    uint32_t getStepTime_us();
+    
+    /** Set the time in microseconds between two CreaMot steps.
+    *  Defaults to MOTOR_STEP_TIME_DEFAULT_US = 5000usec.
+    *  Filters values below Minimum Value = 700.
+    *  Passed to the ticker as delay time.
+    *  Can be called while ticker is running, and takes immediate effect. 
+    *  Was previously called setStepTime(), but was not clear which units.  
+    * @param <AStepTime_us> the time in microseconds between two CreaMot steps
+    */
+    void setStepTime_us(uint32_t AStepTime_us);
+
+    /** Set the time in seconds to get one full turn, rotation of 360°.
+    * was previously called setSpeed().  
+    * @param <Seconds_Per_Turn> Period of Rotation, e.g. if =20.0 then CreaMot will do 360° in 20 seconds.
+    */
+    void setRotationPeriodSec(float Seconds_Per_Turn) ;
+
+
+    motStates   CurrState;  /**< General state that the CreaMot state machine is in.*/
+    motCmands   CurrCmd;    /**< Command asked to be executed currently by the state machine.*/
+
+private:
+    void setCommand(motCmands aCmd, bool aClockWise, int32_t  aNSteps); 
+                        /**< Helper; set Command, Direction and NSteps in one call. */
+
+    // all the  Ticker and Timing procedures, used to run the CreaMot 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();
+    timestamp_t StepTime_us;    // Time in µs for one CreaMot step
+    Ticker      MotorSysTick;   // System Timer for CreaMot
+    uint32_t    Steps_FullTurn; // Number of step for a complete turn
+    bool        ClockWise;  /**< Direction that the CreaMot is asked to run. True if Clockwise */
+    int32_t     NStepsToDo; /**< Number of steps remain for the CreaMot to run. 
+                                NSteps=0: all steps finished; NSteps<0: indicates to run "forever" */
+    bool        TickIsAttached; /**< Indicates if Ticker is attached.
+                            Ticker is automatically attached while CreaMot runs, or paused; 
+                            detaches when finished a run, or stopped.  */
+    
+public: // all the low level direct CreaMot HW access, States are immediately reached    
+
+    /** Low Level: Run one full turn clockwise then anticlockwise. 
+    * After: State: Motor_OFF.
+    * Blocking function, returns back only after end of full movement. 
+    */
+    void MotorTest();
+
+    /** Low Level: turn off all CreaMot Phases
+    * No more current flows, reduces holding force.
+    * After: State: Motor_OFF.
+    * StepPhases memorizes the last used phase.
+    * Equivalent what previously the function "void Stop();" did .  */
+    void MotorOFF();
+    
+    /** Low Level: turn on the CreaMot Phases in the last used phase.
+    * The last used phase is held in StepPhases.
+    * After: State: Motor_ON, or Motor_ZERO if StepPhases==0
+    * Equivalent to what previously the function "void Start();" did.  */
+    void MotorON();
+    
+    /** Low Level: Advance CreaMot one step, rotates in direction of variable AClockWise. */
+    void StepOnce();
+    
+    /** Low Level: Advance CreaMot one step, rotates CounterClockwise. */
+    void StepCCW();
+    
+    /** Low Level: Advance CreaMot one step, rotates Clockwise. */
+    void StepClkW();
+    
+    /** Low Level: turn on the CreaMot Phases in Zero Position. 
+     * After: State: Motor_ZERO, StepPhases==0
+     */
+    void MotorZero();
+    
+private:
+
+    /** Low Level: Engage CreaMot Phases according to MotorIndex. */
+    void SetPhases(); 
+
+    DigitalOut *MPh[4];       // Digital outputs, one per phase
+    int        StepPhase;     // CreaMot Phase Variable, counts up and down with every step
+};
+
+#endif