How to make an led blink before turning off an led?

I have wrote a code in which an LED switches on after a button press and it will switch off after a given delay time but around a second before switching off i want it to blink as a warning that it is going to switch off, can you please help me modify the code given below in order for it to do this. Thank you for your help.

const int ledPin1 =  6;
const int ledPin2 = 5;
const int ledPin3 = 3;
const int buttonPin1 = 13;
const int buttonPin2 = 12;
const int buttonPin3 = 11;

int programState1 = 0;
int programState2 = 0;
int programState3 = 0;
int ledOnTime1 = 5000;
int ledOnTime2 = 3000;
int ledOnTime3 = 3000;
int delayValue1 = 200;
int delayValue2 = 200;
int delayValue3 = 200;

int buttonState1;
int buttonState2;
int buttonState3;
long buttonMillis1 = 0;
long buttonMillis2 = 0;
long buttonMillis3 = 0;
const long intervalButton1 = 20;
const long intervalButton2 = 20;
const long intervalButton3 = 20;
long ledMillis1 = 0;
long ledMillis2 = 0;
long ledMillis3 = 0;
const long intervalLed1 = ledOnTime1;
const long intervalLed2 = ledOnTime2;
const long intervalLed3 = ledOnTime3;
bool ledState1 = false;
bool ledState2 = false;
bool ledState3 = false;

void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);   
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);    
  digitalWrite(buttonPin1, HIGH);
  digitalWrite(buttonPin2, HIGH);
  digitalWrite(buttonPin3, HIGH);
}

void loop()
{
  unsigned long currentMillis = millis();
  buttonState1 = digitalRead(buttonPin1);
 
  if (buttonState1 == LOW && programState1 == 0) {
    buttonMillis1 = currentMillis;
    programState1 = 1;
  }
  else if (programState1 == 1 && buttonState1 == HIGH) {
        programState1 = 0; //reset
  }
  if(currentMillis - buttonMillis1 > intervalButton1 && programState1 == 1) {
    programState1 = 2;
    ledMillis1 = currentMillis;

    digitalWrite(ledPin1, HIGH);
    ledState1 = true;
  }

  if(currentMillis - ledMillis1 > intervalLed1 && programState1 == 2) {
    programState1 = 0;

    digitalWrite(ledPin1, LOW);
    ledState1 = false;
  }
  
  buttonState2 = digitalRead(buttonPin2);
  
  if (buttonState2 == LOW && programState2 == 0) {
    buttonMillis2 = currentMillis;
    programState2 = 1;
  }
  else if (programState2 == 1 && buttonState2 == HIGH) {
        programState2 = 0; //reset
  }
  if(currentMillis - buttonMillis2 > intervalButton2 && programState2 == 1) {
    programState2 = 2;
    ledMillis2 = currentMillis;

    digitalWrite(ledPin2, HIGH);
    ledState2 = true;
  }

  if(currentMillis - ledMillis2 > intervalLed2 && programState2 == 2) {
    programState2 = 0;

    digitalWrite(ledPin2, LOW);
    ledState2 = false;
  }

  buttonState3 = digitalRead(buttonPin3);
  
  if (buttonState3 == LOW && programState3 == 0) {
    buttonMillis3 = currentMillis;
    programState3 = 1;
  }
  else if (programState3 == 1 && buttonState3 == HIGH) {
        programState3 = 0; //reset
  }
  if(currentMillis - buttonMillis3 > intervalButton3 && programState3 == 1) {
    programState3 = 2;
    ledMillis3 = currentMillis;

    digitalWrite(ledPin3, HIGH);
    ledState3 = true;
  }

  if(currentMillis - ledMillis3 > intervalLed3 && programState3 == 2) {
    programState3 = 0;

    digitalWrite(ledPin3, LOW);
    ledState3 = false;
  }
}

something like this you mean? did it for 1 Led. I'll let you repeat the code for the other 2! :wink:

const int ledPin1 =  6;
const int ledPin2 = 5;
const int ledPin3 = 3;
const int buttonPin1 = 13;
const int buttonPin2 = 12;
const int buttonPin3 = 11;

int ledOnTime1 = 4000;
int LedPendingOff1 = 1000;
int LedFlashing1 = 200;
long intervalLed1 = 0;
int programState1 = 0; //0: OFF, 1: ON, 2:Pending OFF(flashing). Total ON time = ledOnTime1 + LedPendingOff1
int buttonState1;

int buttonState2;
int buttonState3;
long buttonMillis1 = 0;
long buttonMillis2 = 0;
long buttonMillis3 = 0;
const long intervalButton1 = 20;
const long intervalButton2 = 20;
const long intervalButton3 = 20;
long ledMillis1 = 0;
long ledMillis2 = 0;
long ledMillis3 = 0;

//const long intervalLed2 = ledOnTime2;
//const long intervalLed3 = ledOnTime3;
bool ledState1 = false;
bool ledState2 = false;
bool ledState3 = false;

void setup() {
  pinMode(ledPin1, OUTPUT); 
  pinMode(buttonPin1, INPUT_PULLUP);

}

void loop()
{
  unsigned long currentMillis = millis();
  buttonState1 = digitalRead(buttonPin1);
  
  if (buttonState1 == LOW) {
    buttonMillis1 = currentMillis;
    digitalWrite(ledPin1, HIGH);
    programState1 = 1;
    return;
  }

  switch(programState1){
    case 0:
      digitalWrite(ledPin1, LOW);
    break;

    case 1:
      digitalWrite(ledPin1, HIGH);
      if(millis()-buttonMillis1 > ledOnTime1){
        buttonMillis1 = currentMillis;
        intervalLed1 = 0;
        programState1 = 2;
      }
    break;

    case 2:
      if(millis()-buttonMillis1 > LedFlashing1){
        digitalWrite(ledPin1, !digitalRead(ledPin1));
        intervalLed1 += LedFlashing1;
        buttonMillis1 = currentMillis;
      }
      if(intervalLed1>=LedPendingOff1) programState1 = 0;
    break;
  }
  
}

hope that helps...

lot of code

consider

#define LedTime1   3000
#define LedTime2   3300
#define LedTime3   4000

enum { On = LOW, Off = HIGH };

byte ledPins [] = { 11, 12, 13 };
byte butPins [] = { A1, A2, A3 };

#define N  sizeof(ledPins)

byte           butSt   [N];
unsigned long ledMsec [N] = {};

// -----------------------------------------------------------------------------
void setup()
{
    Serial.begin(9600);

    for (unsigned n = 0; n < N; n++)  {
        digitalWrite (ledPins[n], Off);
        pinMode (ledPins[n], OUTPUT);

        pinMode (butPins [n], INPUT_PULLUP);
        butSt [n] = digitalRead (butPins [n]);
    }
}

// -----------------------------------------------------------------------------
void loop()
{
    unsigned long msec = millis ();

    // check for button presses
    for (unsigned n = 0; n < N; n++)  {
        byte but = digitalRead (butPins [n]);
        if (butSt [n] != but)  {
            butSt [n] = but;
            if (On == but)  {
                digitalWrite (ledPins[n], On);
                ledMsec [n] = msec;
            }
        }
    }

    // process LEDs
    for (unsigned n = 0; n < N; n++)  {
        if (0 == ledMsec [n])
            continue;

        // longest time first
        if (msec - ledMsec [n] >= LedTime3)  {
            digitalWrite (ledPins[n], Off);
            ledMsec [n] = 0;
        }

        else if (msec - ledMsec [n] >= LedTime2)
            digitalWrite (ledPins[n], On);

        else if (msec - ledMsec [n] >= LedTime1)
            digitalWrite (ledPins[n], Off);
    }
}

arduino12_5, your sketch is some kind of Finite State Machine: The Finite State Machine | Majenko Technologies.
If you are going to use that, then do it right as sherzaad showed.
When the behaviour of the buttons and the leds is the same, then it is possible to write just one Finite State Machine and use array's to do all the buttons and all the leds. Also the 'state' and the 'previousMillis' should be an array.

With a Finite State Machine you can add things and change things easy. If you want to blink and fade the leds or increase the blinking, all of that is possible. Example of millis() with Finite State Machine: millis_and_finite_state_machine.ino

gcjr, the leds blink only once ? You use 'On' and 'Off' for the buttons and the leds. That means the code is not suited when both the buttons and the leds are connected to GND.

arduino12_5, take a pick, we help you to make either of them work for you. I can think of a few more variations, but they are not better. There are libraries that would make this easier, but I prefer that you use millis() in its basic form to learn how millis() can be used best. Please always use 'unsigned long' when doing something with millis().

Koepel:
gcjr, the leds blink only once ?

without being more precise, that's what interpreted blink to mean. did he mean blinking?

Koepel:
You use 'On' and 'Off' for the buttons and the leds. That means the code is not suited when both the buttons and the leds are connected to GND.

yes. i defined what On and Off mean for my case. instead of needing to replace the use of LOW/HIGH throughout the code for different hardware, there is just one place to change the enum values.

if the polarity of led and button are different, ButOn/ButOff and LedOn/LedOff make sense

i tried to show a simpler and cleaner approach for writing the code. i assume this is learning exercise for the OP and i think seeing well written code is the best way to learn to write well written code.

@sherzaad do i have to add ledFlashing 2 and intervalLed2 too?

arduino12_5:
@sherzaad do i have to add ledFlashing 2 and intervalLed2 too?

That is up to you! :wink:

if you require different flashing and interval timings then yes!

if not, then you just use the same ledFlashing1 and intervalLed1 variables for the other leds/buttons