Robin2:
The functions delay() and delayMicroseconds() block the Arduino until they complete. Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.
And see Using millis() for timing. A beginners guide if you need more explanation.
...R
johnwasser:
One good way to debounce a button:
const unsigned long DebounceTime = 30;
const byte ButtonPin = 7;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(ButtonPin, INPUT_PULLUP); // Button goes between pin and ground. Active LOW.
}
void loop()
{
static boolean lastButtonState = false; // Not pushed
static unsigned long lastButtonStateChangeTime = 0;
static boolean LEDState = LOW;
boolean buttonState = digitalRead(ButtonPin) == LOW; // 'true' if button is pressed
if (buttonState != lastButtonState && millis() - lastButtonStateChangeTime > DebounceTime)
{
// Button State Changed
lastButtonState = buttonState;
lastButtonStateChangeTime = millis();
if (buttonState)
{
// Button just pressed
LEDState = !LEDState; // Toggle LED
digitalWrite(LED_BUILTIN, LEDState);
}
else
{
// Put code here if you want to do something when button is released
}
} // end of Button State Changed
} // end of loop()
Thanks guys, this sorted out the speed issue
Any idea why the improved code with millis() started working only after I removed the Serial.begin and Serial.print commands from the loop?
So in summary the code contains 3 states.
State 0, during which the stepper does not do anything.
State 1, during which the stepper runs until reaching a certain distance and changes to state 2.
State 2, during which the stepper runs into the opposite direction for the same distance as in state 1 and changes to state 0 upon completion.
Now the next thing that I want to accomplish is for the code to repeat state 1 and 2 for x number of times, and upon reaching that number, changing to state 0. In other words I want the stepper motors to run forward and backward for X amount of times before stopping and waiting for the next input.
I've tried the following:
-
Changed the code in state 2 to switch back to state 1 instead of 0, thereby creating a loop between state 1 and 2.
-
Added int repeatCounter at the end of state 2, which counts (or is supposed to count) the number of times that state 1 and 2 have been completed.
-
Added an if statement after state 2 that switches back to state 0 if repeatCounter matches a certain number.
Does this make sense in terms of what I am trying to accomplish? Or should I pursue a different approach? Either way, after pressing the button, the motor keeps spinning back and forth (state 1 and state 2) without stopping after a certain amount of times :-\
#define DISTANCE 1000
// Statechange//
int buttonState = 0;
int lastButtonState = 0;
int ledState = 0;
int StepCounter = 0;
int Stepping = false;
//Stepper//
int Distance = 0; // Record the number of steps we've taken
int repeatCounter = 0;
//Debounce//
const unsigned long DebounceTime = 50;
void setup() {
//Initialize at startup
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(8, OUTPUT); //Dir
pinMode(9, OUTPUT); //Step
digitalWrite(8, 0);
digitalWrite(9, 0);
}
void loop() {
//Debounce//
static unsigned long lastButtonStateChangeTime = 0;
//STATECHANGE//
//read the pushbutton input pin
buttonState = digitalRead(2);
//check if the button is pressed or released
//by comparing the buttonState to its previous state
if (buttonState != lastButtonState && millis() - lastButtonStateChangeTime > DebounceTime){
//change the state of the led (stepper motor) when someone pressed the button
if (buttonState == 1) {
if (ledState==1) ledState=0;
else ledState=1;
}
// remember the current state of the button
lastButtonState = buttonState;
lastButtonStateChangeTime = millis();
}
//ACTION BASED ON STATECHANGE//
// turns LED on if the ledState=1 or off if the ledState=0
if (ledState == 1) {
digitalWrite(9, HIGH);
delayMicroseconds(200);
digitalWrite(9, LOW);
delayMicroseconds(200);
StepCounter = StepCounter +1;
if (StepCounter == DISTANCE)
{
StepCounter = 0;
ledState = 2;
digitalWrite(8, HIGH); // change direction
}
}
if (ledState == 2) {
digitalWrite(9, HIGH);
delayMicroseconds(200);
digitalWrite(9, LOW);
delayMicroseconds(200);
StepCounter = StepCounter +1;
if (StepCounter == DISTANCE) //When finished state 2
{
StepCounter = 0;
repeatCounter = repeatCounter +1;
digitalWrite(8, LOW); // Change direction
if (repeatCounter == 4); // If leadstate 1 + 2 have been repeated 4 times
{
ledState = 0; //Stop stepper motor
repeatCounter = 0;
}
if (repeatCounter < 4);
{
ledState = 1;
}
}
}
}