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.

Links

(*) Disclosure: Some of the links above are affiliate links, meaning, at no additional cost to you I will earn a (little) comission if you click through and make a purchase. I only recommend products I own myself and I'm convinced they are useful for other makers.

History

First upload: 2021-09-02 | Version: 2024-03-22