IR remote question

Hi all, I’m trying to update an old project which used an IR remote to control Neopixel lighting strip. The old project used IRremote.h v 2.2.3 whereas the new project uses IRremote.h v 4.6.0. I’ve taken a simple IR receiver sketch and and added a “switch” routine which came from the old project. The sketch is far from complete but when I run it, pressing a particular button on the remote produces a result in the serial monitor “BF40FF00” I was expecting “0xFF02FD” which the same remote code produced in the old sketch. I gather that BF40FF00 is not actually a HEX code or something. What am I missing? Many thanks for any input you can give!

Update,

Sketch below

#include <IRremote.hpp>
#define IR_RECEIVE_PIN 2

// Set the light output to a low level white
int redValue = 10;
int greenValue = 10;
int blueValue = 10;
int oldred = 10;
int oldgreen = 10;
int oldblue = 10;
int memred = 155;
int memgreen = 255;
int memblue = 255;

void setup() {

  Serial.begin(115200);                                   // // Establish serial communication
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  // Start the receiver
}

void loop() {
  if (IrReceiver.decode()) {
    Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);  // Print "old" raw data
                                                                   //IrReceiver.printIRResultShort(&Serial);                        // Print complete received data in one line
                                                                   //IrReceiver.printIRSendUsage(&Serial);                          // Print the statement required to send this data

    switch (IrReceiver.decodedIRData.decodedRawData, HEX) {

      case 0xFF6897:  //1
        redValue = redValue - 10;
        if (redValue < 0) { redValue = 0; };
        break;
      case 0xFF9867:  //2
        {
          redValue = 255;
        };
        break;
      case 0xFFB04F:  //3
        redValue = redValue + 10;
        if (redValue > 250) { redValue = 255; };
        break;
      case 0xFF30CF:  //4
        greenValue = greenValue - 10;
        if (greenValue < 0) { greenValue = 0; };
        break;
      case 0xFF18E7:  //5
        {
          greenValue = 255;
        };
        break;
      case 0xFF7A85:  //6
        greenValue = greenValue + 10;
        if (greenValue > 250) { greenValue = 255; };
        break;
      case 0xFF10EF:  //7
        blueValue = blueValue - 10;
        if (blueValue < 0) { blueValue = 0; };
        break;
      case 0xFF38C7:  //8
        {
          blueValue = 255;
        };
        break;
      case 0xFF5AA5:  //9
        blueValue = blueValue + 10;
        if (blueValue > 250) { blueValue = 255; };
        break;
      case 0xFF4AB5:  //0
        {
          redValue = 0, greenValue = 0, blueValue = 0;
        };
        break;
      case 0xFF02FD:  //OK
        {
          redValue = 255, greenValue = 255, blueValue = 255;
        };
        break;
      case 0xFF42BD:  //* Loads memorised values
        redValue = memred, greenValue = memgreen, blueValue = memblue;
        break;
      case 0xFF52AD:  //# Stores current values in memory
        memred = redValue, memgreen = greenValue, memblue = blueValue;
        break;
    }

    delay(200);

    Serial.print("Red ");
    Serial.print(redValue);
    Serial.print("   Green ");
    Serial.print(greenValue);
    Serial.print("   Blue ");
    Serial.println(blueValue);

    delay(10);

    IrReceiver.resume();  // Enable receiving of the next value
  }
}
  • If we assume your remote uses the NEC protocol, this tutorial should give you some ideas how to change your old code.
  • The tutorial uses TinyIRReceiver.hpp which comes in the IRremote library installation.
    Read the comments at the top of the sketch.
    The receive command is now returned as only two hex digits.
    For example, notice the top left remote button code.
    0x5C instead of 0x00FF5CA3

  • The new IRremote library version is very different from the old.

in the tool bar when you create a post you'll see a button <code>

you click on it and in inserts some text in the post where your cursor is

just replace the text type or paste code here by your code.

Many thanks for this, original post updated with the code

1 Like

The format was changed and also from msb to. Lsb. Library documentation explains it quite well. While you can convert your old codes to modern format, it's probably quicker just to receive them all with new receiver code

Sorry guys, thanks for your input so far but I’m out of my depth here, if the code returned in the serial monitor for a particular button on the remote is “BF40FF00” what should I enter into the switch routine to respond to this code?

switch (IrReceiver.decodedIRData.decodedRawData) {

      case 0xBF40FF00: //and so on...

But probably best way would be using just the command

switch (IrReceiver.decodedIRData.command) {

      case 0x02: //the two digit command your receiver code outputs

Thanks kmin, I tried your first example, didn’t work I’m affraid. In you second suggestion, how do I determine what the 2 digit command is?

  • Look at the examples that come with the updated library.

  • There will be an example that prints the commands for your remote to the serial monitor, record the 2 digit hexadecimal commands printed for each button.

  • Use these 2 digit commands in your sketch.

  • What are you using for your IR remote ?

You’re gonna think I’m a right thicko here but “Look at the examples that come with the updated library.” How do I do that?

This is my remote

  • This is an array definition for your particular remote.

const byte buttonCode[][2] PROGMEM =
{
  //           Index KeyName
  {0x46, '^' }, //0  ^
  {0x44, '<' }, //1  <
  {0x40, 0x0A}, //2  OK
  {0x43, '>' }, //3  >
  {0x15, 'v' }, //4  v
  {0x16, '1' }, //5  1
  {0x19, '2' }, //6  2
  {0x0D, '3' }, //7  3
  {0x0C, '4' }, //8  4
  {0x18, '5' }, //9  5
  {0x5E, '6' }, //10 6
  {0x08, '7' }, //11 7
  {0x1C, '8' }, //12 8
  {0x5A, '9' }, //13 9
  {0x42, '*' }, //14 *
  {0x52, '0' }, //15 0
  {0x4A, '#' }  //16 #
};

Thanks Larry, but continuing the “Thicko” theme, I don’t get it. I have several of these remotes and all give different output codes, how do I find out which 2 digit codes mine do output?

  • Use the IDE menu go to the examples entry use File > Open menu option or the File > Open menu in the Arduino IDE, find the IR library entry, there will be examples therein.
  • After 0xCOFFEE I’ll attach a simple sketch, 30 minutes or so.
    Others may chime in the meantime.

0x46, '^'

When you push the ^ on your remote you get the 0x46 command.

Receive demo should output something like this:

Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
Send with: IrSender.sendNEC(0x80, 0x45, );

Arduino-IRremote/examples/ReceiveDemo/ReceiveDemo.ino at master · Arduino-IRremote/Arduino-IRremote · GitHub

you run something like this

#include <IRremote.hpp>
#define IR_RECEIVE_PIN 2

void setup() {
  Serial.begin(115200);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {
    const uint8_t cmd = IrReceiver.decodedIRData.command;
    Serial.print("Command: 0x"); Serial.println(cmd, HEX);
    IrReceiver.resume();
  }
}

once you know the right codes, you fill that into your original switch/case and adjust for the new version of the library

#include <IRremote.hpp>
#define IR_RECEIVE_PIN 2

void setup() {
  Serial.begin(115200);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {
    const uint8_t cmd = IrReceiver.decodedIRData.command;
    Serial.print("Command: 0x"); Serial.println(cmd, HEX);

    switch (cmd) {
      case 0x16: redValue = max(redValue - 10, 0); break;    // Button 1
      case 0x19: redValue = 255; break;                      // Button 2
      case 0x0D: redValue = min(redValue + 10, 255); break; // Button 3
      case 0x0C: greenValue = max(greenValue - 10, 0); break; // Button 4
      case 0x18: greenValue = 255; break;                   // Button 5
      case 0x5E: greenValue = min(greenValue + 10, 255); break; // Button 6
      case 0x08: blueValue = max(blueValue - 10, 0); break; // Button 7
      case 0x1C: blueValue = 255; break;                    // Button 8
      case 0x5A: blueValue = min(blueValue + 10, 255); break; // Button 9
      case 0x52: redValue = 0; greenValue = 0; blueValue = 0; break; // Button 0
      case 0x0A: redValue = 255; greenValue = 255; blueValue = 255; break; // OK
      case 0x42: redValue = memRed; greenValue = memGreen; blueValue = memBlue; break; // *
      case 0x4A: memRed = redValue; memGreen = greenValue; memBlue = blueValue; break; // #
    }


    Serial.print("Red "); Serial.print(redValue);
    Serial.print("   Green "); Serial.print(greenValue);
    Serial.print("   Blue "); Serial.println(blueValue);

    IrReceiver.resume();
  }
}

1 Like

Thank you **J-M-L**Jackson, much appreciated.

With a couple of changes to the 2 digit codes it all works perfectly. now I can move on to the rest of the project…..

Thanks to everyone else too………..

Glad you solved it!

BTW

is it APA102 or really neopixels ?
what type of arduino are you using ?

(IR and Neopixel with lots of animations don't do so well together on many arduinos)

  • I like using TinyIRReceiver.hpp library as it uses interrupts instead of a TIMER.
#include <TinyIRReceiver.hpp>                //For use with NEC IR remotes.

Sample sketch

//
//================================================^================================================
//                               IR_Remote_44_Tutorial_TinyIRReceiver
//================================================^================================================
//
//  https://forum.arduino.cc/t/ir-remote-question/1427219
//
//  LarryD
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ========================================================================
//  1.00       26/01/25    Running code
//
//



//================================================^================================================
//Leave these "defines" at this location. i.e. before line: #include "TinyIRReceiver.hpp"
//
//#define IR_FEEDBACK_LED_PIN            13  //Defaults to 13.
//#define NO_LED_FEEDBACK_CODE               //Disables LED feedback.
#define IR_RECEIVE_PIN                   2   //Defaults to 2.
#define USE_CALLBACK_FOR_TINY_RECEIVER       //Allow the user ISR callback function to execute.

//==================================
#include <TinyIRReceiver.hpp>                //For use with NEC IR remotes.


//ISR VARIABLES
//================================================
//These variables are shared between:
// - the interrupt routine (ISR)
// - the main loop()
//
//'volatile' tells the compiler that these values can change at ANY time,
//so it must always read them directly from memory.
//
volatile bool irCommandReady            = false;
volatile byte irCommand                 = 0;

//Timing stuff.
//========================
unsigned long heartbeatTime             = 0;
const unsigned long heartbeatInterval   = 500ul;

//MISC
//========================
const byte tonePin                      = 8;
const byte heartbeatLED                 = 13;       //Toggles every 500ms. Also flashes when an IR signal is detected.



//                                           s e t u p ( )
//================================================^================================================
//
void setup()
{
  Serial.begin(115200);

  pinMode(heartbeatLED, OUTPUT);
  
  //IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

  //This single function call does ALL of the following:
  //1) Configures the IR receive pin.
  //2) Enables pin-change interrupts.
  //3) Starts listening for NEC IR commands.
  //
  //When a command is detected, the library automatically calls
  //handleReceivedTinyIRData() (our ISR callback).
  //
  initPCIInterruptForTinyReceiver();

} //END of   setup()


//                                            l o o p ( )
//================================================^================================================
//
void loop()
{
  //========================================================================  T I M E R  heartbeatLED
  //NOTE: This LED is "dual purpose".
  //Is it time to toggle the heartbeat LED ?
  //TinyIRReceiver.hpp also uses this LED for IR RX FEEDBACK.
  //
  if (millis() - heartbeatTime >= heartbeatInterval)
  {
    //Restart this TIMER.
    heartbeatTime = millis();

    //Toggle the heartbeat LED.
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }
  
  //======================================================================== Process new IR received commands
  //Did we receive a new IR remote command ?
  //
  bool tempFlag;
  byte _irCommand;

  //Atomic access
  //The ISR can change "irCommandReady" and "irCommand" at any moment.
  //To avoid reading half-updated data, we briefly disable interrupts,
  //copy the values, then immediately re-enable interrupts.
  //This keeps the program safe and predictable.
  //
  noInterrupts();
  if (irCommandReady == true)
  {
    irCommandReady = false;
    tempFlag = true;
    _irCommand = irCommand;
  }
  else
  {
    tempFlag = false;
  }
  interrupts();

  //Did we receive a new command ?
  if (tempFlag == true)
  {
    //Process the new IR command.
    serviceButtonPress(_irCommand);
  }


  //================================================
  //       Other non blocking code goes here
  //================================================


} //END of   loop()


//                         h a n d l e R e c e i v e d T i n y I R D a t a ( )
//================================================^================================================
//We do not call this ISR ourselves — the IR library does this automatically when an IR signal is detected.
//
void handleReceivedTinyIRData()
{
  if (irCommandReady == false)
  {
    //Save the IR code for later processing.
    irCommand = TinyIRReceiverData.Command;

    //Flag that we have a new IR code.
    irCommandReady = true;
  }

  //IMPORTANT ISR RULES
  //- Keep ISRs VERY short
  //- Do NOT use Serial.print()
  //- Do NOT use delay()
  //- Do NOT do heavy calculations
  //
  //For this ISR only:
  //1) set a flag to tell loop() that new data is ready,
  //2) copy the received command, and
  //3) determine if this is a "new command" or a "repeat" command.

} //END of   handleReceivedTinyIRData()


//                               s e r v i c e B u t t o n P r e s s ( )
//================================================^================================================
void serviceButtonPress(byte _irCommand)
{
  //NOTE: You can egnore repeat codes so only the 1st button press gets printed.
  
  //tone() inside main loop can glitch PWM
  //tone() uses Timer2 on UNO.
  //analogWrite() on pin 9 uses Timer1 → OK, Breaks PWM on pins 3 & 11 (Timer2)
  tone(tonePin, 3400, 100);
  Serial.println(_irCommand, HEX);

} //END of   serviceButtonPress()