t r o n i x s t u f f

fun and learning with electronics

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.

Example 32.1

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…

Example 32.2

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 twitterGoogle+, 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.

March 30, 2011 - Posted by | arduino, education, learning electronics, microcontrollers | , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

39 Comments »

  1. 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.

    Comment by Sudar | March 30, 2011 | Reply

    • Hello
      I am using v22 under Windows 7 x64 – works fine for me.
      Can you describe your issues in more detail?
      cheers
      john

      Comment by John Boxall | March 30, 2011 | Reply

      • 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.

        Comment by Sudar | March 31, 2011

      • That is very strange. Unfortunately the only solution I can recommend is to revert back to Arduino v21 and see what happens.
        john

        Comment by John Boxall | March 31, 2011

  2. 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

    Comment by alex | April 6, 2011 | Reply

    • 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.

      Comment by John Boxall | April 6, 2011 | Reply

  3. 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

    Comment by alex | April 7, 2011 | Reply

    • 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

      Comment by John Boxall | April 7, 2011 | Reply

  4. 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

    Comment by alex | April 8, 2011 | Reply

  5. Hola estoy empezando con arduino y me gusto mucho el codigo ya que pude ponerlo a operar con mi control remoto de sony.
    Gracias

    Comment by jose fernando guerrero | May 4, 2011 | Reply

    • Gracias por tu comentario. Realmente lo aprecio. Diviértete con Arduino y la electrónica.
      John

      Comment by John Boxall | May 4, 2011 | Reply

  6. 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??

    Comment by stpdxpdc | May 31, 2011 | Reply

    • Most likely a memory problem, however I don’t have one of the older boards to test out.

      Comment by John Boxall | May 31, 2011 | Reply

  7. 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

    Comment by Kristian Sloth Lauszus | July 8, 2011 | Reply

    • Hey that’s amazing – good on you. Thank you for sharing!
      Cheers
      John

      Comment by John Boxall | July 8, 2011 | Reply

  8. how to program using the remote to turn on and off 10 pieces of light?

    Comment by stpdxpdc | August 7, 2011 | Reply

  9. 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 ..

    Comment by stpdxpdc | August 7, 2011 | Reply

    • 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.

      Comment by John Boxall | August 7, 2011 | Reply

  10. 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();

    }
    }

    Comment by Blaise - Wedding Photographer | August 8, 2011 | Reply

  11. 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();

    }
    }

    Comment by Blaise - Wedding Photographer | August 8, 2011 | Reply

    • 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?

      Comment by John Boxall | August 8, 2011 | Reply

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

    ——————————————–

    Comment by Teasy Pea | October 13, 2011 | Reply

    • Take note that the in the #include statements have been edited out automatically by wordpress filtering for html tags (I’m assuming..)

      Thanks again

      Comment by Teasy Pea | October 13, 2011 | Reply

    • 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

      Comment by John Boxall | October 16, 2011 | Reply

  13. 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

    Comment by Russ | October 28, 2011 | Reply

    • 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

      Comment by John Boxall | October 28, 2011 | Reply

  14. I think you’re right because the arduino sees the transmission, but can only report back zeros.
    Thanks for your help.

    Russ

    Comment by Russ | October 29, 2011 | Reply

  15. Great work! This one can be an useful template for a huge number of IR projects. Thanks for sharing

    Comment by Arduino-avr | December 1, 2011 | Reply

  16. 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?

    Comment by phil | January 5, 2012 | Reply

    • 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.

      Comment by John Boxall | January 6, 2012 | Reply

  17. 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?

    Comment by Adrian | March 7, 2012 | Reply

    • 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.

      Comment by John Boxall | March 8, 2012 | Reply

  18. 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.

    Comment by michael_x | April 26, 2012 | Reply

    • Stick to the unit mentioned – the 38 kHz TSOP 4138.

      Comment by John Boxall | April 26, 2012 | Reply

      • 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 ???

        Comment by michael_x | April 28, 2012

      • Not too sure, perhaps for other types of IR systems.

        Comment by John Boxall | April 29, 2012


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,588 other followers