Skip to content
CommunicationMITv4.4.1

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/IRremote

Supported boards

Arduino UnoESP32STM32 Blue Pill

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();
//   }