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 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?
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.
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.
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()