The Verdict: Which IR Remote Library for Arduino Should You Pick?
If you are trying to decode a TV remote or blast commands to an AC unit, the ecosystem can feel fragmented. In the early 2020s, the transition between library versions caused massive breaking changes, but as of 2026, the landscape has stabilized. Here is the direct answer: for 95% of standard 38kHz NEC, Sony, and RC5 remote sniffing and blasting on classic AVR boards, install IRremote version 4.2.0+ (maintained by ArminJo/crankyoldgit) via the Arduino Library Manager.
Do not waste time on the legacy IRremote v2.x forks or the IRLremote library unless you are maintaining a decade-old codebase. If you are using an ESP32 and need deep, stateful control over complex HVAC protocols (like tracking the exact swing and temperature state of a Mitsubishi AC), use IRremoteESP8266. Otherwise, unify your stack.
| Microcontroller | Primary Use Case | Recommended Library | Why This Pick? |
|---|---|---|---|
| AVR (Uno, Nano, Mega) | Sniffing standard remotes, basic blasting | IRremote (v4.x) | Native timer integration, massive protocol support, active maintenance. |
| ESP32 / ESP8266 | Smart home IR blasters, AC state tracking | IRremoteESP8266 | Unmatched A/C protocol decoding, hardware PWM utilization on ESP chips. |
| Any (AVR/ESP/Pico) | Simple raw IR timing capture (no protocol decoding) | IRremote (v4.x) in Raw mode | Bypasses protocol logic; just dumps microsecond pulse/space arrays. |
IRremote to record the exact microsecond pulse train, then replay it blindly. You don't always need to decode the hex to replicate the signal.
Parts List & Pin Mapping for the Standard NEC Build
The most common failure point in DIY IR projects isn't the code; it is the hardware. Cheap, unbranded 'VS1838B' IR receivers from bulk Amazon packs are notoriously susceptible to fluorescent light interference and power rail noise. For a reliable build, use a genuine Vishay TSOP38238.
Spec Sheet & Parts List
| Component | Exact Variant / Part Number | Estimated Cost | Notes |
|---|---|---|---|
| Microcontroller | Arduino Uno R3 (ATmega328P) | $24.00 (Official) / $6.00 (Clone) | Code targets the 16MHz 5V AVR architecture. |
| IR Receiver | Vishay TSOP38238 | $1.50 | 38kHz carrier, internal AGC, high noise immunity. |
| IR Emitter LED | TSAL6200 (940nm) | $0.50 | Must be 940nm. 850nm is for security cameras, not remotes. |
| Driver Transistor | PN2222A (NPN) | $0.10 | Required to drive LED at 100mA pulses (Arduino pins max at 20mA). |
| Resistors | 1kΩ (Base), 10Ω (Collector) | $0.05 | Sets transistor saturation and limits LED current. |
| Decoupling Cap | 10µF Electrolytic + 100nF Ceramic | $0.20 | Placed directly across receiver VCC/GND. |
Pin Mapping Table
| Module / Component | Arduino Uno R3 Pin | Hardware Constraint |
|---|---|---|
| TSOP38238 OUT (Data) | D2 | Any digital pin works for receiving. |
| PN2222A Base (via 1kΩ) | D3 | Must be a PWM/Timer pin. On Uno, D3 uses Timer 2, which IRremote uses for sending. |
| TSOP38238 VCC | 5V | Do not power from 3.3V on a 5V Uno. |
| TSOP38238 GND | GND | Shared ground with emitter circuit. |
Wiring and Complete Compilable Code (Arduino Uno R3)
This code targets the Arduino Uno R3 (AVR) using the modern IRremote v4.x API. It acts as a sniffer that prints decoded hex values to the serial monitor, and if it detects a specific 'Power' button code (NEC protocol), it blasts a response.
Prerequisite: Install 'IRremote' by shirriff, z3t0, ArminJo via the Arduino Library Manager. Ensure you are on version 4.0 or higher.
/*
* IR Sniffer and Blaster - IRremote v4.x
* Target Board: Arduino Uno R3 (AVR ATmega328P)
* Library: IRremote (v4.2.0+)
*/
#include
// --- PIN DEFINITIONS ---
const uint8_t PIN_IR_RECV = 2; // TSOP38238 Data Out
const uint8_t PIN_IR_SEND = 3; // PN2222A Base Resistor (Timer 2 on Uno)
const uint8_t PIN_STATUS_LED = 13; // Built-in LED for visual feedback
// --- PROTOCOL CONSTANTS ---
// Replace these with the actual hex codes captured from your specific remote
const uint32_t NEC_POWER_BUTTON_CODE = 0x00FF6897;
const uint16_t NEC_ADDRESS = 0x0000;
void setup() {
Serial.begin(115200);
while (!Serial); // Wait for serial port on native USB boards (skips on Uno)
pinMode(PIN_STATUS_LED, OUTPUT);
// Initialize Receiver and Sender
// ENABLE_LED_FEEDBACK blinks the built-in LED when receiving
IrReceiver.begin(PIN_IR_RECV, ENABLE_LED_FEEDBACK);
IrSender.begin(PIN_IR_SEND);
Serial.println(F("IR Remote Library v4.x Initialized."));
Serial.println(F("Point your remote at the TSOP38238 and press a button."));
}
void loop() {
// Check if a new IR frame has been received
if (IrReceiver.decode()) {
// ERROR HANDLING: Check for overflow or noise
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
Serial.println(F("ERROR: Buffer overflow. Signal too long or noise."));
IrReceiver.resume();
return;
}
// Print the raw summary
Serial.print(F("Protocol: "));
Serial.println(IrReceiver.decodedIRData.protocol);
Serial.print(F("Hex Value: 0x"));
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
// Decision Logic: If it's our target NEC Power button, blast a response
if (IrReceiver.decodedIRData.protocol == NEC &&
IrReceiver.decodedIRData.decodedRawData == NEC_POWER_BUTTON_CODE) {
Serial.println(F(">> Match! Blasting response..."));
digitalWrite(PIN_STATUS_LED, HIGH);
// Send NEC command: Address, Command, Repeats
// Note: In v4.x, we use the specific send function or sendNEC
IrSender.sendNEC(NEC_ADDRESS, 0x00FF9867, 2); // 0x00FF9867 is a dummy 'Mute' command
digitalWrite(PIN_STATUS_LED, LOW);
// Mandatory delay after sending to let the hardware timer reset
delay(100);
}
// CRITICAL: Re-enable the receiver to catch the next signal
IrReceiver.resume();
}
}
Debugging: Exact Error Strings and Ranked Causes
When an IR build fails, it usually fails in one of three specific ways. Before rewriting your code, execute these first three things to check:
- Ambient Light Saturation: Point the sensor away from windows and CFL/LED bulbs. To prove this is the issue, slide a cardboard toilet paper tube over the TSOP sensor to block peripheral light. If decoding suddenly works, you need a physical shroud or a higher-quality Vishay sensor with better optical filtering.
- Carrier Frequency Mismatch: Most remotes are 38kHz. If you are trying to decode an RC6 remote (often used by Microsoft/Xbox or some European TVs), it uses a 36kHz carrier. A 38kHz TSOP will output garbage or 'UNKNOWN' for a 36kHz signal. Swap to a TSOP38236.
- Power Rail Noise: The VS1838B clones draw erratic current when hit by IR pulses, causing VCC sag that resets their internal AGC. Solder a 10µF electrolytic and a 100nF ceramic capacitor directly across the VCC and GND legs of the receiver.
Quoted Error Strings & Fixes
Error 1: Recv: UNKNOWN, Hash: 12345678 or Protocol: UNKNOWN
- Cause A (Most Likely): The remote uses a proprietary or unsupported protocol (e.g., certain Mini-Split ACs use massive 200+ bit frames that exceed the default 100-byte buffer).
- Cause B: The IR LED on your remote is dying, producing a weak 38kHz envelope that the receiver chops into fragmented noise.
- Fix: Increase the buffer size in the library by adding
#define RAW_BUFFER_LENGTH 750before the#include <IRremote.hpp>line. If it still fails, use the raw dump example to manually map the microsecond timings.
Error 2: #error "Pin 3 is not a valid send pin for this timer" (or similar Timer conflict)
- Cause: On AVR boards, sending IR requires hardware timers to generate the precise 38kHz PWM carrier.
IRremotev4.x defaults to Timer 2 (Pin 3 on Uno). If you are using a library likeServo.horSoftwareSerial.h, they may have hijacked Timer 2. - Fix: Move your IR send pin to D9 (Timer 1) and configure the library to use it, or disable the conflicting library. You cannot use Pin 3 for IR sending and Pin 9/10 for Servos simultaneously on an Uno.
Error 3: 'IRrecv' does not name a type or 'irrecv' was not declared in this scope
- Cause: You are copying code from a 2018 tutorial written for
IRremotev2.x, but you installed v4.x. The object-oriented syntax changed completely. - Fix: Delete
IRrecv irrecv(PIN);andirrecv.enableIRIn();. Replace them with the v4.x syntax used in the code block above:IrReceiver.begin(PIN_IR_RECV, ENABLE_LED_FEEDBACK);.
Extending the Build: From Sniffer to Smart Home Blaster
Once you have the sniffer working, the immediate next step is usually extending the range to control a room. Do not wire an IR LED directly to an Arduino GPIO pin. The ATmega328P absolute maximum DC current per I/O pin is 40mA, and the recommended continuous current is 20mA. An IR LED needs 100mA pulses to achieve a 10-meter range; pulling 100mA from Pin 3 will permanently degrade the silicon and cause voltage brownouts.
The Transistor Driver Circuit (Do Not Skip)
To extend your build into a high-power blaster, use the PN2222A NPN transistor included in the parts list. Here is the bench math for the biasing resistors:
- Target Collector Current ($I_c$): 100mA (for the TSAL6200 LED).
- Transistor Gain ($h_{FE}$): ~100 (from the ON Semi PN2222A Datasheet).
- Base Current ($I_b$) needed: $100mA / 100 = 1mA$.
- Saturation Overdrive: To ensure the transistor acts as a hard switch (fully saturated) and doesn't dissipate heat, we overdrive the base by 3x. Target $I_b = 3mA$.
- Base Resistor ($R_b$): $(5V - 0.7V_{be}) / 3mA = 1.43k\Omega$. A standard 1kΩ resistor is perfect.
- Collector Resistor ($R_c$): To limit the LED current to 100mA assuming a 1.2V LED forward voltage and 0.2V transistor saturation voltage: $(5V - 1.2V - 0.2V) / 0.1A = 36\Omega$. However, because the IR signal is a 33% duty cycle PWM, we can safely push the peak current higher. A 10Ω resistor yields ~360mA peaks, which the TSAL6200 can handle in short pulses, giving you massive range.
IRrecvDumpV3 example sketch included in the IRremote library. It automatically formats the output into copy-pasteable C++ arrays and raw timing buffers, saving you hours of manual hex translation.
Final Recommendation & Next Steps
Stop guessing with generic sensor kits. Order a genuine Vishay TSOP38238 receiver and a TSAL6200 940nm emitter. Standardize your codebase on IRremote v4.x for AVR boards, and strictly use a PN2222A transistor driver for your blaster circuit. This exact combination eliminates 99% of the ambient light noise, timer conflicts, and weak-signal failures that plague beginner IR builds. Once your sniffer reliably dumps hex codes to the serial monitor, your only remaining task is mapping those codes to your home automation logic.






