To make a led blink 5 times after button press using millis

To Make an led blink 5 times after button press using millis look at paulpaulson's code in this post.

This code makes and led blink repeatedly after button press using millis. How do i make it only blink 5 times and stop till the button is pressed again.

const int ledPin = 8;
const int button1 = 5;
int ledState = LOW;
unsigned long previousMillis1 = 0;

const long interval = 1000;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentMillis = millis();
  if (digitalRead(button1) == LOW)
  {
   digitalWrite(ledPin, ledState);
   digitalWrite(button1, LOW);
   if (currentMillis - previousMillis1 >= interval) 
   {
     previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
      if (ledState == LOW) 
      {
       ledState = HIGH;
      } 
       else 
       {
        ledState = LOW;
       }
      
    }
        
  }
}

Consider making the blinking portion a function. When the button is pressed set a counter to 5. The blink function will blink 5 times, each blink sequence will count down 1. When zero is reached exit the function.

2 Likes

The @gilshultz function method is best, but another way to adjust: Make a counter (x). Make the "interval" condition line include checking the value of x. Increment x every time the light changes (10 changes - 5 off, 5 on). When x reaches 10, the "interval" condition will fail and the LED will not blink.

1 Like

Firstly, The code should not: digitalWrite(button1, LOW);

Secondly, you had better to use the state change detection, please see
Arduino button tutorial

Thirdly, you can simplify the code by using libraries:

Hello johnathonj

Consider:

const int ledPin = 8;
const int button1 = 5;
int ledState = LOW;
unsigned long previousMillis1 = 0;
const long interval = 1000;

uint8_t counter = 0;
constexpr uint8_t NumberOfCounts {5};

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentMillis = millis();

  if (digitalRead(button1) == LOW)
  {
    previousMillis1 = currentMillis;
    counter = NumberOfCounts;
    digitalWrite(ledPin, HIGH);
  }

  if (currentMillis - previousMillis1 >= interval)
  {
    previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      if (counter != 0) counter--;
    }
    else
    {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState and counter);
  }
}

Have a nice day and enjoy coding in C++.

Your awesome that works. My button need a dyebounce time though. Thank you thank you and thank you.

@johnathonj - this is the debounce...

No, that is not. There is no denouncing.

The blinking doesn't start until you get off the button.

If @johnathonj wants the blinking to start immediately the button gets pressed, there will have to be debouncing and edge detection logic added.

a7

Hello johnathonj

Change

if (digitalRead(button1) == LOW)

to

if ((digitalRead(button1) == LOW) and (counter == 0))

Now the LED will blink until you get off the button plus a few more blinks.

Which my be what you want.

a7

This code works like this with my set up. A quick button press usually results in five short led blinks. A slow button press usually results in a long led blink and three short blinks. I added a debounce to it (i think) didn't seem to help. This is an exercise to help myself and maybe other readers of this post better understand millis timing. So might try a delay using millis after the button press or something. I am work right now and can't post code or anything. Thank you and everyone one else for your help.

1 Like

Your description of the behaviour probably matches what you could determine by walking your finger through the code.

Rather than trying to patch up what are undesirable outcomes, you could use debouncing and common ways of acting on the press of a button rather than the state of the button

In the IDE there is an example, early on, called "state change detection" or something like that, and googling

arduino state change detection

will turn up a fairly good official article on the code used, and many other hits as this is a necessary thing to know how to do - act when a button gets pressed, rather than because it is being held down.

It's also called edge detection, "edge" in this context is that time at which you press (leading edge) or release (trailing edge) a pushbutton.

Act on the leading edge, let that be what starts the five blink counting.

a7

1 Like

Awesome i will do that. Thank you

I don't know why but this does almost exactly what i wanted. Doesn't seem to matter what i change the previousMillis1 == 250 number to. Had to change the numberofcounts to 6, to get five blinks. Start blinking delay time is a little inconsistent but not much. The led stays off while the button is pressed and blinks five times, after button is released.

const int ledPin = 8;
const int button1 = 5;
int ledState = LOW;
unsigned long previousMillis1 = 0;
const long interval = 1000;

uint8_t counter = 0;
constexpr uint8_t NumberOfCounts {6};

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentMillis = millis();
    if (digitalRead(button1) == LOW)
    {
     previousMillis1 = currentMillis;
     counter = NumberOfCounts;
     if (previousMillis1 == 250)
     {
     digitalWrite(ledPin, HIGH);
     }
    }
  if (currentMillis - previousMillis1 >= interval)
  {
    previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      if (counter != 0) counter--;
    }
    else
    {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState and counter);
  }
}

with button state detection, if i did right. Didn't seem to help.

const int ledPin = 8;
const int button1 = 5;
int ledState = LOW;
unsigned long previousMillis1 = 0;
const long interval = 1000;
int buttonState = 0;
int lastButtonState = 0;

uint8_t counter = 0;
constexpr uint8_t NumberOfCounts {5};

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  buttonState = digitalRead(button1);
  unsigned long currentMillis = millis();
  if (buttonState != lastButtonState)
  {
  if (buttonState == LOW)
  {
    previousMillis1 = currentMillis;
    counter = NumberOfCounts;
    digitalWrite(ledPin, HIGH);
  }
  }
  lastButtonState = buttonState;
  if (currentMillis - previousMillis1 >= interval)
  {
    previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      if (counter != 0) counter--;
    }
    else
    {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState and counter);
  }
}

with button debounce, if I did it right. Didn't seem to help,

const int ledPin = 8;
const int button1 = 5;
int ledState = LOW;
unsigned long previousMillis1 = 0;
const long interval = 1000;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

uint8_t counter = 0;
constexpr uint8_t NumberOfCounts {5};

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentMillis = millis();

 if ((millis() - lastDebounceTime) > debounceDelay)
  {
    if (digitalRead(button1) == LOW)
   {
    previousMillis1 = currentMillis;
    counter = NumberOfCounts;
    digitalWrite(ledPin, HIGH);
    lastDebounceTime = millis();
   }
  }
  if (currentMillis - previousMillis1 >= interval)
  {
    previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
     if (ledState == LOW)
     {
      ledState = HIGH;
      if (counter != 0) counter--;
     }
      else
      {
        ledState = LOW;
      }
    digitalWrite(ledPin, ledState and counter);
  }
}

Have you abandoned the code in #14?

I can't read your code just now. Are these two sketches one with state change detection and the other with debounce?

You need to do both.

As for doing it right, where are you seeing the patterns that you are copying or working from? If you start with something simpler you would be able to see if you did it right or not straight away.

You can trace the code with your finger, but usually it is faster to use serial printing. Place serial print statements in the code all over to see the flow through your code and verify that is is informed
properly by the values of key variables.

If you don't do the finger thing or the printing thing, you are flying blind.

An easier first sketch is to just get something to print

  • I saw you press the button

  • I saw you release the button

once each time you do press, then release the button.

When you have that working, kick off five blinks where you printed that you saw the button get pressed.

Worry later about how to handle a second button press whilst still counting off the five blinks.

You code may be close, but between the odd formatting, the tiny window I am looking through and a few distractions my inspection will have to wait.

Later: Through the larger window, I see necessary elements in both sketches, but nothing complete in either.

This is parts of your code all mashed together with printing. I hand it to you and hope you take some time to read it line by line, execute it with your finger or by adding even more printing, and perhaps try to fix what I consider to be a defect even though the sketch "works": it continues to write to the output even after count is 0, is just that at that point it is always writing 0.

const int ledPin = 8;
const int button1 = 5;

int ledState = LOW;
int lastButtonState;

unsigned long previousMillis1 = 0;
const long interval = 1000;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

uint8_t counter = 0;
constexpr uint8_t NumberOfCounts {5};

void setup()
{
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentMillis = millis();

  if ((millis() - lastDebounceTime) > debounceDelay)  // debounce
  {
    int buttonState = digitalRead(button1);
  
    if (buttonState != lastButtonState)               // state change detection
    {
      if (buttonState == LOW) {
        previousMillis1 = currentMillis;
        counter = NumberOfCounts;
        digitalWrite(ledPin, HIGH);
      }
      
      lastButtonState = buttonState;
      lastDebounceTime = millis();
    }
  }

  if (currentMillis - previousMillis1 >= interval)
  {
    Serial.print("timed for blinkation: count = ");
    Serial.println(counter);

    previousMillis1 = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      if (counter != 0) counter--;
    }
    else
    {
      ledState = LOW;
    }
    Serial.println("                    writing to the LED!");
    digitalWrite(ledPin, ledState and counter);
  }
}

If it doesn't work, try fixing it. ;-)

Tip: Use the Autoformat tool in the IDE until you are automatically writing code with good formatting.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.