IRimage2001-opt

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

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

  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.

Leave a Reply