IRimage2001

How to Control the GPIO on a Raspberry Pi with an IR Remote

In this post I demonstrate how to use an infrared remote to control the GPIO on a Raspberry Pi.

Normally a remote would be used to control a TV card or XMBC, however they also provide a good interface to control the GPIO on a Raspberry Pi.
Adafruit has a Mini Remote and IR sensor which are perfect for this.

In this example we will use the remote to control a number of LEDs connected to some GPIOs on a Raspberry Pi.

Connect the IR Sensor to the Raspberry Pi

Connecting the IR sensor to a Raspberry Pi is very easy as there are only 3 pins on the sensor, GND, 3v and Output. We will connect the output to GPIO 18. You can choose another pin, just take note of it as you will need to specify this pin when installing LIRC.
We will also connected up three LEDs to GPIOs 23, 24 & 25, and a 270Ω on the GND sound of each LED.

IRwiring2

Here is my setup;

OLED.front 823back_LRG

Installing LIRC

LIRC is a package that allows you to decode infrared signals of many (but not all) commonly used remote controls. LIRC runs as a daemon that will decode IR signals received by the device drivers and provide the information on a socket. We will then write a program in the user space to monitor this socket for input events using the LIRC client library.

1. We need to install LIRC and client libraries.

pi@raspberrypi ~ $ sudo apt-get install lirc liblircclient-dev

2.Then add the two lines below to /etc/modules . This will start the modules up on boot. Pin 18 bellow will be used to take the output from the IR sensor.

lirc_dev
lirc_rpi gpio_in_pin=18

3.Edit /etc/lirc/hardware.conf and have it appear exactly as shown below.

    # /etc/lirc/hardware.conf
    #
    # Arguments which will be used when launching lircd
    LIRCD_ARGS="--uinput"

    # Don't start lircmd even if there seems to be a good config file
    # START_LIRCMD=false

    # Don't start irexec, even if a good config file seems to exist.
    # START_IREXEC=false

    # Try to load appropriate kernel modules
    LOAD_MODULES=true

    # Run "lircd --driver=help" for a list of supported drivers.
    DRIVER="default"
    # usually /dev/lirc0 is the correct setting for systems using udev
    DEVICE="/dev/lirc0"
    MODULES="lirc_rpi"

    # Default configuration files for your hardware if any
    LIRCD_CONF=""
    LIRCMD_CONF=""

3.Reboot

A quick test
To perform a quick test to see if LIRC is working, we need to stop the LIRC daemon and start mode2. mode2 shows the the pulse/space length of infrared signals.

pi@raspberrypi ~ $ sudo /etc/init.d/lirc stop
pi@raspberrypi ~ $ mode2 -d /dev/lirc0

When buttons are pressed on your remote, mode2 will give a similar output to what is shown below.

pulse 627
space 514
pulse 624
space 513
pulse 599
space 521
pulse 618
space 1668
pulse 589
space 532

Record IR codes from your remote

irrecord will help us discover the IR codes used by your remote and assist with creating a conf file which will be used by LIRC.

pi@raspberrypi ~ $ irrecord -d /dev/lirc0 ~/lircd.conf

Once started, irrecord will show detailed instructions on how to setup your remote. However, here is summary;
1.When asked, press all buttons on your remote until asked to stop.
2.Assign a pre-defined name to each button. running irrecord --list-namespace will display a list of available names.

The config file for the Adafruit MinRemote looks like this;

# Please make this file available to others
# by sending it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(default) on Tue Oct  8 07:05:38 2013
#
# contributed by 
#
# brand:                       /home/pi/lircd.conf
# model no. of remote control: 
# devices being controlled by this remote:
#

begin remote

  name  /home/pi/lircd.conf
  bits           16
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9006  4447
  one           594  1648
  zero          594   526
  ptrail        587
  repeat       9006  2210
  pre_data_bits   16
  pre_data       0xFD
  gap          107633
  toggle_bit_mask 0x0

      begin codes
          KEY_1                    0x08F7
          KEY_2                    0x8877
          KEY_3                    0x48B7
          KEY_4                    0x28D7
          KEY_5                    0xA857
          KEY_6                    0x6897
          KEY_7                    0x18E7
          KEY_8                    0x9867
          KEY_9                    0x58A7
          KEY_0                    0x30CF
          KEY_DOWN                 0xB04F
          KEY_LEFT                 0x10EF
          KEY_UP                   0xA05F
          KEY_RIGHT                0x50AF
          KEY_BACK                 0x708F
          KEY_ENTER                0x906F
          KEY_SETUP                0x20DF
          KEY_PAUSE                0x609F
          KEY_PAUSE                0x807F
          KEY_STOP                 0x609F
          KEY_VOLUMEUP             0x40BF
          KEY_VOLUMEDOWN           0x00FF
      end codes

end remote

Now replace the existing conf file (which is most likely empty) with the new one you just created.

pi@raspberrypi ~ $ sudo cp lircd.conf /etc/lirc/lircd.conf

Restart LIRC

pi@raspberrypi ~ $ sudo /etc/init.d/lirc restart

Test the new remote conf file
You can use irw to test the new config. irw sends data from Unix domain socket to stdout
You should get a similar output as below…. This was me pushing the 1, 2 and 3 keys on the remote.

pi@raspberrypi ~ $ irw
0000000000fd08f7 00 KEY_1
0000000000fd08f7 01 KEY_1
0000000000fd08f7 02 KEY_1
0000000000fd8877 00 KEY_2
0000000000fd8877 01 KEY_2
0000000000fd8877 02 KEY_2
0000000000fd48b7 00 KEY_3

Creating your program to control the GPIO

We will use C to write a simple program that will be used to control three LEDs connected to the GPIO.
We will also require WiringPi to control the PINs and use the LIRC client library to get data from the IR sensor.

First, install WiringPi

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ git clone git://git.drogon.net/wiringPi
pi@raspberrypi ~ $ cd wiringPi
pi@raspberrypi ~ $ git pull origin
pi@raspberrypi ~ $ ./build

The code
The code below will allow you to control three LEDs connected to the GPIO of a Raspberry Pi. We will use the 1,2 & 3 buttons on the numerical pad of the Adafruit mini remote to turn these LEDs off and on.
The code includes alot of comments which will help you understand how it works.

#include <wiringPi.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lirc/lirc_client.h>
#include <time.h>


void flipLED (int led);

//The WiringPi pin numbers used by our LEDs
#define LED1 4
#define LED2 5
#define LED3 6

#define ON 1
#define OFF 0

int main(int argc, char *argv[])
{
        struct lirc_config *config;

        //Timer for our buttons
        int buttonTimer = millis();


        char *code;
        char *c;



        //Initiate WiringPi and set WiringPi pins 4, 5 & 6 (GPIO 23, 24 & 25) to output. These are the pins the LEDs are connected to.
        if (wiringPiSetup () == -1)
            exit (1) ;

        pinMode (LED1, OUTPUT);
        pinMode (LED2, OUTPUT);
        pinMode (LED3, OUTPUT);

        //Initiate LIRC. Exit on failure
        if(lirc_init("lirc",1)==-1)
                exit(EXIT_FAILURE);

        //Read the default LIRC config at /etc/lirc/lircd.conf  This is the config for your remote.
        if(lirc_readconfig(NULL,&config,NULL)==0)
        {
                //Do stuff while LIRC socket is open  0=open  -1=closed.
                while(lirc_nextcode(&code)==0)
                {
                        //If code = NULL, meaning nothing was returned from LIRC socket,
                        //then skip lines below and start while loop again.
                        if(code==NULL) continue;{
                                //Make sure there is a 400ms gap before detecting button presses.
                                if (millis() - buttonTimer  > 400){
                                        //Check to see if the string "KEY_1" appears anywhere within the string 'code'.
                                        if(strstr (code,"KEY_1")){
                                                printf("MATCH on KEY_1\n");
                                                flipLED(LED1);
                                                buttonTimer = millis();
                                        }
                                        else if(strstr (code,"KEY_2")){
                                                printf("MATCH on KEY_2\n");
                                                flipLED(LED2);
                                                buttonTimer = millis();
                                        }
                                        else if(strstr (code,"KEY_3")){
                                                printf("MATCH on KEY_3\n");
                                                flipLED(LED3);
                                                buttonTimer = millis();
                                        }
                                }
                        }
                        //Need to free up code before the next loop
                        free(code);
                }
                //Frees the data structures associated with config.
                lirc_freeconfig(config);
        }
        //lirc_deinit() closes the connection to lircd and does some internal clean-up stuff.
        lirc_deinit();
        exit(EXIT_SUCCESS);
}

void flipLED (int led)
{
        //If LED is on, turn it off. Otherwise it is off, so thefore we need to turn it on.
        if(digitalRead(led)==ON)
                digitalWrite(led, OFF);
        else
                digitalWrite(led, ON);
}



Compile the above code with;

pi@raspberrypi ~ $ gcc -o example example.c -lwiringPi -llirc_client

Create an empty lirc file, otherwise lirc will complain;

pi@raspberrypi ~ $ touch /etc/lirc/lircrc

Start it with;

pi@raspberrypi ~ $ sudo ./example

12 thoughts on “How to Control the GPIO on a Raspberry Pi with an IR Remote”

  1. Thanks for the tutorial. I managed to get to the ‘Creating your program to control the GPIO’ but was wondering if you knew how to do that except in Python?
    Thanks,
    Isaac

  2. Great Tutorial! When I run the Code I get this error:
    irexec: could not open config files /home/pi/.lircrc and /etc/lirc/lirc/lircrc
    irexec: No such file or directory
    Do you know what to do?

    1. Fabian
      I must have missed this. Let me know if creating an empty file fixes the issue and I’ll update the blog.

      Mark

      1. Hey Mark

        Awesome write-up. I had the same issue as Fabian and it had been resolved with the introduction of an empty file named ‘lircrc’ in the directory ‘/etc/lirc’. Otherwise I’d say it’s a flawless writeup and one of the best tech blogs I’ve yet seen.

      2. thanks Hari. Please let me know where in the instructions I should place the info of creating the empty lircrc.

  3. Hey Mark,

    Just add it before the last instruction (the one which executes the WiringPi example). By the way, I cited your blog in my site (tweakgeek.in).

Leave a Reply