My Version of the Crealab MotorLib.
Fork of MotorLib by
Revision 24:932ea7bdc850, committed 2019-04-18
- Comitter:
- sepp_nepp
- Date:
- Thu Apr 18 12:12:48 2019 +0000
- Parent:
- 23:6060422cd6eb
- Commit message:
- Compiles
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CreaMot.cpp Thu Apr 18 12:12:48 2019 +0000
@@ -0,0 +1,249 @@
+#include "CreaMot.h"
+
+ // -------------------- CreaMot Class ---------------------------
+
+CreaMot::CreaMot(PinName _MPh[4]) {
+ initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US);
+}
+
+CreaMot::CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3) {
+ PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3};
+ initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US);
+}
+
+CreaMot::CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t AStepTime_us) {
+ PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3};
+ initialization( _MPh, AStepTime_us);
+}
+
+void CreaMot::initialization(PinName _MPh[4], uint32_t AStepTime_us) {
+
+ for (int ph=0; ph<4; ph++) { MPh[ph] = new DigitalOut(_MPh[ph]); }
+
+ MotorOFF(); // Default state is all phases are OFF
+ StepPhase = 0; // initial phase is Zero
+
+ setCommand(MOTOR_nop, CLOCKWISE, 0);// Default command is NOP, clockwise direction, 0 steps
+
+ 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
+
+ // All geometric information defaults to 0:
+ diam_cm = 0; // wheel diameter in centimeter
+ perim_cm = 0; // wheel perimeter in centimeter
+ degree_per_cm = 0; // rotation angle in degrees per cm circumference
+ defaultDirection = CLOCKWISE;
+}
+
+// *****************************************************************
+// all following functions are based on centimeter information
+// *****************************************************************
+
+/* High Level: Run CreaMot for a given number of Dist_cm, Dist_cm<0 are run in opposite direction. */
+void CreaMot::RunDist_cm(bool AClockWise, float Dist_cm)
+{ RunDegrees(AClockWise,Dist_cm * degree_per_cm); }
+
+/* High Level: Run CreaMot for a given number of Dist_cm in default direction. */
+void CreaMot::RunDist_cm(float Dist_cm)
+{ RunDegrees(defaultDirection, Dist_cm * degree_per_cm); }
+
+/** Additional geometric information: set the wheel diameter, also sets perimeter and degrees per cm.*/
+void CreaMot::setDiamCM( float Adiam_cm)
+{ diam_cm = Adiam_cm;
+ perim_cm = PI*diam_cm;
+ degree_per_cm=360.0f/perim_cm;
+}
+
+/** Calculate the needed wheel angle from a turn angle and a turn_radius_cm */
+void CreaMot::RunTurnAngle(float turn_angle_deg, float turn_radius_cm)
+{ // a turn radius smaller than 0 make no sense is not executed
+ if( turn_radius_cm>= 0 )
+ RunDegrees( turn_angle_deg * PI_OVER_180 * turn_radius_cm * degree_per_cm);
+}
+
+void CreaMot::setSpeed_cm_sec(float speed_cm_sec)
+{ if (speed_cm_sec < MIN_SPEED_CM_SEC) // catch too small or negative speeds
+ setRotationPeriodSec( perim_cm / MIN_SPEED_CM_SEC);
+ else setRotationPeriodSec( perim_cm / speed_cm_sec );
+}
+
+// *****************************************************************
+// all following functions are agnostic of centimeter-information
+// *****************************************************************
+
+void CreaMot::RunInfinite(bool AClockWise)
+{ setCommand(MOTOR_run, AClockWise, -1);
+ StartTick();
+}
+
+/* High Level: Run CreaMot for a given angle, angles<0 are run in opposite direction. */
+void CreaMot::RunDegrees(bool AClockWise, float angle_deg) {
+ RunSteps( AClockWise, (int32_t)(angle_deg * (float)Steps_FullTurn / 360.0f) );
+}
+
+/* High Level: Run CreaMot for a given angle in default direction, angles<0 are run in opposite direction. */
+void CreaMot::RunDegrees(float angle_deg) {
+ RunSteps( defaultDirection, (int32_t)(angle_deg * (float)Steps_FullTurn / 360.0f) );
+}
+
+/* High Level: Run CreaMot for a given number of steps, steps<0 are run in opposite direction. */
+void CreaMot::RunSteps(bool AClockWise, int32_t steps)
+{ if (steps<0) { AClockWise = !AClockWise; steps=-steps; }
+ if (steps>0)
+ { setCommand( MOTOR_run, AClockWise, steps );
+ StartTick(); }
+}
+
+void CreaMot::PauseRun()
+{ if (CurrCmd==MOTOR_run) CurrCmd = MOTOR_pause; }
+
+void CreaMot::RestartRun()
+{ if (CurrCmd==MOTOR_pause) CurrCmd = MOTOR_run; }
+
+// not only halt the state machine but also set NSteps to 0
+void CreaMot::StopRun()
+{ setCommand(MOTOR_stop,ClockWise,0); }
+
+void CreaMot::setCommand(motCmands aCmd, bool aClockWise, int32_t aNSteps) {
+ CurrCmd = aCmd;
+ ClockWise = aClockWise;
+ NStepsToDo = aNSteps;
+};
+
+
+/*******************************************************
+ ** Ticker / Timing procedures
+ *******************************************************/
+//Get, set the scaling
+uint32_t CreaMot::getStepsFullTurn()
+{ return Steps_FullTurn; }
+
+void CreaMot::setStepsFullTurn(uint32_t StepsFullTurn)
+{ Steps_FullTurn = StepsFullTurn; }
+
+void CreaMot::setRotationPeriodSec(float Seconds_Per_Turn) {
+ // rescale to usec and pass on to the next handler.
+ setStepTime_us( uint32_t(Seconds_Per_Turn / Steps_FullTurn * 1000000) ) ;
+}
+void CreaMot::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(TickIsAttached) { StopTick(); StartTick(); }
+ }
+
+void CreaMot::StartTick() {
+ if(!TickIsAttached) {
+ // Connect Interrupt routine in which the CreaMot and all the state machine is performed
+ MotorSysTick.attach_us(callback(this, &CreaMot::ProcessMotorStateMachine), StepTime_us);
+ // last=tuneTimings.read_us();
+ TickIsAttached=true;
+ }
+}
+
+void CreaMot::ProcessMotorStateMachine()
+{
+ switch(CurrCmd) {
+ case MOTOR_run: {
+ switch(CurrState) {
+ case Motor_OFF:
+ MotorON(); // First only turn on the CreaMot ..
+ break;
+ case Motor_ZERO:
+ case Motor_ON:
+ CurrState = Motor_RUN;
+ case Motor_RUN:
+ if (NStepsToDo==0) // No more steps to go
+ { CurrCmd = MOTOR_stop;
+ if (_callback) _callback.call(); }
+ else // More steps to go
+ { StepOnce();
+ NStepsToDo--;}
+ break;
+ } // switch(CurrState)
+ } // case MOTOR_run
+ case MOTOR_stop:
+ StopTick();
+ CurrCmd = MOTOR_nop;
+ MotorOFF();
+ break;
+ case MOTOR_nop:
+ case MOTOR_pause:
+ default: break;
+ } // switch(CurrCmd)
+}
+
+void CreaMot::StopTick() {
+ if(TickIsAttached)
+ { MotorSysTick.detach(); TickIsAttached=false; }
+}
+
+/*******************************************************
+ ** all the low level direct CreaMot HW access
+ *******************************************************/
+
+
+ void CreaMot::MotorTest() // 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);
+ StepClkW();
+ }
+ wait(0.5);
+ for (i=0; i<Steps_FullTurn; i++) {
+ wait(0.005);
+ StepCCW();
+ }
+ MotorOFF();
+}
+
+ /** Turn off all CreaMot Phases, no more current flowing */
+void CreaMot::MotorOFF()
+{ for (int ph=0; ph<4; ph++) *MPh[ph] = 0;
+ CurrState=Motor_OFF;
+}
+
+/** Turn on the CreaMot Phase, In the last used phase, memorized in StepPhases
+* Equivalent to what previously the function "void Start();" did */
+void CreaMot::MotorON()
+{ SetPhases(); // attention, does not change StepPhase!
+ if (StepPhase==0) CurrState=Motor_ZERO;
+ else CurrState=Motor_ON;
+}
+
+/** CreaMot phases turned on and put to Zero Position*/
+void CreaMot::MotorZero() {
+ StepPhase = 0; // sets the phases to 0
+ SetPhases();
+ CurrState=Motor_ZERO;
+}
+
+void CreaMot::StepOnce() // Move the CreaMot in the requested 'direction'
+{ if (ClockWise) StepClkW(); else StepCCW();
+}
+
+void CreaMot::StepClkW() // Move the CreaMot one step Clockwise
+{ if (StepPhase<7) StepPhase++; else StepPhase = 0;
+ SetPhases();
+}
+void CreaMot::StepCCW() // Move the CreaMot one step Clockwise
+{ 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 CreaMot::SetPhases() // Engage CreaMot Phases according to StepPhase
+{ for (int ph=0; ph<4; ph++) { *MPh[ph] = MotPh[ph][StepPhase]; } }
+
--- /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
--- a/motor.cpp Wed Apr 17 21:48:14 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-#include "motor.h"
-
-
- // -------------------- CreaMot Class ---------------------------
-
-CreaMot::CreaMot(PinName _MPh[4]) {
- initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US);
-}
-
-CreaMot::CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3) {
- PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3};
- initialization( _MPh , MOTOR_STEP_TIME_DEFAULT_US);
-}
-
-CreaMot::CreaMot(PinName _MPh0, PinName _MPh1, PinName _MPh2, PinName _MPh3, uint32_t AStepTime_us) {
- PinName _MPh[4] = {_MPh0, _MPh1, _MPh2, _MPh3};
- initialization( _MPh, AStepTime_us);
-}
-
-void CreaMot::initialization(PinName _MPh[4], uint32_t AStepTime_us) {
-
- for (int ph=0; ph<4; ph++) { MPh[ph] = new DigitalOut(_MPh[ph]); }
-
- MotorOFF(); // Default state is all phases are OFF
- StepPhase = 0; // initial phase is Zero
-
- setStatus(MOTOR_nop, CLOCKWISE, 0);// Default command is NOP, clockwise direction, 0 steps
-
- 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
-
- // All geometric information defaults to 0:
- rotate_angle_deg = 0; // calculated wheel rotation angle
- diam_cm = 0; // wheel diameter in centimeter
- perim_cm = 0; // wheel perimeter in centimeter
- degree_per_cm = 0; // rotation angle in degrees per cm circumference
- defaultDirection = CLOCKWISE;
-}
-
-// *****************************************************************
-// all following functions are based on centimeter information
-// *****************************************************************
-
-/* High Level: Run CreaMot for a given number of Dist_cm, Dist_cm<0 are run in opposite direction. */
-void CreaMot::RunDist_cm (bool AClockWise, float Dist_cm);
-{ RunDegrees(AClockWise, Dist_cm * degree_per_cm; ) }
-
-/* High Level: Run CreaMot for a given number of Dist_cm in default direction. */
-void CreaMot::RunDist_cm (float Dist_cm);
-{ RunDegrees(defaultDirection, Dist_cm * degree_per_cm; ) }
-
-/** Additional geometric information: set the wheel diameter, also sets perimeter and degrees per cm.*/
-void CreaMot:setDiamCM( float Adiam_cm) /**< Helper; set diameter and perim to values */
-{ diam_cm = Adiam_cm;
- perim_cm = PI*diam_cm;
- degree_per_cm=360.0f/perim_cm;
-}
-
-/** Helper: calculate the needed wheel angle from a turn angle and a turn_radius_cm */
-float CreaMot:RunTurnAngle(float turn_angle_deg, float turn_radius_cm)
-{ // a turn radius smaller than 0 make no sense
- if( turn_radius_cm>= 0 )
- rotate_angle_deg = turn_angle_deg * PI_OVER_180 * turn_radius_cm * degree_per_cm;
- else rotate_angle_deg = 0;
- return rotate_angle_deg;
-}
-
-void CreaMot::setSpeed_cm_sec(float speed_cm_sec)
-{ if (speed_cm_sec < MIN_SPEED_CM_SEC) // catch too small or negative speeds
- setRotationPeriodSec( perim_cm / MIN_SPEED_CM_SEC);
- else setRotationPeriodSec( perim_cm / speed_cm_sec );
-}
-
-// *****************************************************************
-// all following functions are agnostic of centimeter-information
-// *****************************************************************
-
-void CreaMot::RunInfinite(bool AClockWise) {
- setStatus(MOTOR_run, AClockWise, -1);
- StartTick();
-}
-
-/* High Level: Run CreaMot for a given angle, angles<0 are run in opposite direction. */
-void CreaMot::RunDegrees(bool AClockWise, float angle_deg) {
- RunSteps( AClockWise, (int32_t)(angle_deg * (float)Steps_FullTurn / 360.0f) );
-}
-
-/* High Level: Run CreaMot for a given angle in default direction, angles<0 are run in opposite direction. */
-void CreaMot::RunDegrees(float angle_deg) {
- RunSteps( defaultDirection, (int32_t)(angle_deg * (float)Steps_FullTurn / 360.0f) );
-}
-
-/* High Level: Run CreaMot for a given number of steps, steps<0 are run in opposite direction. */
-void CreaMot::RunSteps(bool AClockWise, int32_t steps) {
- if (steps!=0)
- { setStatus(MOTOR_run, AClockWise ^^ (steps<0), abs(steps));
- StartTick(); }
-}
-
-void CreaMot::PauseRun()
-{ if (CurrCmd==MOTOR_run) CurrCmd = MOTOR_pause; }
-
-void CreaMot::RestartRun()
-{ if (CurrCmd==MOTOR_pause) CurrCmd = MOTOR_run; }
-
-void CreaMot::StopRun()
-{ CurrCmd = MOTOR_stop; }
-
-MotStatus CreaMot::getStatus() { return Status; }
-
-/*******************************************************
- ** Ticker / Timing procedures
- *******************************************************/
-//Get, set the scaling
-uint32_t CreaMot::getStepsFullTurn()
-{ return Steps_FullTurn; }
-
-void CreaMot::setStepsFullTurn(uint32_t StepsFullTurn)
-{ Steps_FullTurn = StepsFullTurn; }
-
-void CreaMot::setRotationPeriodSec(float Seconds_Per_Turn) {
- // rescale to usec and pass on to the next handler.
- setStepTime_us( uint32_t(Seconds_Per_Turn / Steps_FullTurn * 1000000) ) ;
-}
-void CreaMot::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(TickIsAttached) { StopTick(); StartTick(); }
- }
-
-void CreaMot::StartTick() {
- if(!TickIsAttached) {
- // Connect Interrupt routine in which the CreaMot and all the state machine is performed
- MotorSysTick.attach_us(callback(this, &CreaMot::ProcessMotorStateMachine), StepTime_us);
- // last=tuneTimings.read_us();
- TickIsAttached=true;
- }
-}
-
-void CreaMot::ProcessMotorStateMachine()
-{
- switch(CurrCmd) {
- case MOTOR_run: {
- switch(CurrState) {
- case Motor_OFF:
- MotorON(); // First only turn on the CreaMot ..
- break;
- case Motor_ZERO:
- case Motor_ON:
- CurrState = Motor_RUN;
- case Motor_RUN:
- if (NStepsToDo==0) // No more steps to go
- { CurrCmd = MOTOR_stop;
- if (_callback) _callback.call(); }
- else // More steps to go
- { StepOnce();
- NStepsToDo--;}
- break;
- } // switch(CurrState)
- } // case MOTOR_run
- case MOTOR_stop:
- StopTick();
- CurrCmd = MOTOR_nop;
- MotorOFF();
- break;
- case MOTOR_nop:
- case MOTOR_pause:
- default: break;
- } // switch(CurrCmd)
-}
-
-void CreaMot::StopTick() {
- if(TickIsAttached)
- { MotorSysTick.detach(); TickIsAttached=false; }
-}
-
-/*******************************************************
- ** all the low level direct CreaMot HW access
- *******************************************************/
-
-void CreaMot::setStatus(motCmands aCmd, bool AClockWise, int32_t aNSteps) {
- cmd = aCmd;
- AClockWise = AClockWise;
- NSteps = aNSteps;
-};
-
-
- void CreaMot::MotorTest() // 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);
- StepClkW();
- }
- wait(0.5);
- for (i=0; i<Steps_FullTurn; i++) {
- wait(0.005);
- StepCCW();
- }
- MotorOFF();
-}
-
- /** Turn off all CreaMot Phases, no more current flowing */
-void CreaMot::MotorOFF()
-{ for (int ph=0; ph<4; ph++) *MPh[ph] = 0;
- CurrState=Motor_OFF;
-}
-
-/** Turn on the CreaMot Phase, In the last used phase, memorized in StepPhases
-* Equivalent to what previously the function "void Start();" did */
-void CreaMot::MotorON()
-{ SetPhases(); // attention, does not change StepPhase!
- if (StepPhase==0) CurrState=Motor_ZERO;
- else CurrState=Motor_ON;
-}
-
-/** CreaMot phases turned on and put to Zero Position*/
-void CreaMot::MotorZero() {
- StepPhase = 0; // sets the phases to 0
- SetPhases();
- CurrState=Motor_ZERO;
-}
-
-void CreaMot::StepOnce() // Move the CreaMot in the Status 'direction'
-{ if (Status.AClockWise) StepClkW(); else StepCCW();
-}
-
-void CreaMot::StepClkW() // Move the CreaMot one step Clockwise
-{ if (StepPhase<7) StepPhase++; else StepPhase = 0;
- SetPhases();
-}
-void CreaMot::StepCCW() // Move the CreaMot one step Clockwise
-{ 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 CreaMot::SetPhases() // Engage CreaMot Phases according to StepPhase
-{ for (int ph=0; ph<4; ph++) { *MPh[ph] = MotPh[ph][StepPhase]; } }
-
--- a/motor.h Wed Apr 17 21:48:14 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,447 +0,0 @@
-/**
- * @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 MOTOR_H
-#define MOTOR_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 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] <turn_angle_deg> Given turn angle in degrees that should be run
- * @param[in] <turn_radius_cm> Given Trun radius that should be run */
- float 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);
-
-
- /** Calculated wheel Angle from calcAngle() Helper function */
- float rotate_angle_deg;
-
- /** 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;
-
- /** 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;
-
-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 int32_t The structure of CreaMot status registers. */
- int32_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(int32_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) ;
-
-private:
- // 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
- int32_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
- motStates CurrState; /**< General state that the CreaMot state machine is in.*/
- motCmands CurrCmd; /**< Command asked to be executed currently by the state machine.*/
- void setStatus(motCmands aCmd, bool AClockWise, int32_t aNSteps);
- /**< Helper; set Command, Direction and NSteps in one call. */
-
-
- /** 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
