Hi I am working on a project which will be using some stepper motors to control dampers opening and closing on a linkage system. For this, we are using Automation Direct Stepper motors and drivers and a ClearCore board.
I am trying to get both stepper motors to drive in one direction, and then have each motor stop when a limit switch is achieved for that individual motor. Once both limit switches have been achieved, I need the motors to reverse and drive until they each hit a second limit switch, then start a timer and repeat.
I have gotten to a point where it will sometimes work, but I have not been able to get it to work consistently. Sometimes it will blow right by the limit switch sensor and continue rotating. For our application it can only do a 180* Turn then needs to reverse directions.
I was hoping someone may be able to point me into the correct direction to get this to work consistently. Thank you in advance
#include "ClearCore.h"
#include "DigitalIn.h"
#include <DigitalInAnalogIn.h>
// Specifies which motor to move.
// Options are: ConnectorM0, ConnectorM1, ConnectorM2, or ConnectorM3.
#define motor1 ConnectorM0
#define motor2 ConnectorM1
#define inputPin6 DI6
#define inputPin7 DI7
#define inputPin1 IO1
#define inputPin0 IO0
#define OnSwitch A12
// The current state of the input pin
PinStatus state;
bool SensorStatus0;
bool SensorStatus1;
bool SensorStatus6;
bool SensorStatus7;
bool SwitchState;
// Select the baud rate to match the target serial device
#define baudRate 9600
// This example has built-in functionality to automatically clear motor alerts,
// including motor shutdowns. Any uncleared alert will cancel and disallow motion.
// WARNING: enabling automatic alert handling will clear alerts immediately when
// encountered and return a motor to a state in which motion is allowed. Before
// enabling this functionality, be sure to understand this behavior and ensure
// your system will not enter an unsafe state.
// To enable automatic alert handling, #define HANDLE_ALERTS (1)
// To disable automatic alert handling, #define HANDLE_ALERTS (0)
#define HANDLE_ALERTS (1)
// Define the velocity and acceleration limits to be used for each move
int accelerationLimit = 1000; // pulses per sec^2
// Declares user-defined helper functions.
// The definition/implementations of these functions are at the bottom of the sketch.
bool MoveAtVelocity(int32_t velocity);
void PrintAlerts();
void HandleAlerts();
void setup() {
// Put your setup code here, it will only run once:
ConnectorA12.Mode(Connector::INPUT_ANALOG);
pinMode(inputPin0, INPUT); // Set the pin as an INPUT
pinMode(inputPin1, INPUT);
pinMode(inputPin6, INPUT); // Set the pin as an INPUT
pinMode(inputPin7, INPUT);
pinMode(OnSwitch, INPUT);
// Sets the input clocking rate. This normal rate is ideal for ClearPath
// step and direction applications.
MotorMgr.MotorInputClocking(MotorManager::CLOCK_RATE_NORMAL);
// Sets all motor connectors into step and direction mode.
MotorMgr.MotorModeSet(MotorManager::MOTOR_ALL,
Connector::CPM_MODE_STEP_AND_DIR);
motor1.PolarityInvertSDEnable(true);
motor1.PolarityInvertSDDirection(true);
motor1.PolarityInvertSDHlfb(true);
motor2.PolarityInvertSDEnable(true);
motor2.PolarityInvertSDDirection(true);
motor2.PolarityInvertSDHlfb(true);
// Set the motor's HLFB mode to bipolar PWM
motor1.HlfbMode(MotorDriver::HLFB_MODE_HAS_BIPOLAR_PWM);
// Set the HFLB carrier frequency to 482 Hz
motor1.HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
// Set the maximum acceleration for each move
motor1.AccelMax(accelerationLimit);
motor2.HlfbMode(MotorDriver::HLFB_MODE_HAS_BIPOLAR_PWM);
// Set the HFLB carrier frequency to 482 Hz
motor2.HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
// Set the maximum acceleration for each move
motor2.AccelMax(accelerationLimit);
// Sets up serial communication and waits up to 5 seconds for a port to open.
// Serial communication is not required for this example to run.
Serial.begin(baudRate);
uint32_t timeout = 5000;
uint32_t startTime = millis();
while (!Serial && millis() - startTime < timeout) {
continue;
}
// Enables the motor; homing will begin automatically if enabled
motor1.EnableRequest(true);
Serial.println("Motor Enabled");
motor2.EnableRequest(true);
Serial.println("Motor Enabled");
// Waits for HLFB to assert (waits for homing to complete if applicable)
Serial.println("Waiting for HLFB...");
while (motor1.HlfbState() != MotorDriver::HLFB_ASSERTED &&
!motor1.StatusReg().bit.AlertsPresent) {
continue;
}
// Check if motor alert occurred during enabling
// Clear alert if configured to do so
if (motor1.StatusReg().bit.AlertsPresent) {
Serial.println("Motor alert detected.");
PrintAlerts();
if(HANDLE_ALERTS){
HandleAlerts();
} else {
Serial.println("Enable automatic alert handling by setting HANDLE_ALERTS to 1.");
}
Serial.println("Enabling may not have completed as expected. Proceed with caution.");
Serial.println();
} else {
Serial.println("Motor Ready");
}
}
void loop() {
// Put your main code here, it will run repeatedly:
float analogReadingV = ConnectorA12.AnalogVoltage();
//Serial.println(analogReadingV);
SwitchState = analogRead(OnSwitch);
delay(1);
// Serial.write(analogReadingV);
if (analogReadingV > 1){
// if (ConnectorM0.EnableRequest()) {
// If the motor is currently enabled, disable it.
ConnectorM0.EnableRequest(false);
//}
//if (ConnectorM1.EnableRequest()) {
// If the motor is currently enabled, disable it.
ConnectorM1.EnableRequest(false);
//}
}
if (analogReadingV <1) {
//if (ConnectorM0.EnableRequest()) {
// If the motor is currently enabled, disable it.
ConnectorM0.EnableRequest(true);
//}
//if (ConnectorM1.EnableRequest()) {
// If the motor is currently enabled, disable it.
ConnectorM1.EnableRequest(true);
//}
}
/*
Serial.print("Motors: ");
if (analogReadingV < 1) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
// Wait a second thebn repeat...
delay(100);
state = digitalRead(inputPin6);
// Display the state of the input connector.
Serial.print("DI-6 Input state: ");
if (state) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
// Wait a second thebn repeat...
delay(100);
state = digitalRead(inputPin7);
// Display the state of the input connector.
Serial.print("DI-7 Input state: ");
if (state) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
// Wait a second then repeat...
delay(100);
state = digitalRead(inputPin0);
// Display the state of the input connector.
Serial.print("IO-0 Input state: ");
if (state) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
state = digitalRead(inputPin1);
// Display the state of the input connector.
Serial.print("I0-1 Input state: ");
if (state) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
delay(100);
*/
SensorStatus0 = digitalRead(inputPin0);
SensorStatus1 = digitalRead(inputPin1);
SensorStatus6 = digitalRead(inputPin6);
SensorStatus7 = digitalRead(inputPin7);
if (SensorStatus6 == false && (motor2.MoveVelocity(-100))){
motor2.MoveVelocity(0);
}
delay(10);
if (SensorStatus7 == false && (motor1.MoveVelocity(-100))){
motor1.MoveVelocity(0);
}
delay(10);
if (SensorStatus0 == false && (motor1.MoveVelocity(100))){
motor2.MoveVelocity(0);
}
delay(10);
if (SensorStatus1 == false && (motor2.MoveVelocity(100))){
motor1.MoveVelocity(0);
}
delay(10);
if (SensorStatus6 == false && SensorStatus7 == false)
{
motor1.MoveVelocity(0);
motor2.MoveVelocity(0);
delay(2000);
motor1.MoveVelocity(100);
motor2.MoveVelocity(100);
delay(200);
motor1.MoveVelocity(100);
motor2.MoveVelocity(100);
if (SensorStatus1 == false)
{
motor2.MoveVelocity(0);
}
delay(1);
if (SensorStatus0 == false)
{
motor1.MoveVelocity(0);
}
delay(1);
}
delay(100);
if(SensorStatus0 == false && SensorStatus1 == false)
{
motor1.MoveVelocity(0);
motor2.MoveVelocity(0);
delay(2000);
motor1.MoveVelocity(-100);
motor2.MoveVelocity(-100);
delay(200);
motor1.MoveVelocity(-100);
motor2.MoveVelocity(-100);
if (SensorStatus6 == false)
{
motor2.MoveVelocity(0);
}
delay(1);
if (SensorStatus7 == false)
{
motor1.MoveVelocity(0);
}
delay(1);
}
delay(100);
/*
if (SensorStatus1 == false) {
// Move at 1,000 steps/sec for 2000ms
MoveAtVelocity(100);
delay(5000);
MoveAtVelocity(0);
delay(5000);
// Move at -5,000 steps/sec for 2000ms
MoveAtVelocity(-100);
delay(5000);
MoveAtVelocity(0);
delay(10000);
}
*/
}
/*------------------------------------------------------------------------------
* MoveAtVelocity
*
* Command the motor to move at the specified "velocity", in pulses/second.
* Prints the move status to the USB serial port
*
* Parameters:
* int velocity - The velocity, in step pulses/sec, to command
*
* Returns: True/False depending on whether the move was successfully triggered.
*/
bool MoveAtVelocity(int velocity) {
// Check if a motor alert is currently preventing motion
// Clear alert if configured to do so
if (motor1.StatusReg().bit.AlertsPresent) {
Serial.println("Motor alert detected.");
PrintAlerts();
if(HANDLE_ALERTS){
HandleAlerts();
} else {
Serial.println("Enable automatic alert handling by setting HANDLE_ALERTS to 1.");
}
Serial.println("Move canceled.");
Serial.println();
return false;
}
Serial.print("Moving at velocity: ");
Serial.println(velocity);
// Command the velocity move
motor1.MoveVelocity(velocity);
motor2.MoveVelocity(velocity);
// Waits for the step command to ramp up/down to the commanded velocity.
// This time will depend on your Acceleration Limit.
Serial.println("Ramping to speed...");
while (!motor1.StatusReg().bit.AtTargetVelocity) {
continue;
}
Serial.println("At Speed");
return true;
}
//------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
* PrintAlerts
*
* Prints active alerts.
*
* Parameters:
* requires "motor" to be defined as a ClearCore motor connector
*
* Returns:
* none
*/
void PrintAlerts(){
// report status of alerts
Serial.println("Alerts present: ");
if(motor1.AlertReg().bit.MotionCanceledInAlert){
Serial.println(" MotionCanceledInAlert "); }
if(motor1.AlertReg().bit.MotionCanceledPositiveLimit){
Serial.println(" MotionCanceledPositiveLimit "); }
if(motor1.AlertReg().bit.MotionCanceledNegativeLimit){
Serial.println(" MotionCanceledNegativeLimit "); }
if(motor1.AlertReg().bit.MotionCanceledSensorEStop){
Serial.println(" MotionCanceledSensorEStop "); }
if(motor1.AlertReg().bit.MotionCanceledMotorDisabled){
Serial.println(" MotionCanceledMotorDisabled "); }
if(motor1.AlertReg().bit.MotorFaulted){
Serial.println(" MotorFaulted ");
}
}
//------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
* HandleAlerts
*
* Clears alerts, including motor faults.
* Faults are cleared by cycling enable to the motor.
* Alerts are cleared by clearing the ClearCore alert register directly.
*
* Parameters:
* requires "motor" to be defined as a ClearCore motor connector
*
* Returns:
* none
*/
void HandleAlerts(){
if(motor1.AlertReg().bit.MotorFaulted){
// if a motor fault is present, clear it by cycling enable
Serial.println("Faults present. Cycling enable signal to motor to clear faults.");
motor1.EnableRequest(false);
Delay_ms(10);
motor1.EnableRequest(true);
}
// clear alerts
Serial.println("Clearing alerts.");
motor1.ClearAlerts();
}
//------------------------------------------------------------------------------
