Receiving Infrared Remote Codes
| Difficulty | Intermediate |
|---|---|
| Category | Inputs |
| Supported boards | Arduino Uno R3 and compatible ATmega328P boards |
| Time needed | 45 minutes |
| Prerequisites | Digital and Analog, and When Each Applies |
| Tested board | Not yet verified |
| Tested on | Not yet verified |
| Arduino IDE version | Not yet verified |
| Library | Not yet verified |
What it does
A small three-pin receiver that listens for the infrared flashes a remote control sends, and a 21-button remote to send them. Point, press, and your sketch gets a number.
It is the cheapest way to control a project from across a room, and the receiver will also decode most of the remotes already in the house, which makes it more useful than it first looks.
Before you begin
Required parts and tools
- An Arduino Uno or compatible board.
- One IR receiver and remote kit. This is Siratek product 4141.
- A CR2025 coin cell for the remote, if one is not already fitted.
- Three jumper wires.
Check the remote first
The remote takes a CR2025, and these kits almost always ship with a clear plastic tab sticking out of the battery compartment that keeps the cell from making contact in transit.
Pull it out. A remote that does nothing, with a receiver that is wired correctly, is very often just this.
If there is no tab and still nothing, slide the holder out from the bottom edge and check the cell is there and the right way up, positive side towards the printed +.
The receiver’s three pins
The receiver is a small black blob on a three-pin lead, typically a VS1838B or similar. It contains a photodiode, an amplifier, a 38 kHz filter and a demodulator, which is a lot inside something that size.
Its pin order is not the one you would guess. With the domed face towards you and the legs downward, the usual order is OUT, GND, VCC — the output first, not the power.
Wiring it as VCC GND OUT by habit puts 5 V on the output pin. These parts often survive it, but not always, and the symptom afterwards is a receiver that reads nothing ever again.
If yours is on a small breakout board rather than a bare lead, read the silkscreen. If it is bare, check the datasheet for the part number moulded into it, or probe carefully: the two outer legs differ, and the middle one is ground on every common variant.
Why 38 kHz
Infrared is everywhere: sunlight, filament bulbs, body heat, this library’s own flame sensor. A receiver that simply watched for infrared would be swamped.
So remotes do not send steady light. They send light flickering at about 38 kHz, and the receiver is tuned to that frequency and ignores everything else. The data is in how long the flickering bursts last, not in the flickering itself.
Two consequences. Direct sunlight can still overwhelm it, so range falls dramatically outdoors. And the receiver’s output is already the demodulated signal, which is why it is one plain digital pin rather than anything exotic.
Read your own codes
Nearly every tutorial for this part prints a list of codes for exactly this remote. Do not copy them, including from here.
Code sets differ between batches of visually identical remotes, and libraries have changed how they report values between major versions, so a list copied from anywhere has two ways to be wrong. The first sketch below prints whatever your remote actually sends, which takes two minutes and is correct by construction.
Pin reference
| Receiver pin | Connect to | Purpose | Notes |
|---|---|---|---|
OUT |
Uno D2 |
Demodulated signal | Usually the pin nearest one edge, not the middle |
GND |
Uno GND |
Ground | The middle pin on common variants |
VCC |
Uno 5V |
Power | 2.7 to 5.5 V |
Wiring steps
- Unplug the USB cable.
- Identify the three legs. Confirm which is
OUTbefore connecting anything. GNDtoGND.VCCto5V.OUTtoD2.- Plug the USB cable back in.
- Pull the plastic tab out of the remote.
Software and libraries
Install IRremote through Library Manager.
Note the version. IRremote changed substantially at version 3, and sketches written for version 2 do not compile against version 3 without changes. The code below is written for version 3 and later, which is what Library Manager installs today. Record the version you used, because a sketch that compiled last year may not compile now.
Minimal working example
// Siratek: print whatever the remote sends. Write the numbers down.
#include <IRremote.hpp>
const int receiverPin = 2;
void setup() {
Serial.begin(9600);
IrReceiver.begin(receiverPin);
Serial.println("Siratek: press each button in turn.");
}
void loop() {
if (IrReceiver.decode()) {
Serial.print("command 0x");
Serial.print(IrReceiver.decodedIRData.command, HEX);
Serial.print(" address 0x");
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(" protocol ");
Serial.println(getProtocolString(IrReceiver.decodedIRData.protocol));
IrReceiver.resume();
}
}
Press every button once and keep the list. Those commands are the only ones that matter for your remote.
resume() must be called or nothing further is decoded. Leaving it out gives you exactly one button press and then silence, which looks like a hardware fault.
Most of these remotes use the NEC protocol, and the library will say so. The address is the same for every button on one remote, which is how you can ignore the television remote while responding to this one.
Acting on buttons
// Siratek: using the codes you recorded. Replace these with your own.
#include <IRremote.hpp>
const int receiverPin = 2;
const int ledPin = 8;
// From the sketch above. Yours will differ.
const uint16_t BUTTON_ONE = 0x0C;
const uint16_t BUTTON_TWO = 0x18;
bool lampOn = false;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
IrReceiver.begin(receiverPin);
}
void loop() {
if (!IrReceiver.decode()) {
return;
}
// A held button repeats. Ignore the repeats.
if (!(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
switch (IrReceiver.decodedIRData.command) {
case BUTTON_ONE:
lampOn = true;
Serial.println("on");
break;
case BUTTON_TWO:
lampOn = false;
Serial.println("off");
break;
}
digitalWrite(ledPin, lampOn);
}
IrReceiver.resume();
}
The repeat check is what makes this feel right. Hold a button down and an NEC remote sends a short repeat frame every hundred milliseconds or so; without the check, a toggle would flicker on and off while your thumb rested on the key.
A note on timers
IRremote uses a hardware timer to measure the pulse widths, and on an Uno that is Timer2 by default, which is also the timer behind analogWrite() on pins 3 and 11.
So PWM on those two pins stops working once IRremote is active. If an LED you were dimming goes full brightness the moment you add the receiver, that is why, and moving it to pin 5, 6, 9 or 10 fixes it. The Servo library takes Timer1 for similar reasons, so a sketch using both has lost PWM on four of the six PWM pins.
Expected result
A line of output per button press, with the same address throughout and a different command for each key. Range should be several metres indoors, falling off sharply if you point the remote away or stand in bright sunlight.
Point a phone camera at the remote’s LED while pressing a button: most phone cameras see infrared, and the LED will appear to flicker violet-white on screen. It is a quick way to prove the remote is transmitting before you suspect the receiver.
Troubleshooting
| Symptom | Likely cause | Check or fix |
|---|---|---|
| Nothing at all | Plastic tab still in the remote | Pull it out |
| Nothing, tab removed | Receiver pin order | OUT is usually an outer pin, not the middle |
| Nothing, and the receiver got warm | 5 V applied to the output | It may be damaged; try another |
| Exactly one press then silence | resume() not called |
Call it after every decode |
| Codes differ from a published list | Normal between batches | Use the ones you recorded |
| Sketch will not compile | IRremote version 2 versus 3 | Check which version is installed |
| A held button toggles repeatedly | Repeat frames | Test the repeat flag |
| Works indoors, not outdoors | Sunlight swamping the receiver | Shade it |
| Short range | Weak cell, or off-axis | Replace the CR2025; aim squarely |
| PWM on pins 3 or 11 stopped | IRremote has taken Timer2 | Use 5, 6, 9 or 10 |
| Another remote triggers it | Same protocol, different address | Check the address field too |
Next steps
- Easier first: Read a Push Button, for input without the protocol.
- Related products: a relay to switch something real, or a servo to move it.
- Next project: a remote-controlled lamp, combining this with the relay tutorial and its safety section.
Sources and attribution
All text, wiring guidance and code in this tutorial are original Siratek work.
- The 21-button remote and its CR2025 cell were read from the Siratek product photographs for item 4141.
- IRremote library documentation for the version 3 interface and the timer it uses on the Uno.
Button codes are deliberately not listed, because they vary between batches of identical-looking remotes and between library versions; the tutorial records the reader’s own instead. Receiver pin order is given as the common arrangement with a warning to confirm it. No third-party tutorial text, diagrams, photographs or code has been reproduced here.

