If you want to build a reliable IR Arduino remote control setup, skip the generic black cylinder sensors that come in starter kits. The definitive pick for 90% of hobbyist projects is the Vishay TSOP38238 receiver paired with the Arduino-IRremote v4.x library, running on an Arduino Nano v3 (ATmega328P). The cheap VS1838B sensors fail unpredictably under modern PWM LED lighting, while the TSOP38238 features an automatic gain control (AGC) circuit that rejects optical noise.
This guide gives you the exact parts, the optimized wiring with an RC filter, fully compilable v4.x code, and the specific debugging paths for the most common IR errors.
The Verdict: Which IR Receiver and Library to Choose
Before buying parts, you need to make two decisions: the hardware receiver and the software library. Here is the decision matrix based on real-world bench testing.
| Receiver Model | Carrier Freq | AGC / Noise Rejection | Best Use Case | Verdict |
|---|---|---|---|---|
| VS1838B (Generic) | 38 kHz | Poor (Fails near CFL/LED bulbs) | Quick bench tests in dim rooms | Avoid for permanent installs |
| TSOP38238 (Vishay) | 38 kHz | Excellent (Rejects continuous noise) | Living room, desktop, bright areas | DEFAULT PICK |
| TSOP4838 (Vishay) | 38 kHz | Excellent (Optimized for low voltage) | Battery-powered 3.3V builds | Pick only if running 3.3V logic |
IRLremote unless you are strictly using hardware interrupts on an ATtiny with tight flash constraints.
Parts List and Spec Sheet
This build targets the Arduino Nano v3 (ATmega328P) due to its compact breadboard footprint, but the code and wiring are 100% compatible with the Arduino Uno R3.
| Component | Exact Part / Spec | Est. Price (2026) | Notes |
|---|---|---|---|
| Microcontroller | Arduino Nano v3 (ATmega328P, 5V/16MHz) | $4.00 - $8.00 | Ensure it has the CH340 or FT232RL USB chip |
| IR Receiver | Vishay TSOP38238 | $1.50 - $2.50 | 38kHz, NEC protocol compatible |
| Current Limiter | 100Ω Resistor (1/4W) | $0.05 | Protects the internal LED from supply spikes |
| Decoupling Cap | 4.7µF Electrolytic Capacitor | $0.10 | Stabilizes VCC during high-current draw pulses |
| Remote | Generic 24-Key IR Remote (NEC protocol) | $2.00 | Commonly bundled with RGB LED strip kits |
Pin Mapping and Wiring Steps
The TSOP38238 datasheet explicitly recommends an RC filter on the VCC line to suppress power supply ripple, which is the leading cause of "ghost" IR triggers. Do not wire VCC directly to the Arduino 5V pin without this filter.
| TSOP38238 Pin | Function | Arduino Nano Pin / Component |
|---|---|---|
| 1 (OUT) | Demodulated Signal | D2 (Hardware Interrupt 0) |
| 2 (GND) | Ground | GND |
| 3 (VS / VCC) | Supply Voltage | 5V (via 100Ω resistor) |
Numbered Wiring Steps
- Place the TSOP38238 on the breadboard. Identify pin 1 (OUT) by the small notch or flat edge indicator on the front of the epoxy body.
- Wire the RC Filter: Insert the 100Ω resistor between the Nano's 5V pin and TSOP Pin 3. Place the 4.7µF capacitor between TSOP Pin 3 and TSOP Pin 2 (GND). Ensure the capacitor's negative stripe faces GND.
- Connect Ground: Run a jumper from TSOP Pin 2 to the Nano's GND pin.
- Connect Signal: Run a jumper from TSOP Pin 1 (OUT) to the Nano's D2 pin. We use D2 because it maps to INT0, allowing the IRremote library to use hardware interrupts for precise timing without blocking your main loop.
- Verify Power: Plug the Nano into USB. Use a multimeter to verify you read 4.8V to 5.2V across the capacitor. If it reads 3.3V, your Nano is configured for 3.3V logic and you must swap to a TSOP4838.
Complete Compilable Code (Arduino-IRremote v4.x)
The v4.x API shifted from object-oriented instantiation (IRrecv irrecv(PIN)) to a global singleton (IrReceiver). The code below includes pin definitions, repeat-flag error handling, and a structured switch-case for a standard NEC 24-key remote.
/*
* IR Arduino Remote Receiver - NEC Protocol
* Target: Arduino Nano v3 (ATmega328P)
* Library: Arduino-IRremote v4.x
* Hardware: Vishay TSOP38238 on Pin D2
*/
#include
// --- PIN DEFINITIONS ---
const int IR_RECEIVE_PIN = 2; // Must be an interrupt-capable pin
const int STATUS_LED_PIN = 13; // Nano onboard LED
void setup() {
Serial.begin(115200);
// Initialize the IR receiver singleton
// ENABLE_LED_FEEDBACK blinks the onboard LED when a signal is received
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
pinMode(STATUS_LED_PIN, OUTPUT);
Serial.println(F("IR Receiver ready. Awaiting NEC signals..."));
}
void loop() {
if (IrReceiver.decode()) {
// 1. Check for repeat codes (user holding the button down)
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
// Ignore repeats to prevent flooding serial or toggling states rapidly
IrReceiver.resume();
return;
}
// 2. Verify protocol is NEC
if (IrReceiver.decodedIRData.protocol != NEC) {
Serial.print(F("Warning: Non-NEC protocol detected. Protocol ID: "));
Serial.println(IrReceiver.decodedIRData.protocol);
IrReceiver.resume();
return;
}
// 3. Process the 8-bit command byte
uint8_t command = IrReceiver.decodedIRData.command;
Serial.print(F("NEC Command Received: 0x"));
Serial.println(command, HEX);
// Decision path based on specific remote buttons
switch (command) {
case 0x45: // Power Button (Generic 24-key remote)
Serial.println(F("Action: Toggle Power"));
digitalWrite(STATUS_LED_PIN, !digitalRead(STATUS_LED_PIN));
break;
case 0x46: // Mode / Function Button
Serial.println(F("Action: Cycle Mode"));
// Insert mode cycling logic here
break;
case 0x47: // Mute / Pause
Serial.println(F("Action: Pause"));
break;
default:
Serial.print(F("Unmapped Command: 0x"));
Serial.println(command, HEX);
break;
}
// 4. CRITICAL: Reset the state machine to receive the next signal
IrReceiver.resume();
}
}
Debugging: Exact Errors and the "First Three" Checklist
IR debugging usually falls into two categories: compilation failures from library version mismatches, or runtime "ghost" readings. When your build fails, run through this checklist.
The First Three Things to Check
- Power Supply Ripple: If the serial monitor spits out random hashes when no remote is pressed, your 5V rail is noisy. Did you include the 100Ω resistor and 4.7µF capacitor? USB power from cheap laptop hubs often introduces 50mV+ ripple that triggers the TSOP's AGC.
- Line of Sight and Distance: The TSOP38238 is rated for 35 meters in ideal conditions, but through a plastic project enclosure, range drops by 60%. Ensure the epoxy dome is not painted over or blocked by translucent PLA/PETG.
- Library Version Mismatch: If you copied code from a 2019 tutorial, it uses v2.x syntax. You must update the code to use
IrReceiver.decode()instead ofirrecv.decode(&results).
Ranked Causes for Common Error Strings
| Exact Error String | Root Cause | Fix |
|---|---|---|
error: 'IRrecv' does not name a type |
Using v2.x code with the v4.x library installed in the IDE. | Replace IRrecv irrecv(PIN); with IrReceiver.begin(PIN); as shown in the code block above. |
Protocol=UNKNOWN Hash=0x... |
The remote uses a proprietary or unsupported protocol (like Sony SIRC or RC6), or the carrier frequency is not 38kHz. | Remove the protocol check in code. Read IrReceiver.decodedIRData.decodedRawData to map the raw hash instead of the 8-bit command. |
| Random serial output without pressing buttons | Optical noise from CFL bulbs or PWM-dimmed LED room lighting overriding the AGC. | Swap VS1838B for TSOP38238. Add a physical IR-pass optical filter (dark red acrylic) over the sensor dome. |
Extending or Simplifying the Build
Once you have reliable signal decoding, you need to decide how to scale the project based on your end goal.
How to Extend: Adding High-Voltage Relays
If you are using this IR Arduino remote setup to control mains-voltage appliances (like a lamp or fan), do not drive a relay coil directly from the Nano's D3 pin. The ATmega328P GPIO can only source 20mA safely.
The Fix: Use a 5V optocoupler relay module (like the Songle SRD-05VDC-SL-C based modules). Wire the Nano D3 to the module's IN pin, and power the module's VCC from the Nano's 5V pin. The optocoupler provides galvanic isolation, protecting your microcontroller from inductive flyback spikes when the relay coil de-energizes.
How to Simplify: Shrinking to an ATtiny85
If the Arduino Nano is too physically large for your enclosure, you can port this exact logic to an ATtiny85. However, the standard Arduino-IRremote library consumes ~12KB of flash, which leaves almost no room for your application logic on the 8KB ATtiny85.
The Fix: Switch to the IRsmallDecoder library. It is specifically engineered for constrained AVRs, consuming less than 2KB of flash by hardcoding only the NEC protocol state machine and dropping support for the 40+ other protocols you likely aren't using.
For deeper hardware specifications regarding optical noise rejection thresholds, refer to the Vishay IR Receiver Modules documentation or the Adafruit IR Sensor overview for alternative wiring topologies.






