Sequential tail lights controlled with IR remote

I'm working on a project for school where I am simulating sequential tail lights with a breadboard and LEDs. I'm using an IR remote to control the functions of the lights. So far I am able to control the lights that only need to turn on and off. The issue I'm having is with the sequential turn signals. When I press the "turn signal" it creates a while loop to keep the turn signal going, but it gets stuck inside of the loop. I need help figuring out how to stop the loop and turn the lights off when I press the same button or a separate "off" button. I am also not able to control any other lights when it gets stuck inside of this loop. So for example when the turn signals are on maybe the brake lights need to turn on and off.

Code

#include <IRremote.h> //including infrared remote header file

int RECV_PIN = 53; // the pin where you connect the output pin of IR sensor
IRrecv irrecv(RECV_PIN);
decode_results results;

int Red1 = 13;
int Red2 = 10;
int Red3 = 7;
int Red4 = 4;
int Red5 = 16;
int Red6 = 19;
int Red7 = 22;
int Red8 = 25;
int Red9 = 11;
int Red10 = 8;
int Red11 = 5;
int Red12 = 2;
int Red13 = 17;
int Red14 = 20;
int Red15 = 23;
int Red16 = 26;
int Yellow1 = 12;
int Yellow2 = 9;
int Yellow3 = 6;
int Yellow4 = 3;
int Yellow5 = 28;
int Yellow6 = 15;
int Yellow7 = 18;
int Yellow8 = 21;
int Yellow9 = 24;
int Yellow10 = 27;
int White1 = 29;
int White2 = 14;

int LedOn = {0,0,0,0,0};

#define ButtonR 0XFFFFFFFF
#define Button0 0xFF6897
#define Button1 0xFF30CF
#define Button2 0xFF18E7
#define Button3 0xFF7A85
#define Button4 0xFF10EF
#define Button5 0xFF38C7
#define Button6 0xFF5AA5
#define Button7 0xFF42BD
#define Button8 0xFF4AB5
#define Button9 0xFF52AD
#define ButtonP 0xFFA25D
#define ButtonPrev 0xFF22DD
#define ButtonFwd 0xFFC23D
#define ButtonPlay 0xFF02FD
#define ButtonVol_Up 0xFF629D
#define ButtonVol_D 0xFFA857
#define ButtonDown 0xFFE01F
#define ButtonUp 0xFF906F
#define ButtonEQ 0xFF9867

void setup()
{
Serial.begin(9600);
irrecv.enableIRIn();
pinMode (Red1, OUTPUT);
pinMode (Red2, OUTPUT);
pinMode (Red3, OUTPUT);
pinMode (Red4, OUTPUT);
pinMode (Red5, OUTPUT);
pinMode (Red6, OUTPUT);
pinMode (Red7, OUTPUT);
pinMode (Red8, OUTPUT);
pinMode (Red9, OUTPUT);
pinMode (Red10, OUTPUT);
pinMode (Red11, OUTPUT);
pinMode (Red12, OUTPUT);
pinMode (Red13, OUTPUT);
pinMode (Red14, OUTPUT);
pinMode (Red15, OUTPUT);
pinMode (Red16, OUTPUT);
pinMode (Yellow1, OUTPUT);
pinMode (Yellow2, OUTPUT);
pinMode (Yellow3, OUTPUT);
pinMode (Yellow4, OUTPUT);
pinMode (Yellow5, OUTPUT);
pinMode (Yellow6, OUTPUT);
pinMode (Yellow7, OUTPUT);
pinMode (Yellow8, OUTPUT);
pinMode (Yellow9, OUTPUT);
pinMode (Yellow10, OUTPUT);
pinMode (White1, OUTPUT);
pinMode (White2, OUTPUT);
}

void loop()
{
if (irrecv.decode(&results)){
int value = results.value;
irrecv.resume();

switch(results.value) {
      
      // Brakes On/Off
      case ButtonVol_Up : 
        if (LedOn[1] == 1) {
          digitalWrite(Red1, LOW); 
          digitalWrite(Red2, LOW);
          digitalWrite(Red3, LOW);
          digitalWrite(Red4, LOW);
          digitalWrite(Red5, LOW);
          digitalWrite(Red6, LOW);
          digitalWrite(Red7, LOW);
          digitalWrite(Red8, LOW);
        LedOn[1] = 0;
        } else {
            digitalWrite(Red1, HIGH); 
            digitalWrite(Red2, HIGH);
            digitalWrite(Red3, HIGH);
            digitalWrite(Red4, HIGH);
            digitalWrite(Red5, HIGH);
            digitalWrite(Red6, HIGH);
            digitalWrite(Red7, HIGH);
            digitalWrite(Red8, HIGH);
            LedOn[1] = 1;
        }
        break;
     
      // Running Lights On/Off
      case ButtonVol_D : 
        if (LedOn[2] == 1) {
          digitalWrite(Red9, LOW); 
          digitalWrite(Red10, LOW);
          digitalWrite(Red11, LOW);
          digitalWrite(Red12, LOW);
          digitalWrite(Red13, LOW);
          digitalWrite(Red14, LOW);
          digitalWrite(Red15, LOW);
          digitalWrite(Red16, LOW);
          LedOn[2] = 0;
        } else {
            digitalWrite(Red9, HIGH); 
            digitalWrite(Red10, HIGH);
            digitalWrite(Red11, HIGH);
            digitalWrite(Red12, HIGH);
            digitalWrite(Red13, HIGH);
            digitalWrite(Red14, HIGH);
            digitalWrite(Red15, HIGH);
            digitalWrite(Red16, HIGH);
            LedOn[2] = 1;
        }
        break;

      // Left Turn Signal On
      case ButtonPrev :
        while (results.value != ButtonDown){
           digitalWrite(Yellow5, HIGH);
           delay(300);
           digitalWrite(Yellow4, HIGH);
           delay(300);
           digitalWrite(Yellow3, HIGH);
           delay(300);
           digitalWrite(Yellow2, HIGH);
           delay(300);
           digitalWrite(Yellow1, HIGH);
           delay(300);
           digitalWrite(Yellow5, LOW);
           delay(300);
           digitalWrite(Yellow4, LOW);
           delay(300);
           digitalWrite(Yellow3, LOW);
           delay(300);
           digitalWrite(Yellow2, LOW);
           delay(300);
           digitalWrite(Yellow1, LOW);
           }
           break;
      
      // Left Turn Signal Off
      case ButtonDown :
        digitalWrite(Yellow1, LOW);
        digitalWrite(Yellow2, LOW);
        digitalWrite(Yellow3, LOW);
        digitalWrite(Yellow4, LOW);
        digitalWrite(Yellow5, LOW);
        break;
        
}
}

}

Welcome

loop() is already a while loop, you don't really need another one, and with a little thinking, you will be able to do non-blocking code.

But, your problem is that results.value is not updated in the while loop, so its value cannot be ButtonDown, since it is ButtonPrev :slight_smile:

Too much code.
Not enough code tags.

Is there a way to break the while loop by pressing another button. Because if there is I don't know how to set that up. A counter variable won't work, since it will just go until the variable reaches a certain number. I need the loop to stop exactly when I say with the push of a button.

A suggestion: build an FSM.  You can use one similar to the one described in Timer counter state change toggle FSM - all at once.

To this basic structure you can add states and outputs as you wish.  Create a boolean variable controlled by your start and stop inputs.  Use this boolean in an if/else such that when the boolean is false the lights are off.  Else, when it's true enable the FSM to sequence through the LEDs.  Do not use delay() for this!  millis() timing allows the FSM to not get bogged down in a delay() so the inputs can be checked each pass through the code (normally thousands of times per second) allowing an instant response to a stop command.

A further suggestion: Don't try to eat the whole elephant in one sitting.  Start with just making the FSM control the LEDs then add the switches and on/off functions.

If you think about it, this is very similar to a traffic light sequence.  You may find some inspiration doing a site search on traffic lights.

take a look at this


const byte pinsLed [] = { 10, 11, 12, 13 };

enum { Off = HIGH, On = LOW };

enum { None, Flash, Left, Right };
int mode = None;

unsigned idx;

// -----------------------------------------------------------------------------
void
ledsOnOff (
    byte  state)
{
    for (unsigned n=0; n < sizeof(pinsLed); n++)
        digitalWrite (pinsLed [n], state);
}

// -------------------------------------
void
ledsFlash (void)
{
    for (unsigned n=0; n < sizeof(pinsLed); n++)
        digitalWrite (pinsLed [n], ! digitalRead (pinsLed [n]));
}

// -------------------------------------
void
ledsSeq (
    int  dir )
{
    if (Left == dir) {
        for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
            if (n <= idx)
                digitalWrite (pinsLed [n], On);
            else
                digitalWrite (pinsLed [n], Off);
        }

        if (sizeof(pinsLed) <= ++idx)
            idx = 0;
    }

    else if (Right == dir) {
        for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
            if (n >= idx)
                digitalWrite (pinsLed [n], On);
            else
                digitalWrite (pinsLed [n], Off);
        }

        if (0 == idx--)
            idx = sizeof(pinsLed)-1;
    }

    Serial.print   (sizeof(pinsLed));
    Serial.print   ("  ");
    Serial.println (idx);
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    if (Serial.available ())  {
        char c = Serial.read ();
        switch (c)  {
        case '0':
            ledsOnOff (Off);
            mode = None;
            break;

        case '1':
            ledsOnOff (On);
            mode = None;
            break;

        case 'f':
            mode = Flash;
            break;

        case 'l':
            mode = Left;
            break;

        case 'r':
            mode = Right;
            break;
        }
    }

    static unsigned long msecLst;
           unsigned long msec = millis ();

#define Period   250
    if ( (msec - msecLst) > Period)  {
        msecLst = msec;

        switch (mode)  {
        case Right:
        case Left:
            ledsSeq (mode);
            break;

        case Flash:
            ledsFlash ();
            break;
        }
    }
}

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

    for (unsigned n=0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}