Blinking light between "if-else if"

Dear all,

I'm new in arduino programming.

I want to use Arduino UNO board to turn ON/OFF and blinking a stacklight 3 colors (RED, AMBER, GREEN) accordant to 3 contact switches (for each color, S_FWD ---> RED, S_RWD ---> AMBER, S_MDO ---> GREEN).

My code is tested and works well when:

S_MDO button is pushed, GREEN light: OFF

During this moment:

a. S_FWD button is pushed, RED light: ON

b. S_RWD button is pushed, AMBER light: ON

I want to insert the code statement in case: if S_MDO button is latched, during the RED (or AMBER):ON, the RED (or AMBER), it should be blinking in that moment. And when S_MDO is pushed, blinking stops.

Could anyone please tell me how to do that ?

Thanks and very appreciates your helps.


const unsigned int RED   = A5;          // control RED stacklight   
const unsigned int AMBER = A4;          // control AMBER stacklight  
const unsigned int GREEN = A3;          // control GREEN stacklight   

const unsigned int FWD = 10;            // Forward SW (for RED light)
const unsigned int RWD = 11;            // Reward SW (for AMBER light)
const unsigned int MDO = 12;            // Door SW (for GREEN light)

int S_FWD, S_RWD, S_MDO;                // Buttons (with INPUT_PULLUP resistors)

void setup(){
    pinMode(RED,   OUTPUT);
    pinMode(AMBER, OUTPUT);
    pinMode(GREEN, OUTPUT);
    
    pinMode(FWD, INPUT_PULLUP);
    pinMode(RWD, INPUT_PULLUP);
    pinMode(MDO, INPUT_PULLUP);

    Sleep();                       // Outputs pins (A3, A4, A5) go to HIGH: Stack Lights turn OFF
}

void loop(){
    S_FWD = digitalRead(FWD);      // Forward limit switch 
    S_RWD = digitalRead(RWD);      // Reward limit switch 
    S_MDO = digitalRead(MDO);      // Main door detected switch 
        
   if (S_MDO == HIGH){      
      digitalWrite(GREEN, LOW);        // The door is opened, GREEN:ON, others lights turn OFF
      digitalWrite(RED, HIGH);
      digitalWrite(AMBER, HIGH);
      }  
    
   else if (S_MDO == LOW){             // During the door is closed, 
        digitalWrite(GREEN, HIGH);     // GREEN light turns OFF immediately and AMBER/RED light turns ON dependant on their limit SW positions.

        if (S_RWD == LOW){             // Reward limit SW touched (GND)
            digitalWrite(AMBER, LOW);  // AMBER:ON
            digitalWrite(RED, HIGH);   // RED:OFF
          
           [i] // TO DO: If Door opens during AMBER:ON ----> GREEN:ON immediately, AMBER flashing with A_Flashing() function
            // When the Door is closed, AMBER:ON, GREEN:OFF [/i]
            }
            
        else if (S_FWD == LOW){           // Forward limit SW touched (GND) ---> RED:ON, AMBER:OFF
            digitalWrite(RED, LOW);
            digitalWrite(AMBER, HIGH);

            [i]// TO DO: If Door opens during RED:ON ----> GREEN:ON immediately, RED flashing with R_Flasching() function
            // When the Door is closed, RED:ON, GREEN:OFF [/i]
            }
        }
    }

  
void Sleep(){                       // Set ALL stack lights OFF
    digitalWrite(RED, HIGH);
    digitalWrite(AMBER, HIGH);
    digitalWrite(GREEN, HIGH);
  } 


void A_Flashing(){
    digitalWrite(AMBER, HIGH);  // AMBER:OFF
    digitalWrite(RED, HIGH);
    delay (50);
    digitalWrite(AMBER, LOW);   // AMBER:ON
    digitalWrite(RED, HIGH);
    delay (50);
   } 
  
void R_Flashing(){
    digitalWrite(AMBER, HIGH);
    digitalWrite(RED, HIGH);     // RED:OFF
    delay (50);
    digitalWrite(AMBER, HIGH);
    digitalWrite(RED, LOW);      // RED:ON
    delay (50);
   }

I don't think you will be able to simply hack that code to achieve those changes. You need to use a state machine approach and you will not be able to use blocking code like delay() statements.
You have to identify and separate the states, the action and the transitions between the states.
The real world problem appears to be a door control system where you detect movement, open/close a door and use lights to indicate whether passage is permitted or not. But if you explain it more fully, it might be easier to identify the states, but it could be something like this:

States:
waiting_for_door_main_switch
Door_fully_open
Door_fully_closed
Door_opening
Door_closing
etc.

Actions:
Start_door_open
Start_door_close
Show_Red_Signal
Show_Green_signal
Show_Amber_Signal
Show_Blink_Amber_Signal
etc.

Then you can code like this (pseudocode)

if ( state == waiting_for_door_main_switch and door switch detected) {
Start_door_open
state = Door_opening
}
if (state == Door_opening {
Show_Red_Signal
}
etc.

Hello 6v6gt,

Thanks for reply.

It seems my code already in that structure as your suggestion.

If (sw-main-door is opened)

GREEN light: ON

If (sw-main-door is closed)

GREEN light: OFF

{

If (sw-RED is closed)

RED light: ON
AMBER light : OFF
(to do: if sw-main-door opens: flashing RED light.
If sw-main-door is closed, RED: ON, GREEN: OFF)

else if (sw-AMBER is closed

RED light: OFF
AMBER light: ON
(to do: if sw-main-door opens: flashing AMBER light.
If sw-main-door is closed, AMBER: ON, GREEN: OFF)

}

Do I have to define the StateButton (currentStateButton, LastStateButton,...) methods to flash the Light (RED/AMBER) if the sw-main-door reopens in the 2nd "if" condition ?

Best regards,
Viet5d
Viet5d

First, try to get the rules expressed more clearly. It is difficult to see what you are trying to do.

What do the buttons/switches represent ?
FWD: door forward limit switch. Closes when door fully open ? Is this your sw-RED ?
RWD: door reverse limit switch. Closes when door fully closed ? Is this your sw-AMBER ?
MDO: If door is shut, starts opening door ?

What do the leds represent:
Green: On when door fully opened, otherwise off ?
Red: flashes to indicate door is opening. On when door fully closed ?
Amber: flashes to indicate door is opening. On when door fully closed ?

Red and amber seem to run in parallel. What frequency flashing do you want? 1Hz ?

To flash a led, at 1 Hz you can do a trick like this in the loop() without using delay():

digitalWrite( AMBER, ( millis() % 1000 ) < 500 ) ) ; // flash amber 1Hz

Sorry for my poor English that makes you confuse. :frowning: Thanks for your patience.

  1. What do the buttons/switches represent ?:

The switch (S_MDO value) to detect the door open (==1)/close (==0, GND). When the door is closed, there are 2 limit switches (S_FWD and S_RWD) that are used to detect an object moving forward/reward.

  1. FWD: door forward limit switch. Closes when door fully open ? Is this your sw-RED ?

FWD: Object moving forward. In the code, that is the FWD pin#10 of arduino [S_FWD = digitalRead(FWD)].

Yes, when the door is closed (GREEN light:OFF), the object moves forward touching the limit switch (S_FWD), this switch is closed (connected to GND), the RED light: ON (until the object changes the direction, rewarding, touching S_RWD switch, the RED light: OFF, AMBER light: ON).

  1. RWD: door reverse limit switch. Closes when door fully closed ? Is this your sw-AMBER ?

(Similarly of point 2)

  1. MDO: If door is shut, starts opening door ?

Im not really understand this question, but the object can move FWD/RWD ONLY when the door is closed.

  1. What do the leds represent:

a. Green: On when door fully opened, otherwise off ?: YES (the way as safety for an object moving inside the door).

b. Red: flashes to indicate door is opening. On when door fully closed ?: YES, but RED light flashes when it was turned ON before (door already closed in the beginning) and if suddenly the door opens. If the door is closed later, before the object touches the S_RWD switch, the RED light stops flashing and turns ON.

c. Amber: flashes to indicate door is opening. On when door fully closed ?: Similarly to point 5b.

  1. Red and amber seem to run in parallel. What frequency flashing do you want? 1Hz ?: Flashing frequency is not important. Thanks for excellent trick.

Thanks so much for support,

OK. It is all clear now. You called the switches limit switches which implied it was sliding door type control. The switches are actually detectors for approaching objects.
It was not a trivial exercise and it now uses a state machine type solution. If you have problems, use Serial.print statements to debug it.

Try this:

const unsigned int RED   = A5;          // control RED stacklight
const unsigned int AMBER = A4;          // control AMBER stacklight
const unsigned int GREEN = A3;          // control GREEN stacklight

const unsigned int FWD = 10;            // Forward SW (for RED light)
const unsigned int RWD = 11;            // Reward SW (for AMBER light)
const unsigned int MDO = 12;            // Door SW (for GREEN light)

int S_FWD, S_RWD, S_MDO;                // Buttons (with INPUT_PULLUP resistors)

enum indState_t : int {
  // state of yellow/red leds
  AMBER_ON_WAITING_OPEN = 1 ,
  AMBER_FLASH = 2 ,
  AMBER_ON = 3 ,
  RED_ON_WAITING_OPEN = 4 ,
  RED_FLASH = 5 ,
  RED_ON = 6 ,
  NONE = 7
} ;

indState_t indState ;

bool S_MDO_last = HIGH ;  //door closed

void setup() {
  Serial.begin(115200) ;
  pinMode(RED,   OUTPUT);
  pinMode(AMBER, OUTPUT);
  pinMode(GREEN, OUTPUT);

  pinMode(FWD, INPUT_PULLUP);
  pinMode(RWD, INPUT_PULLUP);
  pinMode(MDO, INPUT_PULLUP);

  Sleep();                       // Outputs pins (A3, A4, A5) go to HIGH: Stack Lights turn OFF
}

void loop() {
  // read switches
  S_FWD = digitalRead(FWD);      // Forward limit switch
  S_RWD = digitalRead(RWD);      // Reward limit switch
  S_MDO = digitalRead(MDO);      // Main door detected switch

  // handle green led
  if (S_MDO == HIGH) {
    digitalWrite(GREEN, LOW);        // The door is opened, GREEN:ON, others lights turn OFF
  }
  else {
    digitalWrite(GREEN, HIGH);    // Green off
  };

  // handle red/amber leds
  switch ( indState ) {
    case NONE:
      digitalWrite(RED, HIGH);
      digitalWrite(AMBER, HIGH);
      break ;
    case AMBER_ON_WAITING_OPEN:
    case AMBER_ON:
      digitalWrite(RED, HIGH);
      digitalWrite(AMBER, LOW);  //ON
      break ;
    case AMBER_FLASH:
      A_Flashing();
      break ;
    case RED_ON_WAITING_OPEN:
    case RED_ON:
      digitalWrite(RED, LOW); //ON
      digitalWrite(AMBER, HIGH);
      break ;
    case RED_FLASH:
      R_Flashing();
      break ;
  }

  // set states
  if (S_RWD == LOW)  {
    indState = AMBER_ON_WAITING_OPEN  ;
  }
  else if (S_FWD == LOW)  {
    indState = RED_ON_WAITING_OPEN  ;
  }
  if ( S_MDO_last != S_MDO ) {
    if (S_MDO == HIGH && S_MDO_last == LOW ) {  // door just opened
      if ( indState == AMBER_ON_WAITING_OPEN ) {
        indState = AMBER_FLASH ;
      }
      else if ( indState == RED_ON_WAITING_OPEN ) {
        indState = RED_FLASH ;
      }
      else indState = NONE ;
    }
    else if (S_MDO == LOW && S_MDO_last == HIGH ) {  // door just closed
      if ( indState == AMBER_FLASH  ) {
        indState = AMBER_ON ;
      }
      else if ( indState == RED_FLASH ) {
        indState = RED_ON ;
      }
    }
    S_MDO_last = S_MDO ;
  }
  delay(50) ; // debounce buttons (poor)
}

void Sleep() {                      // Set ALL stack lights OFF
  digitalWrite(RED, HIGH);
  digitalWrite(AMBER, HIGH);
  digitalWrite(GREEN, HIGH);
}


void A_Flashing() {
  digitalWrite(AMBER, HIGH);  // AMBER:OFF
  digitalWrite(RED, HIGH);
  delay (50);
  digitalWrite(AMBER, LOW);   // AMBER:ON
  digitalWrite(RED, HIGH);
  delay (50);
}

void R_Flashing() {
  digitalWrite(AMBER, HIGH);
  digitalWrite(RED, HIGH);     // RED:OFF
  delay (50);
  digitalWrite(AMBER, HIGH);
  digitalWrite(RED, LOW);      // RED:ON
  delay (50);
}

Hello 6v6gt,

Your code works exactly what I want to do.

I'm very appreciated your precious time and your patience... with my poor English.

This is my first post, so there are some difficulties for me in explanation an idea. It will be better next time...

Again, thank you so much and wish you all the best in life.

Viet5d