Hi guys, I need your help with a project using a stepper motor that is controlled by a single momentary button.
Depending on the position of a rotary switch, I need the stepper motor to run at different duty cycles, most of which are less than 100%. In other words, while holding the switch down, I want to:
- Make the motor spin for a given duration
- Pause for a given duration
- Repeat 1 and 2 until the button is released
The duration of the spin spintime
and the pause stepdelay
are defined by a 12-position rotary switch (I only need 8 of them, so the other positions are "empty").
My code below is only working for positions 7 and 8, because the stepdelay
variable (i.e. the pause time) is 0 for those two positions. I want the motor to spin continuously in these positions, one forward, one reverse. However, for basically any stepdelay
value over 0, the motor just emits a whining sound and doesn't spin. Thus positions 1-6 aren't working.
#include <ezButton.h>
const int stepPin = 3;
const int dirPin = 4;
ezButton go_button = 5;
const int enable = 6;
const int pos_1 = 8;
const int pos_2 = 9;
const int pos_3 = 10;
const int pos_4 = 16;
const int pos_5 = 14;
const int pos_6 = 15;
const int pos_7 = 18;
const int pos_8 = 7;
int stepdelay; //Motor off time
int spintime; //Motor on time
bool spindirection; //Motor spin direction
unsigned long buttonpresstime; //Moment when the button is pressed
void setup() {
pinMode(stepPin,OUTPUT);
pinMode(dirPin,OUTPUT);
pinMode(enable,OUTPUT);
pinMode(pos_1,INPUT_PULLUP);
pinMode(pos_2,INPUT_PULLUP);
pinMode(pos_3,INPUT_PULLUP);
pinMode(pos_4,INPUT_PULLUP);
pinMode(pos_5,INPUT_PULLUP);
pinMode(pos_6,INPUT_PULLUP);
pinMode(pos_7,INPUT_PULLUP);
pinMode(pos_8,INPUT_PULLUP);
go_button.setDebounceTime(50);
digitalWrite(enable,HIGH); //Sets initial condition of the stepper motor driver board outputs to "off"
}
void loop() {
//Get position from rotary switch
int pos_1_State = digitalRead(pos_1);
int pos_2_State = digitalRead(pos_2);
int pos_3_State = digitalRead(pos_3);
int pos_4_State = digitalRead(pos_4);
int pos_5_State = digitalRead(pos_5);
int pos_6_State = digitalRead(pos_6);
int pos_7_State = digitalRead(pos_7);
int pos_8_State = digitalRead(pos_8);
//Set motor output parameters based on switch position
if (pos_1_State == LOW) {
stepdelay = 450;
spintime = 350;
spindirection = HIGH;
} else if (pos_2_State == LOW) {
stepdelay = 550;
spintime = 300;
spindirection = HIGH;
} else if (pos_3_State == LOW) {
stepdelay = 650;
spintime = 250;
spindirection = HIGH;
} else if (pos_4_State == LOW) {
stepdelay = 750;
spintime = 200;
spindirection = HIGH;
} else if (pos_5_State == LOW) {
stepdelay = 850;
spintime = 150;
spindirection = HIGH;
} else if (pos_6_State == LOW) {
stepdelay = 950;
spintime = 100;
spindirection = HIGH;
} else if (pos_7_State == LOW) { //Constant forward speed position
stepdelay = 0;
spintime = 32000;
spindirection = HIGH;
} else if (pos_8_State == LOW) { //Reverse, constant speed
stepdelay = 0;
spintime = 32000;
spindirection = LOW;
} else { //Accounting for switch in "empty" positions
stepdelay = 0;
spintime = 0;
spindirection = LOW;
}
go_button.loop();
int go_ButtonState = go_button.getState();
if(go_ButtonState == 0) {
digitalWrite(enable,LOW); //Turn on motor driver board outputs
digitalWrite(dirPin,spindirection); //Set motor spin direction based on rotary switch position
buttonpresstime = millis(); //Get the moment in time when the button is pressed
if (millis() - buttonpresstime < spintime) { //Spin motor for "spintime" duration set by switch position
digitalWrite(stepPin,HIGH);
delayMicroseconds(100);
digitalWrite(stepPin,LOW);
delayMicroseconds(100);
}
delay(stepdelay); //Pause for duration set by switch position
go_button.getState();
}
if(go_button.isReleased()){
digitalWrite(enable,HIGH); //Turn off motor driver board outputs
}
}
I understand that using delay
in a sketch is generally not considered best practice as it shuts down everything else from happening, and that appears to be what the primary source of the problem is here. But I can't seem to successfully insert my "pause time" into the code via another method.
I tried creating a second millis()
if loop for the delay using a new unsigned long variable named spindonetime
. I inserted the following code in place of the delay(stepdelay);
line. Unfortunately, this didn't work either:
spindonetime = millis();
if (millis() - spindonetime < stepdelay) {
digitalWrite(enable,HIGH); //Turn off motor driver board outputs for duration of "stepdelay"
}
I'm pretty stumped at this point.
Thanks for any help you can give!