Module: stepperMotor
Executive Summary
The stepper motor module simulates the actuation of a stepper motor. Given the initial motor angle \(\theta_0\), a fixed motor step angle \(\Delta\theta\), a fixed motor step time \(\Delta t\), and an input message containing an integer number of steps commanded, the motor states are computed at each time step and output from the module. The motor states include the scalar motor angle \(\theta\), scalar angle rate \(\dot{\theta}\), scalar angular acceleration \(\ddot{\theta}\), the current motor step count \(c_s\), and the number of steps commanded to the motor \(n_s\). The motor actuation through each step of the command sequence is profiled using a bang-bang acceleration profile. This module also includes logic for handling incoming reference commands that interrupt an unfinished motor actuation sequence. Because the stepper motor is unable to stop actuating during a step, it must finish actuating through the current step before it can begin following a new reference command.
Message Connection Description
The following table lists the module input and output messages.
Msg Variable Name |
Msg Type |
Description |
---|---|---|
motorStepCommandInMsg |
Input message containing the number of commanded motor steps |
|
stepperMotorOutMsg |
Output message containing the stepper motor states |
Motor Step Actuation Profile
The motor states are profiled identically for each step in the command sequence. Specifically, a bang-bang acceleration profile is used to profile the motor states as a function of time. Given the motor step time \(\Delta t\) and motor step angle \(\Delta \theta\) as fixed parameters, the module calculates the required acceleration \(\ddot{\theta}_{\text{max}}\) that must be applied during each motor step.
Note that the motor can take either positive or negative steps. For a forward actuation command (\(n_s > 0\)), the calculated acceleration is applied positively for the first half of the step and negatively during the second half of the step. For a backward actuation command (\(n_s < 0\)), the acceleration is applied negatively during the first half of the step and positively during the second half of the step.
Given the initial time \(t_0\), the switch time \(t_s\) where the acceleration is alternated and the final time \(t_f\) when the step is complete is determined as
The other motor states can be kinematically profiled as a function of time by integrating the applied acceleration profile. The equations used to profile each motor step are
Note that the parameters \(t_0, t_s\) and \(t_f\) must be continually updated after each step is complete to reflect the advancement of time. Doing so enables use of the above equations for each motor step.
Important
If the motor actuation is interrupted by a new reference message while actuating through a step, the motor must finish actuating through the current step before it can begin following a new reference command. If the interrupting message is written when the motor is not in the midst of a step, the module resets the motor step count and immediately begins actuating to follow the new reference command.
Module Functions
Below is a list of functions that this simulation module performs
Reads the incoming motor step command message
Computes the motor states as a function of time
Writes the motor states to the module output message
Handles interruptions to motor actuation by resetting the motor actuation after the current step is complete
Module Assumptions and Limitations
The motor step angle and step time are fixed parameters (Cannot be negative)
The motor cannot stop actuating in the middle of a step
When the motor actuation is interrupted by a new reference command, the motor must complete its actuation through the current step before following the new command
The module update rate must be faster than or equal to the provided motor step time \(\Delta t\)
The module update rate cannot be slower than the motor step rate, or the motor actuation cannot be resolved
Test Description and Success Criteria
There are two tests for this module. The two tests are described in test_stepperMotor.
The first test is a nominal test named test_stepper_motor_nominal
. The second test named
test_stepper_motor_interrupt
tests the module logic for commands interrupting the motor actuation. Both tests
configure two actuation commands. The nominal test separates the actuation commands by a rest period of 5 seconds. The
interruption test interrupts the first command sequence after half of the commanded motor steps are completed. The
time the second command message is written is determined using an interruption factor to specify what fraction of the
next step is completed before the second command message is written. Both tests add 5 seconds to the end of each
simulation for clarity when viewing the generated plots.
The success criteria for all tests is that the motor states converge to the computed reference values in the test at the end of each actuation sequence. Specifically, the motor angle, rate, acceleration, and step count are checked to converge to the reference values at the end of each simulation chunk. The motor rate and acceleration are checked to be zero at the end of each actuation sequence. Note that the motor acceleration is checked at one time step after the other motor states are checked because the motor acceleration is nonzero at the completion of each motor step. The motor acceleration is not zero until after the motor step is complete. This differs from the motor rate profile, which is zero at the completion of each motor step.
Nominal Test
The nominal unit test configures two actuation command segments with a rest period of 5 seconds between the commands. A rest period of 5 seconds is also added to the end of the simulation for clarity when viewing the generated plots. The initial motor angle, motor step angle, step time, and steps commanded for each actuation sequence are varied so that the motor actuates both forwards and backwards during the test. Zero steps commanded are also included in the test to check that the module correctly updates the motor states for a zero command message. The motor angle, rate, acceleration, and step count are checked to converge to the reference values at the end of each simulation chunk.
Interruption Test
The interruption unit test ensures that the module correctly handles reference messages that interrupt an unfinished motor actuation sequence. The initial motor angle, motor step angle, and step time are not varied in the interruption test because these parameters were already varied in the nominal test. The interruption test interrupts the first command sequence after half of the commanded motor steps are completed. The time the second command message is written is determined using an interruption factor to specify what fraction of the next step is completed before the second command message is written. Interruption factors of 0 and 1 are also included to ensure the module correctly resets the motor states when the interruption falls precisely when a step is completed. A rest period of 5 seconds is added to the end of the simulation for clarity when viewing the generated plots. The motor angle, rate, acceleration, and step count are checked to converge to the reference values at the end of each simulation chunk.
-
class StepperMotor : public SysModel
- #include <stepperMotor.h>
Stepper motor class.
Public Functions
-
StepperMotor() = default
Constructor.
-
~StepperMotor() = default
Destructor.
-
void Reset(uint64_t currentSimNanos) override
Module reset method.
- Parameters:
callTime – [ns] Time the method is called
-
void UpdateState(uint64_t currentSimNanos) override
Module update method. This method profiles the stepper motor actuation as a function of time. The motor states are then written to the output message.
- Parameters:
callTime – [ns] Time the method is called
-
double getThetaInit() const
Getter method for the initial motor angle called
thetaInit
.- Returns:
double
-
double getStepAngle() const
Getter method for the motor step angle called
stepAngle
.- Returns:
double
-
double getStepTime() const
Getter method for the motor step time called
stepTime
.- Returns:
double
-
double getThetaDDotMax() const
Getter method for the maximum motor angular acceleration called
thetaDDotMax
.- Returns:
double
-
void setThetaInit(const double thetaInit)
Setter method for the initial motor angle.
- Parameters:
thetaInit – [rad] Initial motor angle
-
void setStepAngle(const double stepAngle)
Setter method for the motor step angle.
- Parameters:
stepAngle – [rad] Motor step angle
-
void setStepTime(const double stepTime)
Setter method for the motor step time.
- Parameters:
stepTime – [s] Motor step time
Public Members
-
ReadFunctor<MotorStepCommandMsgPayload> motorStepCommandInMsg
Input msg for the number of commanded motor step counts.
-
Message<StepperMotorMsgPayload> stepperMotorOutMsg
Output msg for the stepper motor state information.
Private Functions
-
void actuateMotor(double t)
This method is used to simulate the stepper motor actuation in time.
- Parameters:
t – [s] Time the method is called
-
void resetMotor()
This method resets the motor states when the current request is complete and a new request is received.
-
void updateStepParameters()
This method updates the step parameters after a step is completed.
-
bool isInStepFirstHalf(double t)
This method determines if the motor is in the first half of a step.
- Parameters:
t – [s] Time the method is called
- Returns:
bool
-
void computeStepFirstHalf(double t)
This method computes the motor states during the first half of each step.
- Parameters:
t – [s] Time the method is called
-
bool isInStepSecondHalf(double t)
This method determines if the motor is in the second half of a step.
- Parameters:
t – [s] Time the method is called
- Returns:
bool
-
void computeStepSecondHalf(double t)
This method computes the motor states during the second half of each step.
- Parameters:
t – [s] Time the method is called
-
void computeStepComplete(double t)
This method computes the motor states when a step is complete.
- Parameters:
t – [s] Time the method is called
Private Members
-
double stepAngle = {}
[rad] Angle the stepper motor moves through for a single step (constant)
-
double stepTime = {}
[s] Time required for a single motor step (constant)
-
int stepsCommanded = {}
[steps] Number of commanded steps
-
int stepCount = {}
[steps] Current motor step count (number of steps taken)
-
double thetaInit = {}
[rad] Initial motor angle
-
double intermediateThetaInit = {}
[rad] Initial motor angle at the start of each step
-
double intermediateThetaRef = {}
[rad] Reference motor angle at the end of each step
-
double theta = {}
[rad] Current motor angle
-
double thetaDot = {}
[rad/s] Current motor angle rate
-
double thetaDDot = {}
[rad/s^2] Current motor angular acceleration
-
double thetaDDotMax = {}
[rad/s^2] Maximum angular acceleration of the stepper motor
-
double tInit = {}
[s] Simulation time at the beginning of each step
-
double previousWrittenTime = {-1}
[ns] Time the last input message was written
-
double ts = {}
[s] The simulation time halfway through each step (switch time for ang accel)
-
double tf = {}
[s] Simulation time when the current step will be completed
-
bool actuationComplete = {true}
Boolean designating the motor has fully completed the commanded actuation.
-
bool stepComplete = {true}
Boolean designating the completion of a step.
-
bool newMsg = {}
Boolean designating a new command message is written.
-
bool interruptMsg = {}
Boolean designating the new command message is interrupting motor actuation.
-
double a = {}
Parabolic constant for the first half of a step.
-
double b = {}
Parabolic constant for the second half of a step.
-
StepperMotor() = default