Unable to switch between different loops using an IR remote

Hi all. I’m reposting this question at a more sane time to hopefully get some more eyes on it. I’m trying to switch between different LED light effect modes by using an IR remote. In this specific case I’m trying to make it so selecting 0 on my remote causes a red LED to fall down the strip in a loop, selecting 1 a green LED and 2 a blue LED.

Currently what happens is that the first button press on my remote when the arduino is started up is registered and the correct LED effect begins looping. However after that all my other button presses are ignored and I’m unable to switch between modes. Checking the serial monitor shows me that subsequent button presses will cause the switch ‘results.value’ to return the default value.

So my question is, how can I switch between different loops using an IR remote?

I’ve checked through the forums and seen similar issues but their fixes have not resolved my issue, specifically I integrated the fixes from this thread but no luck.

I’m aware that using delay is anathema on this forum but I’ve checked the code with and without them and the issue remains.

Functionally I can’t see why this issue is occurring, from my perspective it looks as though logically all things should be fine. I read that the IR library cannot take an input if it’s transmitting but I don’t think that’s happening here? To be honest I’m not experienced with coding or the nitty gritty of Ardunios so there must be something I’m missing but I have no idea what.

I’m using an Elegoo IR remote and the included IR receiver circuit board. I’m using an Uno R3 and am on version 1.8.9 or the IDE.

#include "IRremote.h"
#include <FastLED.h>

#define LED_PIN_1   7
#define LED_PIN_2   8
#define NUM_LEDS    55
#define updateLEDS 2

CRGB leds[NUM_LEDS] ={};

int receiver = 11; // Signal Pin of IR receiver to Arduino Digital Pin 11

int currentMode = (-1);
const int RED_DOT_MODE = 0;
const int GREEN_DOT_MODE = 1;
const int BLUE_DOT_MODE = 2;

/*-----( Declare objects )-----*/
IRrecv irrecv(receiver);     // create instance of 'irrecv'
decode_results results;      // create instance of 'decode_results'

/*-----( Function )-----*/
void translateIR() // takes action based on IR code received

// describing Remote IR codes

{

  switch(results.value)

  {
  case 0xFFA25D: Serial.println("POWER");   break;
  case 0xFFE21D: Serial.println("FUNC/STOP");   break;
  case 0xFF629D: Serial.println("VOL+"); break;
  case 0xFF22DD: Serial.println("FAST BACK");    break;
  case 0xFF02FD: Serial.println("PAUSE");    break;
  case 0xFFC23D: Serial.println("FAST FORWARD");   break;
  case 0xFFE01F: Serial.println("DOWN");    break;
  case 0xFFA857: Serial.println("VOL-");    break;
  case 0xFF906F: Serial.println("UP");    break;
  case 0xFF9867: Serial.println("EQ");    break;
  case 0xFFB04F: Serial.println("ST/REPT");    break;
 
  case 0xFF6897:
  //Serial.println("0");
  currentMode = RED_DOT_MODE;   
  break;
 
  case 0xFF30CF:
  //Serial.println("1");   
  currentMode = GREEN_DOT_MODE;
  break;
 
  case 0xFF18E7:
  //Serial.println("2");   
  currentMode = BLUE_DOT_MODE;
  break;
 
 
  case 0xFF7A85: Serial.println("3");    break;
  case 0xFF10EF: Serial.println("4");    break;
  case 0xFF38C7: Serial.println("5");    break;
  case 0xFF5AA5: Serial.println("6");    break;
  case 0xFF42BD: Serial.println("7");    break;
  case 0xFF4AB5: Serial.println("8");    break;
  case 0xFF52AD: Serial.println("9");    break;
  case 0xFFFFFFFF: Serial.println(" REPEAT");break; 

  default:
    Serial.println(" other button   ");

  }// End Case


  delay(500); // Do not get immediate repeat


} //END translateIR
void setup()   /*----( SETUP: RUNS ONCE )----*/
{
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode");
  FastLED.addLeds<WS2812, LED_PIN_1, GRB>(leds, NUM_LEDS);
  FastLED.addLeds<WS2812, LED_PIN_2, GRB>(leds, NUM_LEDS);
  irrecv.enableIRIn(); // Start the receiver

}/*--(end setup )---*/


void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  if (irrecv.decode(&results)) // have we received an IR signal?

  {
    translateIR();
    irrecv.resume(); // receive the next value
  } 

      switch(currentMode){
     
      case RED_DOT_MODE:
      Serial.println("Looping Red Dot.");
      for(int dot = 0; dot < NUM_LEDS; dot++) {
            leds[dot].setRGB(255,0,0);
            FastLED.show();
            // clear this led for the next time around the loop
            leds[dot] = CRGB::Black;
            delay(30);
        }
      break;

      case GREEN_DOT_MODE:
      Serial.println("Looping Green Dot");
      for(int dot = 0; dot < NUM_LEDS; dot++) {
            leds[dot].setRGB(0,255,0);
            FastLED.show();
            // clear this led for the next time around the loop
            leds[dot] = CRGB::Black;
            delay(30);
        }
      break;

      case BLUE_DOT_MODE:
      Serial.println("Looping Blue Dot");     
      for(int dot = 0; dot < NUM_LEDS; dot++) {
            leds[dot].setRGB(0,0,255);
            FastLED.show();
            // clear this led for the next time around the loop
            leds[dot] = CRGB::Black;
            delay(30);
        }
     
      break;

      }

 
}/* --(end main loop )-- */

So I figured out the issue. While fastLED.show() is running it will interfere with the receiving of IR codes. My switch case isn't changing as it's receiving a hex code from the IR receiver which has become garbled by the LED effect loop running.

As said by focalintent here "The timing protocol for WS2812 leds requires disabling interrupts while writing out led data, and the IR library relies on interrupts to read the IR data, which means that if you're using the remote while the library is writing out led data, then it is going to miss part of the ir signal and misinterpret it.".

It does appear there's a possible workaround made by VorpalLemur found on the same page:

IRrecv irrecv(RECV_PIN);
decode_results results;

loop() {

    /* do effects here */

    while (!irrecv.isIdle());  // if not idle, wait till complete

    if (irrecv.decode(&results)) {  
        /* respond to button */

        irrecv.resume(); // Set up IR to receive next value.
    }

    FastLED.show(); 
}