Erratic IR - works fine in one sketch and not in the other

I'm working on a project whereby I'm using a remote control to control the lights of a baseball scoreboard that I've made.

I'm using the following script to get the codes for my remote control. The issue is that when I take the exact same code and incorporate it into my main project, the results from the IR are completely different. So there must be some conflict in my main project with the IR but I can't figure out what it is. In the "test" script with just the IR, when I press the "Up" button on the remote, I consistently get the same code. When I put the same code into my main program, every time I press the "Up" button I get a completely different random number.

Here is the test code I'm using to get the IR codes:

#include <IRremote.h>
const int RECV_PIN = 2;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup(){
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  }

void loop(){
  
  if (irrecv.decode(&results)){
         unsigned long test = results.value;
  Serial.println (test);
  }
  
    irrecv.resume();
  }

and here is my whole project, with just different names for the ir variables (in this script the IR results are in a variable called "code" instead of test as in the above. Any help in getting this resolved would be appreciated...

//timer setup

int interval=30000;
// Tracks the time since last event fired
unsigned long previousMillis=0;
unsigned long remoteMillis=0;
int remoteinterval = 1500;
int thirtysecs = 0;

//Libraries

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


//Pins

#define homepin 8
#define awaypin 3
#define inningpin 4
#define ballpin 5
#define strikepin 6
#define outpin 7
#define timerpin 9
const int RECV_PIN = 2;

//Activate remote

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long key_value = 0;
unsigned long old_value = 0;
 

//Activate Leds

CRGB homenum[42];
CRGB away[42];
CRGB ball [3];
CRGB strike[2];
CRGB inning[7];
CRGB out[2];
CRGB timing [14];

//Define Counts

int homeonecount = 0;
int hometencount = 0;
int awayonecount = 0;
int awaytencount = 0;
int ballcount = 0;
int strikecount = 0;
int outcount = 0;
int inningcount = 0;
int tens =0;
int minutes =0;

//Define Bytes

byte digit[10][21] = {
{ 1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1  }, //0
{ 1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0   }, //1
{  1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  1,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1 }, //2
{  1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0 } , //3
{  1,  1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0 } , //4
{  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0 } , //5
{  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 } , //6
{  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0 } , //7
{  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 } , //8
{  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0 } , //9


};

 
byte inningdigit[10][7] = {
{ 1,  1,  1,  0,1,1,1 }, //0
{ 1,  0,  0,  0,  1,  0,  0 }, //1
{  1,  1,  0,  1,  0,  1,  0 }, //2
{  1,  1,  0,  1,  1,  1,  0} , //3
{  1,  0,  1,  1,  1,  0,  0} , //4
{  0,  1,  1,  1,  1,  1,  0} , //5
{  0,  1,  1,  1,  1,  1,  1 } , //6
{  1,  1,  0,  0,  1,  0,  0} , //7
{  1,  1,  1,  1,  1,  1,  1 } , //8
{  1,  1,  1,  1,  1,  0,  0} , //9

};


//Setup

void setup() {

//Define Leds

FastLED.addLeds<WS2812, homepin, GRB>(homenum, 42);
FastLED.addLeds<WS2812, awaypin, GRB>(away, 42);
FastLED.addLeds<WS2812, inningpin, GRB>(inning, 7);
FastLED.addLeds<WS2812, ballpin, GRB>(ball, 3);
FastLED.addLeds<WS2812, strikepin, GRB>(strike, 2);
FastLED.addLeds<WS2812, outpin, GRB>(out, 2);
FastLED.addLeds<WS2812, timerpin, GRB>(timing, 14);

Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);

}



//Loop

void loop() {

unsigned long currentMillis = millis();

   // How much time has passed, accounting for rollover with subtraction!
   if ((unsigned long)(currentMillis - previousMillis) >= interval) {
    thirtysecs = thirtysecs+1;
    if (thirtysecs >= 2){
        minutes = minutes+1;
        thirtysecs = 0;
    }
  
    if (minutes>9){
      minutes = 0;
      tens = tens+1;
    }
    if (tens > 9) tens=0;
       previousMillis = currentMillis;
    }
  
 
  
HomeOnes();
HomeTens;
AwayOnes ;
AwayTens ;
inningcode;
ballcode;
strikecode;
outcode;
onestimer;
tenstimer;

  if (irrecv.decode(&results)){
    unsigned long code = results.value;
 
       if ((unsigned long)(currentMillis - remoteMillis) >= remoteinterval) {

        switch(code){
          case 3772833823:
          homeonecount++;
          remoteMillis = currentMillis;
                   break;
          case 0xFF629D:
        awayonecount++;
        remoteMillis = currentMillis;
          break;
           case 0xFF629e:
        ballcount++;
        remoteMillis = currentMillis;
          break;
           case 0xFF629fe:
       strikecount++;
       remoteMillis = currentMillis;
          break;
           case 0xFF7:
        outcount++;
        remoteMillis = currentMillis;
          break;
           case 0xFF6:
        inningcount++;
        remoteMillis = currentMillis;
          break;
                     }
       }
        key_value = results.value;
        irrecv.resume(); 
               Serial.println (code);
        
  }

if (ballcount >3) ballcount ==0;
if (inningcount >9) inningcount ==0;
if (strikecount >2) strikecount ==0;
if (outcount >2) outcount ==0;
if (homeonecount > 9) {
  homeonecount ==0;
  hometencount++;
}
if (awayonecount > 9) {
  awayonecount ==0;
  awaytencount++;
}
if (hometencount > 9) hometencount ==0;
if (awaytencount > 9) awaytencount ==0;





}



void HomeOnes(){



  for(int i=0; i<20; i++){                

    if( digit[homeonecount][i] )

      homenum[i] = CRGB::Teal;  //Switch the LED on

    else

      homenum[i] = CRGB::Black; // Switch the LED off

  }

  FastLED.show();

}

 

void HomeTens(byte hometencount, CRGB Teal){

 
  for(int i=21; i<42; i++){              

    if( digit[hometencount][i] )

      homenum[i] = CRGB (Teal);  //Switch the LED on

    else

      homenum[i] = CRGB::Black; // Switch the LED off

  }

  FastLED.show();

}

 

void AwayOnes(byte awayonecount, CRGB Teal){

  for(int i=0; i<20; i++){                

    if( digit[awayonecount][i] )

      away[i] = CRGB (Teal);  //Switch the LED on

    else

      away[i] = CRGB::Black; // Switch the LED off

  }

  FastLED.show();

}

 

void AwayTens(byte awaytencount, CRGB Teal){

  

  for(int i=21; i<42; i++){              

    if( digit[hometencount][i] )

      away[i] = CRGB (Teal);  //Switch the LED on

    else

      away[i] = CRGB::Black; // Switch the LED off

  }

  FastLED.show();

}

void inningcode (byte inningcount, CRGB Teal){

 

  for(int i=0; i<7; i++){              

    if( inningdigit[inningcount][i] )

      inning[i] = CRGB (Teal);  //Switch the LED on

    else

      inning[i] = CRGB::Black; // Switch the LED off

  }


  FastLED.show();
}
  void strikecode (){

    if (strikecount == 0) {
    strike[0] = CRGB ::Black;
    strike[1] = CRGB ::Black;
    FastLED.show();}
else
 if (strikecount == 1) {
    strike[0] = CRGB ::Teal;
    strike[1] = CRGB ::Black;
          FastLED.show();}
    else
 if (strikecount == 2) {
    strike[0] = CRGB ::Teal;
    strike[1] = CRGB ::Teal;
       FastLED.show();}
 }

 void outcode (){

    if (outcount == 0) {
    out[0] = CRGB ::Black;
    out[1] = CRGB ::Black;
    FastLED.show();}
else
 if (outcount == 1) {
    out[0] = CRGB ::Teal;
    out[1] = CRGB ::Black;
          FastLED.show();}
    else
 if (outcount == 2) {
    out[0] = CRGB ::Teal;
    out[1] = CRGB ::Teal;
       FastLED.show();}
 }

void ballcode (){

    if (ballcount == 0) {
    ball[0] = CRGB ::Black;
    ball[1] = CRGB ::Black;
      ball[2] = CRGB ::Black;  
    FastLED.show();}
else
 if (ballcount == 1) {
    ball[0] = CRGB ::Teal;
    ball[1] = CRGB ::Black;
      ball[2] = CRGB ::Black;  
    FastLED.show();}
    else
 if (ballcount == 2) {
    ball[0] = CRGB ::Teal;
    ball[1] = CRGB ::Teal;
      ball[2] = CRGB ::Black;  
    FastLED.show();}
       else
 if (ballcount == 3) {
    ball[0] = CRGB ::Teal;
    ball[1] = CRGB ::Teal;
      ball[2] = CRGB ::Teal;  
    FastLED.show();}
 }

 
void onestimer (byte minute, CRGB Teal){

 

  for(int i=0; i<7; i++){              

    if( inningdigit[minute][i] )

      timing[i] = CRGB (Teal);  //Switch the LED on

    else

      timing[i] = CRGB::Black; // Switch the LED off

  }
}

  void tenstimer (byte tens, CRGB Teal){
  for(int i=8; i<15; i++){              

    if( inningdigit[tens][i] )

      timing[i] = CRGB (Teal);  //Switch the LED on

    else

      timing[i] = CRGB::Black; // Switch the LED off

  }


  FastLED.show();

}


  

There are no "scripts" in the Arduino environment. FastLED will interfere with IR code if it is updating the LED strip, at the same time as you are trying to receive. There is no solution to that.

Like @anon57585045 says, FastLED cannot coexist with IRremote because the FastLED show() function disables interrupts when it runs. Any IR data that comes in while interrupts are disabled will be corrupted or ignored. It is the same with serial comms or anything else that depends on interrupts.

This thread may have a solution. >> IR remote erratic in operation?

What version of the IRremote library are you using? The newest versions (> 3.0) may not work properly with code written for older versions. See the IRremote GitHub page.

I'm using version 3 or IRremote. So there is no way to use a remote control to control addressable LED's with arduino? I'm assuming there is a way to light addressable LED's without a library - is that true?

This is for Adafruit_NeoPixel but should work with FastLED too.

Sure. I was not aware of the other efforts, it seems like a lot of work but if that's what you need, that's what you need.

There is no problem if the strips are not continously updating. For example, you can easily accept IR commands and use a received command to change the strip once until another command is received.

Technically, yes, but not easily. And one would still need to disable interrupts while sending data to the strips. The timing for the data stream is very tight. That is why interrupts must be disabled. There can be no interruptions during data transfer.

I think the method shown by @LarryD is kind of clever. I may try it myself.

I'm kind of surprised that there is no driver chip on the market.

1 Like

I know of two ways and there are probably others:

  • Use one of the PJRC Teensy Boards and the associated library to blast the LED strip data out of a UART port via DMA without disabling interrupts. There's also an example how to hook this library into FastLED.

  • Switch to an APA102 or similar LED strip (i.e. Adafruit DotStar). They're driven by a clock / data pair and don't require interrupts to be disabled.

By the way, the cast to 'unsigned long' here is unnecessary.

I found a relatively simple solution to this problem that works with FastLed, and the remote now works consistently providing only one result every time. I changed the library to IRLib 2. I then played around with different scenarios to get consistent results. You need to make sure you put in all these parameters to get the same IR results each time...

 if (myReceiver.getResults()) {
    myDecoder.decode();           //Decode it
    myDecoder.dumpResults(true);  //Now print results. Use false for less detail
    myReceiver.enableIRIn();      //Restart receiver
       Serial.println (myDecoder.value);

Using this method the "MyDecoder.value" is the same every time and works perfectly with FastLED

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