Hi all,
Project brief (simplified):
I am building a project that uses a stepper motor to drive a wheel clockwise (CW), counter-clockwise (CCW) and then CW again 360 degrees for each rotation. This pattern repeats forever. CW/CCW/CW, pause, CW/CCW/CW, pause......
I have the motor turning and working as I expect.
The challenge:
One iteration at random, the wheel will be stopped (i.e. brake applied) after turning 90 degrees on the second CW spin.
If the brake has not been applied then everything should continue.
The 'brake' is independent of the project and is outside the control of the user.
I need a way to know that it has been stopped. I have been searching the forums and there are lots of suggestions of trying to read the current of the motor or other complex ideas. I thought the easier option would be to connect a Rotary Encoder to the output of the motor so that when the motor turns, the encoder turns too; so that's what I've got.
Speed is a consideration, not having too many steps to take or stops along the way is beneficial.
My head scratching moment is how to detect the Rotary Encoder has been moving and isn't anymore. If the brake has been applied then trying to continue turning will cause damage to the motor/support structure/wheel.
Possible methods I'm thinking of so far:
- Move 90 degrees and then move a small increment and check the encoder? Use a count variable to count RE pulses and an iteration variable to count how many steps have been taken. Turn motor in small increments (~10 steps at a time) and increment iteration each time. Compare?
- Measure how many pulses the RE takes for a 90 degree turn of the motor and then if pulses_ count >= pulses_to_turn_90 then it hasn't stalled?
- Is there a way to count how many pulses have occurred in a set time?
Hardware:
1x 23HE45-4204S Stepper motor
1x DM556 driver
1x PSU
1x Arduino Uno
1x KY-040 Rotary Encoder
Rotary encoder tested and working using slightly modified In-Depth: How Rotary Encoder Works and Interface It with Arduino code (I don't care about the button):
// Rotary Encoder Inputs
#define CLK 2
#define DT 3
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir = "";
void setup() {
// Set encoder pins as inputs
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1) {
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
currentDir = "CCW";
} else {
// Encoder is rotating CW so increment
counter ++;
currentDir = "CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Put in a slight delay to help debounce the reading
delay(1);
}
Example of my code to spin motor a full spin:
void fullSpinL() {
//Serial.println("Left");
digitalWrite(dirPin, HIGH);
for (int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(500);
}
delay(1000); // Wait a second
}
Code to turn a quarter turn:
void quarter() { //Quarter turn right
digitalWrite(dirPin, LOW);
for (int x = 0; x < 100; x++) //400 step motor so 1/4 = 100
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
delay(1000); // Wait a second
}
Part of writing this was to 'Rubber Duck" my thoughts but if anyone has any ideas on how to use a rotary encoder to detect when a stepper motor has stopped I would appreciate it.
Hope this is clear but please ask for clarifications!
Thanks