Using Millis to turn an LED on for 3 seconds HELP PLEASE!!

Hi

I'm having trouble turning on an LED for 3 seconds using a push button and the millis function. At the minute the LED only flashes briefly every 3 seconds whilst the button is held down. I need it to turn on for 3 second when the button is pushed briefly.....

Any help appreciated

const int ledPin =  13;      // the number of the LED pin
long previousMillis = 0;        // will store last time LED was updated
const int DisplayButton = 2; 
int buttonState = 0; 


long interval = 3000;           // interval at which to blink (milliseconds)

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

void loop()
{ 
  buttonState = digitalRead(DisplayButton);
    
  unsigned long currentMillis = millis();
  
  if (buttonState == HIGH) {
    
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   

      digitalWrite(ledPin, HIGH);

  }
     
 else
      {
      digitalWrite(ledPin, LOW);
      }

  }
}

You are turning the LED off when ever the button is not pressed. Why?

You need only turn off the LED when you have had the time interval.

So look at the button, is it high? If so set the previous millis. Then look to see if the previous millis compaired to the current is greater than the interval. Only if it is turn off the LED.

The first thing you need to deal with is determining that the switch HAS BECOME pressed, not IS pressed. If the idea is turn have the LED on for three seconds regardless of how long the switch is held down, that is. If the idea is to have the LED on for three seconds after the switch is released, that's a different story.

What is it you want to do?

thanks for the quick reply, i would like to LED to turn on regardless of how long the button is pressed down for and to be turned on instantly not when released.

Grumpy_Mike: You are turning the LED off when ever the button is not pressed. Why?

You need only turn off the LED when you have had the time interval.

So look at the button, is it high? If so set the previous millis. Then look to see if the previous millis compaired to the current is greater than the interval. Only if it is turn off the LED.

so something like this? this turns on the LED permanently and i cant figure out why. when the button is pressed it turns on the led, counts the interval then it should turn off the LED right? thanks

const int ledPin =  13;      // the number of the LED pin
long previousMillis = 0;        // will store last time LED was updated
const int DisplayButton = 2; 
int buttonState = 0; 


long interval = 1000;           // interval at which to blink (milliseconds)

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

void loop()
{ 
    buttonState = digitalRead(DisplayButton);
    
  unsigned long currentMillis = millis();
  
  if (buttonState == HIGH) {
    
    digitalWrite(ledPin, HIGH);
    
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   
  
   digitalWrite(ledPin, LOW);

  }
  }
}

i would like to LED to turn on regardless of how long the button is pressed down for and to be turned on instantly not when released.

Well that's certainly clear as mud.

sorry if i didnt make any sense, i just want to turn the led on for 3 seconds as soon as the button is pressed. does that make sense? thanks

i just want to turn the led on for 3 seconds as soon as the button is pressed. does that make sense?

It makes more sense. Now, I guess we need to discuss "is pressed" vs. "becomes pressed". The state change detection example shows you how to do something (like turn a pin on and record a time) when a switch changes state (from pressed to released or from released to pressed).

The code you have now deals with reading if the switch IS pressed, rather than if the switch HAS BECOME pressed. That is, you need to compare the state of the pin this time to the state of the pin last time, and only act when the states are not the same AND the current state is pressed. Of course, to do this you need to keep track of the state last time, in a global or static variable, as the state change detection example shows.

this turns on the LED permanently and i cant figure out why. when the button is pressed it turns on the led, counts the interval then it should turn off the LED right?

That is not what that code says. You have the scope of the first if statement encompassing the second if statement. That is the only time you look to see if the time has elapsed is when the button is being held down.

  • what Paul says.

m600:
sorry if i didnt make any sense, i just want to turn the led on for 3 seconds as soon as the button is pressed. does that make sense?
thanks

try like this, for example, it will restart the timer if you press while lit…

const int ledPin =  13;      // the number of the LED pin
unsigned long startTime;        // will store last time LED was updated
const int DisplayButton = 2; 
int lastButtonState = 0; 
int ledState;
unsigned long interval = 3000UL;           // interval at which to blink (milliseconds)

void setup() 
{
  pinMode(ledPin, OUTPUT);  
  pinMode(DisplayButton, INPUT);  
}

void loop()
{ 
  int buttonState = digitalRead(DisplayButton);
  if (buttonState == HIGH) 
  {
    if (lastButtonState == LOW)
    {
      ledState = 1;
      startTime = millis();
    }
  }
  lastButtonState = buttonState;
  if (ledState)
  {
    if (millis() - startTime <= interval)
    {
      digitalWrite(ledPin, HIGH);
    }
    else
    {
      digitalWrite(ledPin, LOW);
      ledState = 0;
    }
  }  
}

BulldogLowell:
try like this, for example, it will restart the timer if you press while lit…

Thanks a lot for this, its cleared a massive head ache i got from this. I’m trying to understand whats going on, the loop code is below with my interpretation of the code. Could you please let me know if what I wrote is correct?
thanks a million

void loop()
{ 
  int buttonState = digitalRead(DisplayButton);
  if (buttonState == HIGH) 
  {
    if (lastButtonState == LOW)           // lastButtonState starts as zero so this statement is true
    {
      ledState = 1;                    //turn ledState from 0 to 1
      startTime = millis();      //start timer
    }
  }
  lastButtonState = buttonState;       //lastButtonState is zero but buttonState is high so lastButtonState is now 1
  if (ledState)                                            //ledState is 1 now so this statement is true
  {
    if (millis() - startTime <= interval)  
 //Until the startTime reaches above the interval time the loop will choose this if statement rather than the else which turns off // the LED
    {
      digitalWrite(ledPin, HIGH);         //turns on the LED
    }
    else
    {
      digitalWrite(ledPin, LOW);              //turns off LED and resets the ledState
      ledState = 0;
    }
  }  
}

you pretty mush hav it, but to clarify this bit:

  if (buttonState == HIGH) 
  {
    if (lastButtonState == LOW)           // lastButtonState starts as zero so this statement is true

we are looking to capture the moment the button is pressed (buttonState == HIGH). That occurs when for some period at low (lastButtonState == LOW) changes all of a sudden to HIGH.

lastButtonState, while the button is depressed, will then be assigned a value of HIGH until the button is released, where it will then go LOW

I hope you understand, it is simpler than it sounds.

BulldogLowell: you pretty mush hav it, but to clarify this bit:

  if (buttonState == HIGH) 
  {
    if (lastButtonState == LOW)           // lastButtonState starts as zero so this statement is true

we are looking to capture the moment the button is pressed (buttonState == HIGH). That occurs when for some period at low (lastButtonState == LOW) changes all of a sudden to HIGH.

lastButtonState, while the button is depressed, will then be assigned a value of HIGH until the button is released, where it will then go LOW

I hope you understand, it is simpler than it sounds.

thanks a lot for the detailed explanation, this is really useful! :)

I think a simpler approach is only to change the state when the button is pressed. This code will extend the 3 secs every time the button is pressed. If you don't want that to happen a little extra code would be required.

byte ledON = 0;

void loop() {
   if (digitalRead(buttonPIn) == LOW) {
        ledON = 1;
        ledOnMillis = millis();
   }
   if (millis() - ledOnMillis >= 3000) {
          ledON = 0;
   }

   digitalWrite(ledPin, ledOn);
}

...R