IRremote
by Armin Joachimsmeyer
IRremote decodes and sends infrared remote-control signals for most common protocols, including NEC, Sony, RC5 and Samsung. It captures the exact pulse timings from an IR receiver module and matches them against the known protocols. The usual uses are controlling a project with a TV or cheap kit remote, copying the buttons of a remote, and sending commands from an IR LED. The most common problem is a compile error caused by an old tutorial. Version 3 and 4 rewrote the API. Old code uses `IRrecv irrecv(PIN)`, `decode_results results` and `irrecv.enableIRIn()`, and none of that exists in current versions. The new code uses `IrReceiver.begin(PIN)`, `IrReceiver.decode()`, and reads the result from `IrReceiver.decodedIRData`. In v4 you also include `<IRremote.hpp>`. If an example fails to compile, check which version it was written for. Two examples in the code section below show the old and new style side by side. Wiring needs care. Use a 38 kHz receiver module such as the VS1838B or TSOP38238, which has three pins: signal, GND and VCC. The pin order differs between a bare receiver and a breakout board, so read the markings, because reversed power can destroy the receiver. Put the receiver where it will not face direct sunlight, and if you get random codes, a small capacitor across its power pins and a position away from fluorescent or LED lighting often helps. Know a few hardware limits. The library uses a hardware timer, so on an Uno it conflicts with `tone()`, and on an Uno the sending pin is fixed by the timer (normally pin 3), while on an ESP32 you can usually choose the pin. An IR LED connected straight to a pin gives only a few centimetres of range, so drive it through a transistor for useful distance. The library can only send signals it understands, so if a remote shows up as `UNKNOWN`, capture the raw timings (see the example below) rather than guessing. Two things this library does not cover well. For air conditioners, whose remotes send long state-based messages, use IRremoteESP8266 (which also runs on ESP32). And repeated codes: when a button is held, the remote sends short repeat frames, so check the repeat flag in your code or a single press will trigger an action many times.
Installation
Arduino IDE — Library Manager
Sketch → Include Library → Manage Libraries → search IRremote
PlatformIO
lib_deps = arduino-irremote/IRremoteSupported boards
Examples
Receive and print an IR code (current v4.x API)
The starting point for any remote project. Press a button and the serial monitor shows the protocol, address and command.
#include <Arduino.h>
#include <IRremote.hpp> // v4.x uses the .hpp include
#define IR_RECEIVE_PIN 11 // any suitable GPIO on ESP32
void setup() {
Serial.begin(115200);
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}
void loop() {
if (IrReceiver.decode()) {
IrReceiver.printIRResultShort(&Serial); // protocol, address, command
IrReceiver.resume(); // get ready for the next signal
}
}Control an output with specific remote buttons
Ignores the repeat frames sent while a button is held, then reacts to the command values you saw in the first example. Your remote's codes will differ.
#define LED_PIN 8
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
IrReceiver.begin(IR_RECEIVE_PIN);
}
void loop() {
if (IrReceiver.decode()) {
if (!(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
uint16_t command = IrReceiver.decodedIRData.command;
switch (command) {
case 0x45: digitalWrite(LED_PIN, HIGH); break; // example: first button
case 0x46: digitalWrite(LED_PIN, LOW); break; // example: second button
default:
Serial.print(F("Unmapped command 0x"));
Serial.println(command, HEX);
}
}
IrReceiver.resume();
}
}Send an NEC command
Sends the same address and command a typical NEC remote would. Drive the IR LED through a transistor for good range.
#include <IRremote.hpp>
#define IR_SEND_PIN 3 // on an Uno the send pin is set by the timer (normally 3)
void setup() {
IrSender.begin(IR_SEND_PIN);
}
void loop() {
IrSender.sendNEC(0x00, 0x45, 2); // address, command, number of repeats
delay(2000);
}When the protocol shows as UNKNOWN
Print the raw pulse timings so you can study or replay a remote the library cannot decode.
if (IrReceiver.decode()) {
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
IrReceiver.printIRResultRawFormatted(&Serial, true); // raw timings in microseconds
} else {
IrReceiver.printIRResultShort(&Serial);
}
IrReceiver.resume();
}Old tutorial code vs the current v4 API
If you copied code that no longer compiles, this is the translation. Both versions are shown as comments.
// OLD (v2/v3 tutorials) - will NOT compile with v4:
// IRrecv irrecv(11);
// decode_results results;
// irrecv.enableIRIn();
// if (irrecv.decode(&results)) {
// Serial.println(results.value, HEX);
// irrecv.resume();
// }
// NEW (v4):
// IrReceiver.begin(11);
// if (IrReceiver.decode()) {
// Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
// IrReceiver.resume();
// }