IR Remote Decode Protocol Unknown and returning 0 Command [solved]

Hi I'm Novice Urduino user looking for help to debug what is going wrong with the following code. I've searched the forums and haven't been able to find the exact solution to my isuue.

Project context: a simple scoreboard using a WS2812 Led Strip and generic IR remote to change score . I believe Remote is NEC protocol. The Example code here is a stripped down test version to display the incremental score 0 - 9 on a single 7segment - with 1 led per segment.

Issue: I have extracted the Remote Protocol and HEX value for a single button using the first code example below. The result is Protocol 8 and HEX 4B, which I have then defined as 0x4B in the main code below.

The main code does not appear to be decoding the IR signal and returns Protocol Unknown and an value of 0 when the remote button is pressed.

I appreciate any guidance or assistance

This code retrieves the Protocol and Button value:
Protocol: 8
Command: 75
CommandHEX: 4B

#include <IRremote.h> 
#include <SoftwareSerial.h>
#define IR_RECEIVE_PIN 7 

//                          
// #define IR_BUTT_HOMEUP   4B    75    B44BFE01  //These are the value returned - have captured here


void setup()
{
  Serial.begin(9600);
  IrReceiver.begin(IR_RECEIVE_PIN); 

}

void loop() { 
 /* if (IrReceiver.decode()) { 
    
  IrReceiver.resume(); 
  
  int command = IrReceiver.decodedIRData.command;
  Serial.println(command);  
  }
  
  }
*/
 if (IrReceiver.decode()) {
    if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
      unsigned long command = IrReceiver.decodedIRData.command;
      Serial.print("Protocol: ");
      Serial.println(IrReceiver.decodedIRData.protocol);
      Serial.print("Command: ");
      Serial.println(command);
     Serial.print("CommandHEX: ");
     Serial.println(command, HEX);
      //handleIRInput(command);
    } else {
      Serial.println("Unknown protocol");
    }
    IrReceiver.resume(); // Receive the next value
  }
}

The following Code returns:
Unknown protocol
Command: 0

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

#define NUM_LEDS 35  // Total number of LEDs for testing (1 LED per segment)
#define DATA_PIN 6   // Data pin for LED strip
#define IR_RECEIVE_PIN 7 // Pin for IR receiver

CRGB leds[NUM_LEDS];

IRrecv irrecv(IR_RECEIVE_PIN);

int scoreTeamA = 0;

// Segment configuration for a seven-segment display
const uint8_t segments[10][7] = {
  {1, 1, 1, 1, 1, 1, 0}, // 0
  {0, 1, 1, 0, 0, 0, 0}, // 1
  {1, 1, 0, 1, 1, 0, 1}, // 2
  {1, 1, 1, 1, 0, 0, 1}, // 3
  {0, 1, 1, 0, 0, 1, 1}, // 4
  {1, 0, 1, 1, 0, 1, 1}, // 5
  {1, 0, 1, 1, 1, 1, 1}, // 6
  {1, 1, 1, 0, 0, 0, 0}, // 7
  {1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 1, 0, 1, 1}  // 9
};

// Update this with the correct value from the IR detection sketch
#define BUTTON_A_INC 0x4B // Correct button value

void setup() {
  Serial.begin(9600); // Start the serial communication
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  irrecv.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
  FastLED.clear();
  FastLED.show();
}

void loop() {
  if (irrecv.decode()) {
    if (irrecv.decodedIRData.protocol != UNKNOWN) {
      unsigned long command = irrecv.decodedIRData.command;
      Serial.print("Protocol: ");
      Serial.println(irrecv.decodedIRData.protocol);
      Serial.print("Command: ");
      Serial.println(command, HEX);
      handleIRInput(command);
    } else {
      unsigned long command = irrecv.decodedIRData.command;
      Serial.println("Unknown protocol");
       Serial.print("Command: ");
      Serial.println(command, HEX);
            
    }
    irrecv.resume(); // Receive the next value
  }
  displayScores();
}

void handleIRInput(unsigned long value) {
  switch(value) {
    case BUTTON_A_INC:
      scoreTeamA = (scoreTeamA < 99) ? scoreTeamA + 1 : 99;
      Serial.println("Incrementing Team A Score");
      break;
    default:
      Serial.println("Unknown command");
      break;
  }
}

void displayScores() {
  setDigit(0, scoreTeamA % 10, CRGB::Red); // Units digit of Team A score
}

void setDigit(int digitIndex, int number, CRGB color) {
  int offset = digitIndex * 7; // Calculate LED offset for each digit
  for (int segment = 0; segment < 7; segment++) {
    leds[offset + segment] = segments[number][segment] ? color : CRGB::Black;
  }
  FastLED.show();
}

I suspect that your issue is interrupt related. The libraries for NeoPixels (WS2812) block interrupts while they update the strip (FastLED.show()) and as a result the IR code does not work properly.

Your loop() is constantly updating the strip; you should only update the strip if there is a need, so call your displayScores() only when the score changes.

I would change the code as shown below.

/*
   Handle IR input
   Returns true if the score was updated, else false
*/
bool handleIRInput(unsigned long value) {
  // sterretje
  bool rb = false;
  switch (value) {
    case BUTTON_A_INC:
      scoreTeamA = (scoreTeamA < 99) ? scoreTeamA + 1 : 99;
      Serial.println("Incrementing Team A Score");
      // sterretje
      rb = true;
      break;
    default:
      Serial.println("Unknown command");
      break;
  }
  // sterretje
  return rb;
}

This function now returns true if the score changed, else false; when you call it in loop() you can store the result in a variable. You use that variable to determine if the display needs to be updated.

void loop() {
  // sterretje
  bool scoreUpdated = false;
  if (irrecv.decode()) {
    if (irrecv.decodedIRData.protocol != UNKNOWN) {
      unsigned long command = irrecv.decodedIRData.command;
      Serial.print("Protocol: ");
      Serial.println(irrecv.decodedIRData.protocol);
      Serial.print("Command: ");
      Serial.println(command, HEX);
      // sterretje
      scoreUpdated = handleIRInput(command);
    } else {
      unsigned long command = irrecv.decodedIRData.command;
      Serial.println("Unknown protocol");
      Serial.print("Command: ");
      Serial.println(command, HEX);
    }
    irrecv.resume(); // Receive the next value
  }

  // sterretje
  if (scoreUpdated == true)
  {
    displayScores();
  }
}

Tested and seems to work.

1 Like

Thank you @sterretje, that makes sense and is much cleaner using the True/False logic.
I'll give that a go.

Tested and works.
I was hell bent focused on the decoding function and would never have thought about the following logic:
" The libraries for NeoPixels (WS2812) block interrupts while they update the strip (FastLED.show() ) and as a result the IR code does not work properly."

Thanks again @sterretje

You will learn :slight_smile:

You will encounter similar issues when using e.g. serial communication in combination with NeoPixel (Adafruit, FastLED) libraries.

You can mark the topic as solved by clicking the checkbox under the most useful reply; alternatively edit the topic title and add something like [solved] to it. That way others that encounter the same problem and find the topic know that a solution was provided.

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