Adding a millis timer to individual LED's in CASE loop

I am working on a esp32 project where I am trying to light up a series of LED's based on a button press. I got most of it working But I am having trouble getting each of the LED's to turn off after 2 seconds.

Rules are:

  1. If the button is pressed "Switch LED1 ON for 2 seconds"

  2. If the button is Pressed again while LED1 is still on then "Switch LED2 ON for 2 seconds and keep LED1 ON as long as LED2 is on"

  3. If the button is Pressed again while LED-02 is on "Switch LED3 ON for 2 seconds and Keep LED1 and LED2 ON for as long as LED3 is on"

4, Any Button press resets the timer for all 3 LED's

  1. If no new button presses are received within 2 seconds then clear all LED's and wait for new button press

Here is my code so far. All help will be appreciated. Thank you.


const byte buttonPin = 7;  // Button Pin
const byte led1Pin = 2;    // LED1  Pin
const byte led2Pin = 3;    // LED2  Pin
const byte led3Pin = 4;    // LED3  Pin
const byte nodesNum = 2;
unsigned long onPeriod = 2500;
int led1State = LOW;
int led2State = LOW;
int led3State = LOW;
byte hasState = 0;

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

  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
}

void loop() {
  checkActivation();
}

void checkActivation() {
  boolean BTState = digitalRead(buttonPin);  // Current Button State
  static boolean prevBTState = HIGH;         // Previous Button State
  static unsigned long timer = 0;
  unsigned long interval = 20;
  if (millis() - timer >= interval) {
    timer = millis();

    BTState = digitalRead(buttonPin);  // Get Button Press
    if (BTState != prevBTState)        // Compare Button State
    {
      if (BTState == LOW)  // If State Change Add to counter ++
      {

        hasState++;  // Check Current state is LOW - State Changed from off to on:
        if (hasState > nodesNum) {
          hasState = 0;
        }
        switch (hasState) {
          case 0:
            digitalWrite(led3Pin, HIGH);
            Serial.println("LED3 On");

            break;
          case 1:
            digitalWrite(led1Pin, HIGH);
            Serial.println("LED1 On");
            break;
          case 2:
            digitalWrite(led2Pin, HIGH);
            Serial.println("LED2 On");
            break;
        }
      }
      prevBTState = BTState;  // Save Button State
    }
  }
}

what should happen if the button is pressed and LED1 is off but LED2 is still on

  • Bad habits, boolean is true, false :roll_eyes:
1 Like

So 2 seconds after the LAST button press - everything should reset to OFF

While LED2 is on it should keep LED 1 on.
Same goes for - While LED 3 is on it should keep LED 1 and 2 on.

I am pretty new to coding -
Thank you for the tip.. I will change them to true false

Could the first button pressed also be the last button pressed? Can buttons be pressed 100 times?

  • Use type byte

  • Also, always show us a schematic and good images of actual wiring

Yes, If no new press is received within 2 seconds then it stops and waits.

Okay. Every button sets the timer to 2000ms.

so if LED2 is turned on, don't turn LED1 off after 2 seconds.

also new to specifying requirements. requirements often take the square (!!) of the man-hour/day/week/months to actually do the coding

Correct - Triggering a Button press resets the timer for all LED states.

I will update the requirements to be more concise.

more precise .... "complete, correct and unambiguous"

Read your description, looked at the top of your sketch for the pin #s and typed this out, which seems to match your description (debounce is quick & dirty):

const unsigned buttonPin = 7;
const unsigned led1Pin = 2;
const unsigned led2Pin = 3;
const unsigned led3Pin = 4;

typedef enum {
   ALL_LEDS_OFF,
   LED1_ON,
   LED1_LED2_ON,
   LED1_LED2_LED3_ON
} LedState;

LedState ledState = ALL_LEDS_OFF;
unsigned long ledOnTime = 2000;
unsigned long ledWasTurnedOnTime = 0;

bool buttonPressed() {
   byte currentbuttonState;       // HIGH for inactive, LOW for active
   static byte lastButtonState = HIGH;
   static byte buttonState = HIGH;
   static unsigned long changeDetected = 0;
   const unsigned buttonDebounceDelay = 50;   // 50ms debounce
   bool result = false;
      
   currentbuttonState = digitalRead(buttonPin);

   if( currentbuttonState != lastButtonState ) {
      changeDetected = millis();
   }

   if( changeDetected && millis() - changeDetected > buttonDebounceDelay ) {
      if( currentbuttonState != buttonState ) {
         buttonState = currentbuttonState;
         // buttonPressed is true when buttonPin is low and debounced
         result = buttonState == LOW;
       }
       changeDetected = 0;
   }
   lastButtonState = currentbuttonState;
   
   return result;
}

void setup(void) {
   pinMode(buttonPin, INPUT_PULLUP);
   pinMode(led1Pin, OUTPUT);
   pinMode(led2Pin, OUTPUT);
   pinMode(led3Pin, OUTPUT);
}

void loop(void) {
   switch( ledState ) {
      
      case ALL_LEDS_OFF:
         if( buttonPressed() ) {
            digitalWrite(led1Pin, HIGH);
            ledWasTurnedOnTime = millis();
            ledState = LED1_ON;
         }
         break;
         
      case LED1_ON:
         if( millis() - ledWasTurnedOnTime > ledOnTime ) {
            digitalWrite(led1Pin, LOW);
            ledState = ALL_LEDS_OFF;
         } else if( buttonPressed() ) {
            digitalWrite(led2Pin, HIGH);
            ledWasTurnedOnTime = millis();
            ledState = LED1_LED2_ON;
         }
         break;
            
      case LED1_LED2_ON:
         if( millis() - ledWasTurnedOnTime > ledOnTime ) {
            digitalWrite(led1Pin, LOW);
            digitalWrite(led2Pin, LOW);
            ledState = ALL_LEDS_OFF;
         } else if( buttonPressed() ) {
            digitalWrite(led3Pin, HIGH);
            ledWasTurnedOnTime = millis();
            ledState = LED1_LED2_LED3_ON;
         }
         break;
            
      case LED1_LED2_LED3_ON:
         if( millis() - ledWasTurnedOnTime > ledOnTime ) {
            digitalWrite(led1Pin, LOW);
            digitalWrite(led2Pin, LOW);
            digitalWrite(led3Pin, LOW);
            ledState = ALL_LEDS_OFF;
         } else if( buttonPressed() ) {
            ledWasTurnedOnTime = millis();
         }
         break;
   }
}
1 Like

Thank you for this. Never even thought of doing it this way.

1 Like

keep it simple

const byte PinBut     = A1;
      byte butState;

const byte PinLeds [] = { 10, 11, 12 };
      int  Nled       = sizeof(PinLeds);

enum { Off = HIGH, On = LOW };

int  idx;
bool tmr;

const unsigned long MsecPeriod = 2000;
      unsigned long msec0;

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

    if (tmr && msec - msec0 >= MsecPeriod)  {
        idx = 0;
        tmr = false;
        for (int n = 0; n < Nled; n++)
            digitalWrite (PinLeds [n], Off);
        Serial.println ("reset");
    }

    byte but = digitalRead (PinBut);
    if (butState != but)  {
        butState  = but;
        delay (20);                     // debounce

        if (LOW == but && idx < Nled)  {
            digitalWrite (PinLeds [idx++], On);
            msec0 = msec;
            tmr   = true;
            Serial.println (idx);
        }
    }
}

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

    pinMode (PinBut, INPUT_PULLUP);
    butState = digitalRead (PinBut);

    for (int n = 0; n < Nled; n++)  {
        pinMode      (PinLeds [n], OUTPUT);
        digitalWrite (PinLeds [n], Off);
    }
}
1 Like

No problem. Literally just pounded it out. Updated the buttonPressed routine to get rid of the delay; must stop now! :slight_smile:

Thank you for this as well. I am spending some time going through it to understand it better. I need to incorporate this portion into a larger sketch I am working on that uses a lora signal to trigger it.

yes! try to undestand it

  • Another iteration. :nerd_face:
//================================================^================================================
// https://forum.arduino.cc/t/adding-a-millis-timer-to-individual-leds-in-case-loop/1307035
//
#define LEDon              HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff             LOW

#define PRESSED            LOW    //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED           HIGH

#define CLOSED             LOW    //+5V---[Internal 50k]---PIN---[Switch]---GND
#define OPENED             HIGH

#define ENABLED            true
#define DISABLED           false


const byte led1Pin       = 2;    // LED1  Pin
const byte led2Pin       = 3;    // LED2  Pin
const byte led3Pin       = 4;    // LED3  Pin

const byte buttonPin     = 7;    // Button Pin LOW = pushed
const byte heartbeatLED  = 13;

const byte nodesNum      = 2;

bool LEDonFlag           = DISABLED;

byte lastButtonPin       = RELEASED;

byte hasState            = 0;

unsigned long heartbeatTime;
unsigned long switchTime;
unsigned long LEDsOFFTime;


//                                           s e t u p ( )
//================================================^================================================
void setup()
{
  Serial.begin(9600);

  pinMode(buttonPin, INPUT_PULLUP);

  digitalWrite(led1Pin, LEDoff);
  pinMode(led1Pin, OUTPUT);
  digitalWrite(led2Pin, LEDoff);
  pinMode(led2Pin, OUTPUT);
  digitalWrite(led3Pin, LEDoff);
  pinMode(led3Pin, OUTPUT);

  pinMode(heartbeatLED, OUTPUT);

} //END of   setup()


//                                           l o o p ( )
//================================================^================================================
void loop()
{
  //========================================================================  T I M E R  heartbeatLED
  //is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= 250ul)
  {
    //restart this TIMER
    heartbeatTime = millis();

    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }

  //========================================================================  T I M E R  switches
  //is it time to check our switches ?
  if (millis() - switchTime >= 50ul)
  {
    //restart TIMER
    switchTime = millis();

    checkSwitches();
  }

  //========================================================================  T I M E R  LEDsOFF
  //is it time to turn OFF LEDs ?
  if (LEDonFlag == ENABLED && millis() - LEDsOFFTime >= 2000ul)
  {
    //we are finished with tihis TIMER
    LEDonFlag = DISABLED;

    //get ready for the next sequence
    hasState = 0;

    digitalWrite(led1Pin, LEDoff);
    digitalWrite(led2Pin, LEDoff);
    digitalWrite(led3Pin, LEDoff);
  }

} //END of   loop()


//                                   c h e c k S w i t c h e s ( )
//================================================^================================================
//
void checkSwitches()
{
  byte pinState;

  //========================================================================  buttonPin
  pinState = digitalRead(buttonPin);

  //===================================
  //has this switch changed state ?
  if (lastButtonPin != pinState)
  {
    //update to this new state
    lastButtonPin = pinState;

    //==========================
    //did this switch go pressed/closed ?
    if (pinState == PRESSED)
    {
      //======================
      switch (hasState)
      {
        //==============
        case 0:
          LEDonFlag = ENABLED;

          //restart TIMER
          LEDsOFFTime = millis();

          digitalWrite(led1Pin, LEDon);

          Serial.println("LED1 On");

          break;

        //==============
        case 1:
          LEDonFlag = ENABLED;

          //restart TIMER
          LEDsOFFTime = millis();

          digitalWrite(led2Pin, HIGH);
          Serial.println("LED2 On");

          break;

        //==============
        case 2:
          LEDonFlag = ENABLED;

          //restart TIMER
          LEDsOFFTime = millis();

          digitalWrite(led3Pin, HIGH);
          Serial.println("LED3 On");

          break;
      }
      
      hasState++;

      //we only have 3 machine states  0, 1, 2
      if (hasState > nodesNum)
      {
        hasState = 0;
      }
      
    }

  } //END of mySwitch1.pin

  //========================================================================  Next Switch

} //END of   checkSwitches()


//================================================^================================================

//
1 Like

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