Fun with Millis(): Stopp a delay()
In this series I want to show short snippets of code around millis().
For example, one might ask "Can anyone please tell me if it's possible to interrupt a delay function that is executing and reset the machine state. Say my function flips pin states for a certain time and it uses delay function but when I press a button it should quit executing the delay function. Is this possible?" or, "How can I read a button while the periode of a delay?", how can I do several things at the same time on an Arduino?
The principle we will follow on an Arduino (or other single core microcontrollers) is to avoid the delay() at all. Using principles like shown in "Blink Without Delay" we write code the non blocking way.
Blink two LEDs
The "Blink Without Delay" examples shows how to blink one LED based on milllis().
But can we blink two LEDs? Yes we can!
/* Fun with millis: switch Blink without Delay Switch LED on by button press for a specific time Switch LED off by next button press https://forum.arduino.cc/t/interrupt-delay-execution/1012123/4 wokwi example: https://wokwi.com/projects/337137520588358226 */ // constants won't change. They're used here to set pin numbers: const uint8_t buttonPin = 2; // the number of the pushbutton pin const uint8_t ledPin = 13; // the number of the LED pin const uint32_t interval = 2000; // in milliseconds // Variables will change: uint8_t ledState = LOW; // the current state of the output pin // the following variables are unsigned longs because the time, measured in // milliseconds, will quickly become a bigger number than can be stored in an int. uint32_t lastDebounceTime = 0; // the last time the output pin was toggled uint32_t debounceDelay = 50; // the debounce time; increase if the output flickers uint32_t previousMillis = 0; // the last time the LED was switched on void setup() { pinMode(buttonPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); // set initial LED state digitalWrite(ledPin, ledState); } // read and debounce the button, state change detection void readButton() { static int buttonState; // the current reading from the input pin static int lastButtonState = LOW; // the previous reading from the input pin // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you've waited long enough // since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is active if (buttonState == LOW) { ledState = !ledState; } // set the LED: if (ledState) { digitalWrite(ledPin, HIGH); previousMillis = millis(); // remember the time when LED was switched on by button } else digitalWrite(ledPin, LOW); } } // save the reading. Next time through the loop, it'll be the lastButtonState: lastButtonState = reading; } // switch off LED after interval is over void checkForTimeout() { if (ledState == HIGH && millis() - previousMillis > interval) { ledState = LOW; digitalWrite(ledPin, ledState); } } void loop() { readButton(); // to start or stop checkForTimeout(); }
We just added a new pin, an additional state C (for the third LED) and some lines of code.
A Larson Scanner / KITT Scanner
As we are already have 3 blinking LEDs you might ask, if we can expand this to a Larson Scanner like seen on the famous KITT. Yes for sure, Just follow the Link at the end of the page.