Can i somehow 'switch' loops using an IR Remote?

Hello, For school we are working with Arduino. I have little to no experience coding with Arduino, but so far i am enjoying it.

For the project we are doing, we need to build a traffic light. I want to have diffrent modes for the traffic lights, i want to implement diffrent modes, and can switch to with a remote controller.

Right now, i have everything coded out, but I cant switch what mode im on. it just runs it as one continuous loop.

my end goal is for this project to have diffrent loops i can switch to, and have them stay at that loop untill i push a diffrent button on my remote. Right now, i can switch to diffrent parts of the loop, but it will just continue from that point forward in the loop. It isn't staying on the part of loop i want it to run.

my code is as following:

[code]
#include <IRremote.h>
// variables
int GREENNS = 2;
int GREENEW = 5;
int YELLOWNS = 3;
int YELLOWEW = 6;
int REDNS = 4;
int REDEW = 7;
int DELAY = 2000;
int DELAY2 = 1000;


const int RECV_PIN = 8;
IRrecv irrecv(RECV_PIN);
decode_results results;
double commando;
byte situation;


void green_lightNS()
{
  digitalWrite(GREENNS, HIGH);
  digitalWrite (GREENEW, LOW);
  digitalWrite(YELLOWNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, LOW);
  digitalWrite(REDEW, HIGH);
  Serial.println("NS:GREEN");
}

void yellow_lightNS()
{
  digitalWrite(GREENNS, LOW);
  digitalWrite(GREENEW, LOW);
  digitalWrite(YELLOWNS, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, LOW);
  digitalWrite (REDEW, HIGH);
  Serial.println("NS:YELLOW");
}

void red_lightNS()
{
  digitalWrite(GREENNS, LOW);
  digitalWrite(GREENEW, HIGH);
  digitalWrite(YELLOWNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, HIGH);
  digitalWrite(REDEW, LOW);
  Serial.println("NS:RED");
}

void green_lightEW ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, HIGH);
  Serial.println ("EW:GREEN");
}

void yellow_lightEW ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, HIGH);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDNS, HIGH);
  digitalWrite (REDEW, LOW);
  Serial.println ("EW:YELLOW");

}

void red_lightEW ()
{
  digitalWrite (GREENNS, HIGH);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDNS, LOW);
  digitalWrite (REDEW, HIGH);
  Serial.println ("EW:RED");
}

void all_off ()
{
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (GREENNS, LOW);
  Serial.println("EVERYTHING OFF");
}



void NS_green ()
{
  digitalWrite (REDEW, HIGH);
  digitalWrite (REDNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (GREENNS, HIGH);
  Serial.println("NS: EMERGENCY green");
}

void EW_green ()
{
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, HIGH);
  digitalWrite (GREENNS, LOW);
  Serial.println("EW: EMERGENCY green");
}

void yellow_flash ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, HIGH);
  digitalWrite (YELLOWNS, HIGH);
  digitalWrite (REDNS, LOW);
  digitalWrite (REDEW, LOW);
  Serial.println ("YELLOW FLASH");

}



void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pinMode(GREENNS, OUTPUT);
  pinMode(GREENEW, OUTPUT) ;
  pinMode(YELLOWNS, OUTPUT);
  pinMode(YELLOWEW, OUTPUT);
  pinMode(REDNS, OUTPUT);
  pinMode(REDEW, OUTPUT);

}

void loop() {

  if (irrecv.decode(&results))
  {
    commando = results.value;
    irrecv.resume();
  }

  //if commando for translating remote to signal, situation for defining the actual command

  if (commando = 16738455) {
    situation = 0;
  }

  if (commando = 16724175) {
    situation = 1;
  }

  if (commando = 16743045) {
    situation = 2;
  }

  if (commando = 16716015) {
    situation = 3;
  }

  if (commando = 16716015) {
    situation = 4;
  }

  if (commando = 16726215) {
    situation = 5;
  }



  //All Off
  if (situation = 0) {
    all_off ();
  }

  //Day or Normal situation
  if (situation = 1) {

    green_lightNS();
    delay(DELAY);
    yellow_lightNS();
    delay(DELAY);
    red_lightNS();
    delay(DELAY);
    green_lightEW();
    delay (DELAY);
    yellow_lightEW();
    delay(DELAY);
    red_lightEW();

  }

  //Yellow Flashing
  if (situation = 2) {
    {
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      all_off ();
      delay (DELAY2);
      yellow_flash();
      all_off ();
      delay (DELAY2);
      yellow_flash();
      all_off ();
      delay (DELAY2);
      yellow_flash();
      all_off ();
      delay (DELAY2);
      yellow_flash();

    }
  }

  //green for North and South
  if (situation = 3) {
    NS_green ();
    delay(DELAY);
  }


  //green for East & West
  if (situation = 4) {
    EW_green ();
    delay(DELAY);
  }
}
[/code]

Some things you will see often in this code are NS, and EW
those stand for North/South and East/West.

English isn't my main language, and i am not really sure if i fully understand my own code, since my teacher wrote some of it. so please go easy on me :slight_smile:
Greets from Holland and thanks in advance!

PS. Any other criticism or tips are well apreciated!

quick update: fixed some misktakes i made!

[code]
#include <IRremote.h>
// variables
int GREENNS = 2;
int GREENEW = 5;
int YELLOWNS = 3;
int YELLOWEW = 6;
int REDNS = 4;
int REDEW = 7;
int DELAY = 2000;
int DELAY2 = 1000;


const int RECV_PIN = 8;
IRrecv irrecv(RECV_PIN);
decode_results results;
double commando;
byte situation;


void green_lightNS()
{
  digitalWrite(GREENNS, HIGH);
  digitalWrite (GREENEW, LOW);
  digitalWrite(YELLOWNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, LOW);
  digitalWrite(REDEW, HIGH);
  Serial.println("NS:GREEN");
}

void yellow_lightNS()
{
  digitalWrite(GREENNS, LOW);
  digitalWrite(GREENEW, LOW);
  digitalWrite(YELLOWNS, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, LOW);
  digitalWrite (REDEW, HIGH);
  Serial.println("NS:YELLOW");
}

void red_lightNS()
{
  digitalWrite(GREENNS, LOW);
  digitalWrite(GREENEW, HIGH);
  digitalWrite(YELLOWNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite(REDNS, HIGH);
  digitalWrite(REDEW, LOW);
  Serial.println("NS:RED");
}

void green_lightEW ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, HIGH);
  Serial.println ("EW:GREEN");
}

void yellow_lightEW ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, HIGH);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDNS, HIGH);
  digitalWrite (REDEW, LOW);
  Serial.println ("EW:YELLOW");

}

void red_lightEW ()
{
  digitalWrite (GREENNS, HIGH);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (REDNS, LOW);
  digitalWrite (REDEW, HIGH);
  Serial.println ("EW:RED");
}

void all_off ()
{
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (GREENNS, LOW);
  Serial.println("EVERYTHING OFF");
}



void NS_green ()
{
  digitalWrite (REDEW, HIGH);
  digitalWrite (REDNS, LOW);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (GREENNS, HIGH);
  Serial.println("NS: EMERGENCY green");
}

void EW_green ()
{
  digitalWrite (REDEW, LOW);
  digitalWrite (REDNS, HIGH);
  digitalWrite (YELLOWEW, LOW);
  digitalWrite (YELLOWNS, LOW);
  digitalWrite (GREENEW, HIGH);
  digitalWrite (GREENNS, LOW);
  Serial.println("EW: EMERGENCY green");
}

void yellow_flash ()
{
  digitalWrite (GREENNS, LOW);
  digitalWrite (GREENEW, LOW);
  digitalWrite (YELLOWEW, HIGH);
  digitalWrite (YELLOWNS, HIGH);
  digitalWrite (REDNS, LOW);
  digitalWrite (REDEW, LOW);
  Serial.println ("YELLOW FLASH");

}



void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pinMode(GREENNS, OUTPUT);
  pinMode(GREENEW, OUTPUT) ;
  pinMode(YELLOWNS, OUTPUT);
  pinMode(YELLOWEW, OUTPUT);
  pinMode(REDNS, OUTPUT);
  pinMode(REDEW, OUTPUT);

}

void loop() {

  if (irrecv.decode(&results))
  {
    commando = results.value;
    irrecv.resume();
  }

  //if commando for translating remote to signal, situation for defining the actual command

  if (commando = 16738455) {
    situation = 0;
  }

  if (commando = 16724175) {
    situation = 1;
  }

  if (commando = 16743045) {
    situation = 2;
  }

  if (commando = 16716015) {
    situation = 3;
  }

  if (commando = 16716015) {
    situation = 4;
  }

  if (commando = 16726215) {
    situation = 5;
  }



  //All Off
  if (situation = 0) {
    all_off ();
  }

  //Day or Normal situation
  if (situation = 1) {

    green_lightNS();
    delay(DELAY);
    yellow_lightNS();
    delay(DELAY);
    red_lightNS();
    delay(DELAY);
    green_lightEW();
    delay (DELAY);
    yellow_lightEW();
    delay(DELAY);
    red_lightEW();

  }

  //Yellow Flashing
  if (situation = 2) {
    {
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY2);
      all_off ();
      delay (DELAY2);
      yellow_flash();
      delay (DELAY);

    }
  }

  //green for North and South
  if (situation = 3) {
    NS_green ();
    delay(DELAY);
  }


  //green for East & West
  if (situation = 4) {
    EW_green ();
    delay(DELAY);
  }
}
[/code]

Set up a small project to read and display what the IR Receiver receives. You will find the IR Receiver miss-reads the IR Remote often ... like, over 50% of the time.

Looks to me like you are making a tram/trolley traffic light.

Code like this will block the loop from reading the IT remote for 20+ sec, and if you don't transmit at just the right time, your code will never see it.

If you want it to read the IR remote during the delay() time you have to do something different than delay().

I have been using IR remotes and the IRremote library for years and have not seen anywhere near that many errors.

OP, what version of the IRremote librarydo you have installed? The code that you post is written for the older version of the IRremote library and may have problems if run using the newer versions (>3.0).

Well, its European style Traffic light, so it does work a bit diffrent.

I have tried that, but over 10 presses on eacht button, this is what i got 9 times of 10.

But the problem isn't in detecting what button is being pressed, its how i can make it only do a part of my code when i press that button, and only stop running that until i press another button

the detecting is just fine, i want it to run only a part of the code on each button press

(see response above)

To be honest, i dont know...
how can i check?

after re-reading, i now understand what you mean.
What is a better way of doing it?

There's a few different ways, like: write a replacement delay() that checks the switch, or use yield(), or rewrite the whole thing and eliminate all the delays and use state machines, etc...

... but it all depends on exactly what you want to have happen -- For instance, if you press the button, do you want the light to change immediately, or do you want it to immediately warn the current traffic that it will soon change an then change nicely, or do you want it to change at the end of a cycle?

I'd start with a State Diagram (State diagram - Wikipedia) of what you want to have happen, and think carefully about each arrow in the state diagram and what you'd need to implement it.

And if you want to minimally change your existing code, draw a state diagram for it, and think about what would need to be changed. to make it work like your ideal system.

When i press the button, i want to change it immediatly for the GREENEW and GREENNS, but for the rest, just at the end of the cycle. how would i go about coding that in? The yield() only seems usefull for the ESP8266 if i google it... and could you give an example of the 'state machines' after a quick google search i found a library about it, but i dont really understand the documentation for it...

Your current code is already a state machine based on situation, but it only can update situation a small fraction of the time. You should draw up what you have as a state diagram.

yield works just fine on a basic Arduino Uno: YeildDemo.ino - Wokwi Arduino and ESP32 Simulator

You could use that to update a global lastSeenCommand, or nextSituation variable and then use that for making state transition decisions.

The library is fine... it's the IR Receiver (that I have), so I got another, which does the same. I don't worry, I just do garbage separation code to allow the good Remote button presses to get through.

Okay, Thanks alot! i will definitely try that out tomorrow! Thanks again!

You are using the functionality of a state-machine with variable situation.

There is another kind how to create a state-machine.
This other kind uses the switch-case-break-statement

I bolded the word break to emphasise that the "break"-command is

very important

to make it work

Your functions

  //Day or Normal situation
  if (situation = 1) {

    green_lightNS();
    delay(DELAY);
    yellow_lightNS();
    delay(DELAY);
    red_lightNS();
    delay(DELAY);
    green_lightEW();
    delay (DELAY);
    yellow_lightEW();
    delay(DELAY);
    red_lightEW();
  }

etc. use delay. This must be changed to not use delay but non-blocking timing.

If you want highest responsivness this code must be changed to use its own state-machines too

The state-machine will enable NON-blocking timing
see the both words non-blocking ---------------- and --------------------- timing

Executing things from time to time like switching on / off LEDs
but in a non-blocking way

The key to this is to jump-in / jump-out of a function very quickly

You have to learn two things:

  1. learn how non-blocking timing works
  2. learn how switch-case-break state-machines work

Your state-machines will have time-based transistions from state to state
This will realise that your LEDs will bei switched on / off in the same timely manner as before but with instant reaction on button-presses.

Be the change you want to see in the world
best regards Stefan

Hello anton80
Consider and study the use of arrays and custom data types.
The use of structured arrays will reduce the coding work and debugging immensely. Give them a try.

Have a nice day and enjoy coding in C++.
Дайте миру шанс!

The purpose of additional state machines is to enable responsive processing during the intervals between light-changes in situation 1. The best way to accomplish this is to avoid delay() and write your code as @StefanL38 describes, remembering both situation and the stage-of-the-light-cycle-within-situation and acting appropriately. It is a completely different mode of thought than the blocking/sequential scheme in your code.

Oh--These are errors:

You used the assignment operator = instead of the equality operator == in your if-statements. These will overwrite commando and situation each time they are tested. See

Replace the '=' with '==' everywhere you do not want your variables overwritten.