Tutorial: Arduino and Infra-red control
This is chapter thirty-two of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe.
The first chapter is here, the complete series is detailed here. This tutorial is compatible with Arduino v1.0.
Welcome back fellow Arduidans!
In this article we will look at something different to the usual, and hopefully very interesting and useful – interfacing our Arduino systems with infra-red receivers. Why would we want to do this? To have another method to control our Ardiuno-based systems, using simple infra-red remote controls.
A goal of this article is to make things as easy as possible, so we will not look into the base detail of how things work - instead we will examine how to get things done. If you would like a full explanation of infra-red, perhaps see the page on Wikipedia. The remote controls you use for televisions and so on transmit infra-red beam which is turned on and off at a very high speed – usually 38 kHz, to create bits of serial data which are then interpreted by the receiving unit. As the wavelength of infra-red light is too high for human eyes, we cannot see it. However using a digital camera – we can. Here is a demonstration video of IR codes being sent via a particularly fun kit – the adafruit TV-B-Gone:
Now to get started. You will need a remote control, and a matching IR receiver device. You can purchase a matching set for a good price, such as this example:
Or you may already have a spare remote laying around somewhere. I kept this example from my old Sony Trinitron CRT TV after it passed away:
It will more than suffice for a test remote. Now for a receiver – if you have purchased the remote/receiver set, you have a nice unit that is ready to be wired into your Arduino, and also a great remote that is compact and easy to carry about. To connect your receiver module – as per the PCB labels, connect Vcc to Arduino 5V, GND to Arduino GND, and D (the data line) to Arduino digital pin 11.
Our examples use pin 11, however you can alter that later on. If you are using your own remote control, you will just need a receiver module. These are very cheap, and an ideal unit is the Vishay TSOP4138 (data sheet .pdf). These are available from element-14 and the other usual retail suspects. They are also dead-simple to use. Looking at the following example:
From left to right the pins are data, GND and Vcc (to Arduino +5V). So it can be easily wired into a small breadboard for testing purposes. Once you have your remote and receiver module connected, you need to take care of the software side of things. There is a new library to download and install, download it from here. Extract the IRremote folder and place into the ..\arduino-002x\libraries folder. Then restart your Arduino IDE if it was already open.
Using Arduino v1.0? Open the file “IRRemoteInt.h” in the library folder, and change the line
#include <WProgram.h>
to
#include <Arduino.h>
Then save and close the file, restart the Arduino IDE and you’re set.
With our first example, we will receive the commands from our remote control and display them on the serial monitor. Download and run the following sketch:
// example 32.1 - IR receiver code repeater
// http://tronixstuff.com/tutorials > chapter 32
// based on code by Ken Shirriff - http://arcfn.com
#include <IRremote.h> // use the library
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;
void setup()
{
Serial.begin(9600); // for serial monitor output
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results)) // have we received an IR signal?
{
Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
irrecv.resume(); // receive the next value
} // Your loop can do other things while waiting for an IR command
}
Open the serial monitor box, point your remote control to the receiver and start pressing away. You should see something like this:
What have we here? Lots of hexadecimal numbers. Did you notice that each button on your remote control resulted in an individual hexadecimal number? I hope so. The number FFFFFFFF means that the button was held down. The remote used was from a yum-cha discount TV. Now I will try again with the Sony remote:
This time, each button press resulted in the same code three times. This is peculiar to Sony IR systems. However nothing to worry about. Looking back at the sketch for example 32.1, the
if (irrecv.decode(&results))
section is critical – if a code has been received, the code within the if statement is executed. The hexadecimal code is stored in the variable
results.value
with which we can treat as any normal hexadecimal number. At this point, press a few buttons on your remote control, and take a note of the matching hexadecimal codes that relate to each button. We will need these codes for the next example…
Now we know how to convert the infra-red magic into numbers, we can create sketches to have our Arduino act on particular commands. As the IR library returns hexadecimal numbers, we can use simple decision functions to take action. In the following example, we use switch…case to examine each inbound code, then execute a function. In this case we have an LCD module connected via I2C, and the sketch is programmed to understand fifteen Sony IR codes. If you don’t have an LCD you could always send the output to the serial monitor.
Furthermore you can substitute your own values if not using Sony remote controls. Finally, this sketch has a short loop after the translateIR(); function call which ignores the following two codes – we do this as Sony remotes send the same code three times. Again. you can remove this if necessary. Note that when using hexadecimal numbers in our sketch we preced them with 0x.
Download the sketch below from here:
// example 32.2 - IR receiver code translator
// for Sony IR codes (ignores 2nd and 3rd signal repeat)
// http://tronixstuff.com/tutorials > chapter 32
// based on code by Ken Shirriff - http://arcfn.com
#include "Wire.h" // for I2C bus
#include "LiquidCrystal_I2C.h" // for I2C bus LCD module http://bit.ly/eNf7jM
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <IRremote.h> // use the library for IR
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight(); // turn on LCD backlight
irrecv.enableIRIn(); // Start the receiver
}
void translateIR() // takes action based on IR code received
// describing Sony IR codes on LCD module
{
switch(results.value)
{
case 0x37EE: lcd.println(" Favourite "); break;
case 0xA90: lcd.println(" Power button "); break;
case 0x290: lcd.println(" mute "); break;
case 0x10: lcd.println(" one "); break;
case 0x810: lcd.println(" two "); break;
case 0x410: lcd.println(" three "); break;
case 0xC10: lcd.println(" four "); break;
case 0x210: lcd.println(" five "); break;
case 0xA10: lcd.println(" six "); break;
case 0x610: lcd.println(" seven "); break;
case 0xE10: lcd.println(" eight "); break;
case 0x110: lcd.println(" nine "); break;
case 0x910: lcd.println(" zero "); break;
case 0x490: lcd.println(" volume up "); break;
case 0xC90: lcd.println(" volume down "); break;
case 0x90: lcd.println(" channel up "); break;
case 0x890: lcd.println(" channel down "); break;
default: lcd.println(" other button ");
}
delay(500);
lcd.clear();
}
void loop()
{
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
for (int z=0; z<2; z++) // ignore 2nd and 3rd signal repeat
{
irrecv.resume(); // receive the next value
}
}
}
And here it is in action:
You might be thinking “why would I want to make things appear on the LCD like that?”. The purpose of the example is to show how to react to various IR commands. You can replace the LCD display functions with other functions of your choosing.
At the start working with infra-red may have seemed to be complex, but with the previous two examples it should be quite simple by now. So there you have it, another useful way to control our Arduino systems. Hopefully you have some ideas on how to make use of this technology. In future articles we will examine creating and sending IR codes from our Arduino. So stay tuned for upcoming Arduino tutorials by subscribing to the blog, RSS feed (top-right), twitter or joining our Google Group. Furthermore, a big thanks to Ken Shirriff for his Arduino library.
Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.









What is the version of Arduino you are using? I had issues running this library on v0022. But it was working properly or earlier versions.
Hello
I am using v22 under Windows 7 x64 – works fine for me.
Can you describe your issues in more detail?
cheers
john
The problem I face is that, it is giving the same code for all the buttons.
It was working in the previous versions for me.
That is very strange. Unfortunately the only solution I can recommend is to revert back to Arduino v21 and see what happens.
john
from 32.2in the second instance of #include for ic2 it is followed by http://bit.ly/enf7jm
this has got me lost could you expand on it
thanks
alex
Hello
For some reason wordpress didn’t allow the library names. I have fixed it now and added them.
The URL is a link to the IR product used in the example.
i am having problems with the line in the sketch (LiquidCrystal_I2C lcd(0×27,16,2))
when i try to verify i recive error lcd does not have name type, libraries have been installed properlly
thanks in advance
alex
Hi Alex
Are you using the DFRobot I2C LCD display, or a different model? The sketch is for the I2C display as mentioned. If you are using a different LCD you will need to adjust it accordingly. If unsure, let me know what type of LCD you have.
john
greetings john
whle i am waiting for the lcd to arrive i was testing the system so as to speak thats when i found im unable to verify
alex
Ok. Did you install the library for the I2C display? http://www.dfrobot.com/image/data/DFR0063/Arduino_library.zip
Hola estoy empezando con arduino y me gusto mucho el codigo ya que pude ponerlo a operar con mi control remoto de sony.
Gracias
Gracias por tu comentario. Realmente lo aprecio. Diviértete con Arduino y la electrónica.
John
Thanks for cool project…
I have one quention about IR library,,why this library can’t upload sketch IR example with board arduino NG or older w/atmega8??
Most likely a memory problem, however I don’t have one of the older boards to test out.
Hey you should check out my project. I can succesfully control a robot using Ken shirriff’s library: http://arduino.cc/forum/index.php/topic,65022.msg475002.html#msg475001
Hey that’s amazing – good on you. Thank you for sharing!
Cheers
John
how to program using the remote to turn on and off 10 pieces of light?
Please be more specific.
I wanted to light the lamp uses 10 pieces of tv remote with IR library. and each button press can turn on the lights tv interchangeably depending on which button is pressed. eg I want to turn on the lights one by one button and turn on the lamp 2 with button 2 and so on ..
Oh ok. Well using my demonstration you can have the Arduino detect various button presses from the remote control. All you need to do is control relays to switch each light on and off.
Hi,
thanks for the efforts put in this blog!
I’m stuggling with this example: I got the IR decoder to work fine, but when I try to customise the code in the IR Reader to my remote control I get absolutely nothing in the serial print – I’ve tried adding a few serial print lines to see if I was at least getting something, but the serial monitor stays completely blank!
I don’t even see the line I added in the setup, or the the translate IR loop…
Here’s my simplified code (no LCD):
#include // use the library for IR
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of ‘irrecv’
decode_results results;
void setup()
{
Serial.println(“setup”);
irrecv.enableIRIn(); // Start the receiver
}
void translateIR() // takes action based on IR code received
// describing Sony IR codes on LCD module
{
Serial.println(“translateIR”);
switch(results.value)
{
case 0xff30cf: Serial.println(” 1 “); break;
case 0xff18e7: Serial.println(” 2 “); break;
case 0xff7a85: Serial.println(” 3 “); break;
default: Serial.println(” other button “);
}
delay(500);
}
void loop()
{Serial.println(“Loop”);
if (irrecv.decode(&results)) // have we received an IR signal?
{
Serial.println(“Received”);
translateIR();
}
}
Oh my… I forgot to add serial.begin (9600) at the beginning!!!
Well – problem fixed.
Now I have a new problem: the last number I pressed keeps repeating (twice every second) and I cannot press any new key after the 1st one. Any suggestions?
Updated code:
#include // use the library for IR
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of ‘irrecv’
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void translateIR() // takes action based on IR code received
// describing Sony IR codes on LCD module
{
switch(results.value)
{
case 0xff30cf: Serial.println(” 1 “); break;
case 0xff18e7: Serial.println(” 2 “); break;
case 0xff7a85: Serial.println(” 3 “); break;
default: Serial.println(” other button “);
}
delay(500);
}
void loop()
{
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
}
}
That’s really odd, your sketch looks fine.
What happens when you run the first example in the tutorial? Do any values repeat when you press a button?
Greetings,
Much appreciation for all of your work!
I am attempting to modify your sketch for use with a regular (non-I2C) LCD (20×4) that I purchased from the wonderful Ms. Fried’s fruity website (URL withheld, not certain what your vendor policy is)..
This is my first attempt at something like this. Note that I moved the First / “listen” lead of the IR Sensor from Digital Pin 11 to Digital Pin 3 , to make room for the LCD’s IO needs.
I am using the “Mini Remote Control” offered by the same vendor I obtained the IR Sensor & LCD from. I am using an Arduino UNO.
When I upload & run the serial recieve sketch, I am able to take note and document the HEX codes transmitted by the remote control via the Serial Monitor.
I am also able to print to the LCD screen using the lcd.println(” Prints to LCD “);
However, when I try to use my modified version of your code, I am unable to get the desired results. I have replaced the hex from the original sketch with that produced by my remote control.
Please, if you can direct me or point out where I have failed, I would appreciate it. I am very eager to learn. I hope that others will be able to benefit from this effort as well! Thank you in advance for any advice and for your time.
Here is a copy of my modified version of Example 32.2:
———————————————————-
#include
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
#include
int receiver = 3; // Notice that I have changed the Dig. IO to make room for the LCD
IRrecv irrecv(receiver);
decode_results results;
void setup()
{
lcd.begin(20, 4); // I am using a 20×4 LCD
Serial.begin(9600);
irrecv.enableIRIn();
}
void translateIR()
{
switch(results.value)
{
// I am only including a few of the cases as I have only test 1-9
case 0xFD08F7: lcd.println(” FD08F7 – 1 “); break;
case 0xFD8877: lcd.println(” FD8877 – 2 “); break;
case 0xFD48B7: lcd.println(” FD48B7 – 3 “); break;
case 0xFD28D7: lcd.println(” FD28D7 – 4 “); break;
// return
default: lcd.println(” other button “);
}
delay(1000);
lcd.clear();
}
void loop()
{
if (irrecv.decode(&results)) {
{
irrecv.resume();
}
}
}
——————————————–
Take note that the in the #include statements have been edited out automatically by wordpress filtering for html tags (I’m assuming..)
Thanks again
Hello
Apologies for the delay in my reply, I have been away on business for most of the last week.
The values returned by your IR controller seem extraordinarily large. For example – 0xFD28D7 is 16,591,063. Hexadecimal numbers are treated as integers (max. 32767) when being computed by the Arduino. You can mention adafruit. I can only suggest you try your IR system with their specific library, the download link is in the product description here – http://www.adafruit.com/products/389. I don’t have their version to test it out, so if you have any more questions about that particular product please try the adafruit support forums.
cheers
john
John,
I hooked this circuit up and loaded the code, and it reads my remote, but displays zeros for every remote button I press. My remote is for an HDTV box and not TV. I tried someone else’s remote from their TV and it was reading out the button hex numbers, so do you have any idea why my remote reads zeros and how I might fix it?
Thanks, Russ
Could be that the manufacturer of your HDTV box is using their own codes (that are not recognisable by the Arduino IR library) to ensure people have to buy a specific type of replacement remote control. If you had a digital storage oscilloscope you could measure the pulses and modify the library, however that’d be somewhat extreme – would be easier to consider using a different remote.
john
I think you’re right because the arduino sees the transmission, but can only report back zeros.
Thanks for your help.
Russ
Great work! This one can be an useful template for a huge number of IR projects. Thanks for sharing
Thanks
Im using a teensy, running the first example all i receive is 0′s, would this be because it doesnt recognize the protocol, or do you think its because of the board?
Try another brand of remote control, for example a Sony. If it is still all zeros then it would be the Teensy’s implementation of Arduino software.
If I want, for example to make a robot go forward. How do I make it run only if I keep the button pressed down?
Get the robot to only run the forward motion for say 100mS when it receives the ‘forward’ command of your choice from IR. Then the user will have to hold down the button to continue forward motion, but it will stop when the button is released.
My favorite electronics parts dealer offers a Vishay TSOP312xx, which they claim to be the successor of the “well known TSOP 1738 Series” However, they offer a variety for frequencies between 30 and 40 kHz.
(The whole series claims being compatible with usual TV Remote Controls.)
Should I stick to the 38 kHz version in general?
Does it make a difference ? If yes, where can I find which is for which … (found no indication in my TV remote nor in the TV manual)
I have a spare Panasonic remote and I think LCD display and Remote is a very convenient User Interface alternative to a Serial PC connection.
Stick to the unit mentioned – the 38 kHz TSOP 4138.
Thanks for the reply! Oh, the datasheet you mentioned shows that your TSOP 41xx also comes in those variations 30 .. 40 kHz . So I will definitely get the 38kHz version, wondering what the others might be good for ???
Not too sure, perhaps for other types of IR systems.