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.

IR ReceiverMini Remote

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

[wp_ad_camp_1]

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

Also edit your /boot/config.txt file and add:

dtoverlay=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

BerryIMU Raspberry Pi Gyroscope Accelerometer

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

[wp_ad_camp_1]

42 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

      1. Your Python Code is simple, however, will not work.
        The Python-lirc package wants a valid lircrc file to be present, and it seems, it parses the button combinations from there.

        I have tested it to be working well, provided there is a valid licrc file and stores the buttons combinations that are expected in the licrc format.

        The C Program works flawlessly with an empty licrc file, whereas the python one cannot.
        I have raised an issue here about the same here : https://github.com/tompreston/python-lirc/issues/5

        Hope the author will respond soon.

        So anyone who cannot get it to work inb Python, please make sure you have a valid entries like below in the licrc file.

        begin
        button = B_POWER
        prog = myprogram
        config = B_POWER
        end

        for each of your buttons.

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

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

  4. After running sudo /etc/init.d/lirc stop I get several messages saying /etc/lirc/hardware.config can’t be found. The file is definitely there. Any idea why this might be happening?

  5. Hey Hari,
    Do i have to use three LEDs to GPIOs 23, 24 & 25, and a 270Ω on the GND or can i connect the ir receiver directly to the GPIO pins?? without the led’s and the 270Ω. I’m interested in using it only to control my Openelec.

  6. Thanks very much for the tutorial. Worked great for me. I have a Pi with 16×2 LCD in my car reading OBDII data through USB, displaying speed, MPG, etc., and playing audio files into my car stereo through the aux in. (The stereo’s user interface is the pits.) Now it’s being controlled with the remote for the car stereo, and it’s fantastic! And all in Java. So sweet.

  7. Hello,

    January 25th 2015: Marc W. in the comments pointed out that in the 3.18.x RaspberryPi firmware you must modify one additional file for the lirc-rpi kernel extension to be loaded:

    Edit your /boot/config.txt file and add:

    dtoverlay=lirc-rpi,gpio_in_pin=18

  8. Hi i have a problem when i try to do the quick test in the part of:

    mode2 -d /dev/lirc0

    I get this:

    mode2: could not get file information for /dev/lirc0
    mode2: default_init(): No such file or directory

  9. Hi

    Thank’s you very much for this nice lirc DIY but i was unable to find /dev/lirc0 until i found a “trick” wich is actually a prerequisite point !
    Please, consider @diego master comment and adding a chapter about the declaration of dtoverlay=lirc-cpi in the boot config.txt for a happy ending !

    Thanks

  10. I follow this great article for my IR LED and Receiver Installation, I used it in my Raspberry Pi control Room Temprature with Heater and Fan which combine a bunch of different sensor, smart devices to work together including Raspberry Pi, Smart Plug, Temperature Sensor, IR Receiver and IR LED. https://github.com/polease/HomeAutomation

  11. Greetings!!..
    While running … (irrecord -d /dev/lirc0 ~/lircd.conf) this command i face a problem like this file lircd.conf does not contain valid data…How to rectify that?give me sugesstion to overcome this error.

  12. I have followed this tutorial to the letter several times and I still can’t get lirc install on my Pi. I get all the way to running a quick test and I get an error saying sudo /etc/init.d/lirc stop coomand not found then when i try to run the next line it says “using driver devinput on device /dev.lirc0 cannot initiate device /dev/lirc0. Can anyone help me figure out what I did wrong

  13. Ik krijg het ook niet voorelkaar.
    bij sudo /etc/init.d/lirc stop
    krijg ik de melding sudo: /etc/init.d/lirc: opdracht niet gevonden.
    bij het komando mode2 -d / dev / lirc0
    Too many arguments.
    Kan het te maken hebben met de versie op raspberry?

  14. re:
    Ik krijg het ook niet voorelkaar.
    bij sudo /etc/init.d/lirc stop
    krijg ik de melding sudo: /etc/init.d/lirc: opdracht niet gevonden.
    bij het komando mode2 -d / dev / lirc0
    Too many arguments.
    Kan het te maken hebben met de versie op raspberry?
    ________________________________________
    yep, me too

  15. WiringPi is no longer available in the new Raspberry Pi os (for Pi4). Is there any way to make this tuto working in new RPI devices?

  16. Hello,

    Thank you Mark for this wonderful tutorial and all the others who have contributed to it.

    In the tutorial, all the three LEDs are in toggle mode. (Key press changes the state of the LED. Same key press, again, changes it back to its original state.)
    I would like one of the LED to give a pulse output of say 500uSec.

    What changes do I make to the ‘C’ code?
    I am not good at C so any help is much appriciated.

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.