Stepper Motor Sync
In order for Bottango to animate a stepper motor it needs to first confirm the stepper motor is in a single, known home location. This process is called synchronization.
Bottango requires a single stepper motor position to be the only synchronization point. This is the home position of the stepper motor when you configured it in your project. Because of this fact, it’s encouraged when modeling your project in Bottango and establishing home, you take the detectable single location of the stepper into account.
A very common workflow is to set the home position of the stepper to be at one of the two end points of the range of motion of the stepper, and then place a limit switch of some kind just a little beyond that point. The goal of this process would be
- Begin the “auto homing” process on the stepper in a given direction, towards its home position.
- The stepper will travel until it hits the limit switch that is a little beyond the desired home position.
- The stepper motor will “back off” the limit switch by a small amount, landing at the desired position.
You could also skip the “back off” portion, and just have home be exactly where the limit switch is hit. The callbacks below show how to enable the kind of functionality described above.
isEffectorAutoHomeComplete - Basic
Section titled “isEffectorAutoHomeComplete - Basic”bool isEffectorAutoHomeComplete(AbstractEffector *effector, int &postAutoSyncMove, int autoSyncDirection){ char effectorIdentifier[9]; effector->getIdentifier(effectorIdentifier, 9);
if (strcmp(effectorIdentifier, "6") == 0) { pinMode(10, INPUT); if (digitalRead(10) == LOW) { return true; } }
return false;}This is the most basic use of the callback. Once a stepper starts auto-syncing, it will step in that direction until your logic in the callback stops it.
Initialization of pins is placed in the callback or near it for formatting reasons for the examples in this documentation. Better practice would be to move the pinMode initialization to the onThisControllerStarted callback rather than every callback trigger.
In the example above, the check occurs if the stepper has the identifier “6.” If it does, it then checks if pin 10 is read LOW (for example, a limit switch on pin 10). If it is detected low, the code returns TRUE.
When you return TRUE, you are signifying that the stepper has reached its desired home position, and can be considered ready to animate. The firmware will handle the rest of the process from there of communicating out that event.
isEffectorAutoHomeComplete - Advanced
Section titled “isEffectorAutoHomeComplete - Advanced”Here is a more advanced use of this callback that uses the two additional parameters in the callback.
int autoSyncDirectionautoSyncDirection is a signed integer representing the direction that auto sync is moving. A value of 1 means the stepper is moving clockwise, a value of -1 means the stepper is moving counter clockwise.
int &postAutoSyncMovepostAutoSyncMove is a pointer to an int. You set its value before returning true, to flag the number of steps (and direction) you want the stepper to move before it will finalize homing.
Here’s both put to use:
bool isEffectorAutoHomeComplete(AbstractEffector *effector, int &postAutoSyncMove, int autoSyncDirection){ char effectorIdentifier[9]; effector->getIdentifier(effectorIdentifier, 9);
if (strcmp(effectorIdentifier, "6") == 0) { // verify the direction of the sync // throw an error and shutdown if the wrong direction if (autoSyncDirection != -1) { // call stop and shutdown the firmware Outgoing::printOutputStringFlash(F("ERROR: Stepper 6 sync wrong direction")); Outgoing::printLine(); BottangoCore::stop(true); }
pinMode(10, INPUT); if (digitalRead(10) == LOW) { // move 150 steps in the opposite direction before finishing synchronization postAutoSyncMove = 150 * autoSyncDirection * -1; return true; } }
return false;}There are two additions to the simpler example above:
- We verify that the effector with identifier “6” is moving in the expected direction. If user error, etc. caused the stepper to move in the wrong direction, that might result in damage to the physical robot, especially since the stop moving limit switch would never get hit. In the example here, we want the stepper with the identifier “6” to home counter-clockwise (a negative value of autoSyncDirection). If we detect anything besides -1, we add an error to the outgoing log, and then call the stop method of Bottango core. We pass true to BottangoCore::stop() to flag that we want the entire firmware to shut down at this point.
// verify the direction of the sync// throw an error and shutdown if the wrong directionif (autoSyncDirection != -1){ // call stop and shutdown the firmware Outgoing::printOutputStringFlash(F("ERROR: Stepper 6 sync wrong direction")); Outgoing::printLine(); BottangoCore::stop(true);}- We want to step 150 steps back in the opposite direction we were syncing once we hit the limit switch, before finalizing the syncing process. In the branch where the limit switch is detected, we set postAutoSyncMove to “150 * autoSyncDirection * -1;” You can read that as 150 steps times the opposite direction of the current direction.
if (digitalRead(10) == LOW){ // move 150 steps in the opposite direction before finishing synchronization postAutoSyncMove = 150 * autoSyncDirection * -1; return true;}onEffectorPostAutoHomeSecondarySyncComplete
Section titled “onEffectorPostAutoHomeSecondarySyncComplete”void onEffectorPostAutoHomeSecondarySyncComplete(AbstractEffector *effector){ char effectorIdentifier[9]; effector->getIdentifier(effectorIdentifier, 9);
if (strcmp(effectorIdentifier, "6") == 0) { pinMode(12, OUTPUT); digitalWrite(12, HIGH); }}In the above advanced example, we tell the firmware to step 150 steps in the opposite direction after hitting the limit switch before finalizing the stepper synchronization. There’s a period of time that inherently occurs between when the limit switch is hit, and synchronization ends while the stepper is moving those 150 steps. That 150 steps to finalize the syncing is called PostAutoHomeSecondarySync. If you want to know when it’s done, and the stepper is fully synchronized and ready to go, this callback occurs.
In the example above we’re simply setting pin 12 high. But that’s unlikely to be a real use case. More likely you have your own state machine or state tracking, and you want to know when all your steppers are ready. For example, maybe in exported animation mode, you want to track each stepper and ensure that all are fully homed before starting the first animation.
onEffectorHomeReset
Section titled “onEffectorHomeReset”void onEffectorHomeReset(AbstractEffector *effector){ // callback when an effector is no longer considered homed, use for your own internal state tracking if needed.}Similar to the above, you may want tracking for your own internal state machine when a stepper loses its homing and is no longer considered able to move. The only place this callback occurs with out-of-the-box functionality of the Bottango firmware is when the desktop app requests a stepper to reset its home value. But it will also occur if you call into an AbstractEffector with your own logic and reset its home state manually.
effector->resetHome();