RPI Computers

Setup Raspberry PI Infrared Remote from terminal

Infrared sensors are really common to devices which need to be controlled from a remote within reduced distances. Typical applications are in remoting TV, media center, robots, air conditioning systems, etc.

With the growth of mass production, their prices have plummeted and can be found on e-commerce websites.

Linux systems have a spread package called LIRC (Linux Infrared Remote Control). This is a really handy package with most common remotes, but it becomes a little tricky when you havea remote not included in LIRC remotes database because you have to know you remote infrared signal map to create your custom configuration file.

A second chance comes from ir-keytable package. This package is really simple to use and allows you to record one by one you remote keys signals and map them to your custom config file, even without knowing signal profile of your remote.

In this article, I’ll show how to connect your Raspberry PI to an IR receiver and control it from a remote with ir-keytable. For this article, I’m going to use a Raspberry PI Zero W, but the same procedure works also with newer Raspberry PI boards.

How Infrared Sensors Work

Before starting with terminal commands, let’s dig on how they works. A very good explaination is available at Adafruit Infrared Sensor description page:

IR detectors are little microchips with a photocell that are tuned to listen to infrared light. They are almost always used for remote control detection – every TV and DVD player has one of these in the front to listen for the IR signal from the clicker. Inside the remote control is a matching IR LED, which emits IR pulses to tell the TV to turn on, off or change channels. IR light is not visible to the human eye, which means it takes a little more work to test a setup.
There are a few difference between these and say a CdS Photocells:

– IR detectors are specially filtered for Infrared light, they are not good at detecting visible light. On the other hand, photocells are good at detecting yellow/green visible light, not good at IR light
– IR detectors have a demodulator inside that looks for modulated IR at 38 KHz. Just shining an IR LED wont be detected, it has to be PWM blinking at 38KHz. Photocells do not have any sort of demodulator and can detect any frequency (including DC) within the response speed of the photocell (which is about 1KHz)
– IR detectors are digital out – either they detect 38KHz IR signal and output low (0V) or they do not detect any and output high (5V). Photocells act like resistors, the resistance changes depending on how much light they are exposed to.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

Many of listed hardware (except from Raspberry PI Zero W and micro SD Card) can be bought alone or can be also found in the useful Elegoo starter kit.

Wiring Diagram

The following picture shows the wiring diagram adopted:

Step-by-Step Procedure

Prepare OS

Install OS following install Raspberry PI OS Lite guide. Make your OS up to date:

sudo apt update
sudo apt upgrade

Prepare ir-Keytable

Add GPIO to Device Tree overlay in boot config. Edit /boot/config.txt

sudo nano /boot/config.txt

Uncomment and change dtoverlay row as following (GPIO pin parameter refers to BCM naming for RPI pins):

dtoverlay=gpio-ir,gpio_pin=17

Close and save. Reboot your Raspberry PI:

 sudo reboot

After restart, please login again from terminal and install ir-keytable package:

sudo apt install ir-keytable

Map Your Remote With ir-Keytable

Before starting to customize our remote mapping, we can try our luck to find supported remotes. To list supported pre-built Keymaps:

ls /lib/udev/rc_keymaps/

ir-keytable has less pre-built remotes than LIRC, but I prefer it because – as said – it is simpler to customize. If you was lucky and found your remote in pre-built ones, than you can simply test it by typing “ir-keytable -t” on terminal and testing if buttons work. If it returns key names, then you are ok and this procedure ended.

Create Your Custom Mapping

For not so lucky people, list supported kernel protocols with ir-keytable command:

pi@raspberrypi:~ $ sudo ir-keytable
Found /sys/class/rc/rc0/ (/dev/input/event0) with:
Name: gpio_ir_recv
Driver: gpio_ir_recv, table: rc-rc6-mce
LIRC device: /dev/lirc0
Attached BPF protocols: Operation not permitted
Supported kernel protocols: lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp imon
Enabled kernel protocols: lirc rc-6
bus: 25, vendor/product: 0001:0001, version: 0x0100
Repeat delay = 500 ms, repeat period = 125 ms

In next step we’ll use ir-keytable in test mode to identify and take note about supported protocol and keys pressure ID. Let’s start test procedure with all protocols supported:

sudo ir-keytable -v -t -p rc-5,rc-5-sz,jvc,sony,nec,sanyo,mce_kbd,rc-6,sharp,xmp

The initialization procedure will start:

Found device /sys/class/rc/rc0/
Parsing uevent /sys/class/rc/rc0/lirc0/uevent
/sys/class/rc/rc0/lirc0/uevent uevent MAJOR=252
/sys/class/rc/rc0/lirc0/uevent uevent MINOR=0
/sys/class/rc/rc0/lirc0/uevent uevent DEVNAME=lirc0
Input sysfs node is /sys/class/rc/rc0/input0/
Event sysfs node is /sys/class/rc/rc0/input0/event0/
Parsing uevent /sys/class/rc/rc0/input0/event0/uevent
/sys/class/rc/rc0/input0/event0/uevent uevent MAJOR=13
/sys/class/rc/rc0/input0/event0/uevent uevent MINOR=64
/sys/class/rc/rc0/input0/event0/uevent uevent DEVNAME=input/event0
Parsing uevent /sys/class/rc/rc0/uevent
/sys/class/rc/rc0/uevent uevent NAME=rc-rc6-mce
/sys/class/rc/rc0/uevent uevent DRV_NAME=gpio_ir_recv
/sys/class/rc/rc0/uevent uevent DEV_NAME=gpio_ir_recv
input device is /dev/input/event0
/sys/class/rc/rc0/protocols protocol rc-5 (enabled)
/sys/class/rc/rc0/protocols protocol nec (enabled)
/sys/class/rc/rc0/protocols protocol rc-6 (enabled)
/sys/class/rc/rc0/protocols protocol jvc (enabled)
/sys/class/rc/rc0/protocols protocol sony (enabled)
/sys/class/rc/rc0/protocols protocol rc-5-sz (enabled)
/sys/class/rc/rc0/protocols protocol sanyo (enabled)
/sys/class/rc/rc0/protocols protocol sharp (enabled)
/sys/class/rc/rc0/protocols protocol mce_kbd (enabled)
/sys/class/rc/rc0/protocols protocol xmp (enabled)
/sys/class/rc/rc0/protocols protocol imon (disabled)
/sys/class/rc/rc0/protocols protocol lirc (enabled)
Opening /dev/input/event0
Input Protocol version: 0x00010001
Protocols changed to rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp
Testing events. Please, press CTRL-C to abort.

you are now prompted to generate key pressure events. Point your remote to IR sensor and press a key. In my test, with an Elegoo remote, the following rows are generated:

1274.230088: lirc protocol(nec): scancode = 0x45
1274.230144: event type EV_MSC(0x04): scancode = 0x45
1274.230144: event type EV_SYN(0x00).

The first line shows that my remote uses “nec” protocol. trace this in your notes. Protocol will be the same for all buttons.

The first and second rows show that my key pressure generated a “0x45” scancode. I had this event by pressing my Power button on remote. So my first matching is:

0x45 = Power key

Repeat this step for each remote button and create a mapping table similar to the following one:

protocol: nec

0x45 = Power
0x46 = Vol+
0x47 = FUNC/STOP
0x44 = BCW
0x40 = PLAY/PAUSE
0x43 = FRW
0x07 = DOWN
0x15 = VOL-
0x09 = UP
0x16 = 0
0x19 = EQ
0x0d = ST/REPT
0x0c = 1
0x18 = 2
0x5e = 3
0x08 = 4
0x1c = 5
0x5a = 6
0x42 = 7
0x52 = 8
0x4a = 9

Create Your Custom .toml File From Mapping

In this section, we are going to create our custom .toml file that will be used by ir-keytable at kernel level. A .toml file is a simple file with a short description of remote name and a map of system buttons to scancodes. Usable system buttons are listed in following text file you can get from my dowload area:

ir-keytable available keycodes.txt

Usually, the correct ones are these keys starting with “KEY_” prefix.

Create a toml file similar to (or download from the next link) my Elegoo.toml, but with your data you noted in the previous step and related kernel keys:

[[protocols]]
name = "Elegoo"
protocol = "nec"
variant = "nec32"

[protocols.scancodes]
0x45 = "KEY_POWER"
0x46 = "KEY_VOLUMEUP"
0x47 = "KEY_FN_S"
0x44 = "KEY_BACK"
0x40 = "KEY_PLAYPAUSE"
0x43 = "KEY_FORWARD"
0x07 = "KEY_DOWN"
0x15 = "KEY_VOLUMEDOWN"
0x09 = "KEY_UP"
0x16 = "KEY_0"
0x19 = "KEY_EQUAL"
0x0d = "KEY_REPLY"
0x0c = "KEY_1"
0x18 = "KEY_2"
0x5e = "KEY_3"
0x08 = "KEY_4"
0x1c = "KEY_5"
0x5a = "KEY_6"
0x42 = "KEY_7"
0x52 = "KEY_8"
0x4a = "KEY_9"

To test our toml file, we need to clean current keytable, load toml file, read i to check and then we can test (diring test, consider that if you press power button and if it works, then your Raspberry PI will shut down):

sudo ir-keytable -c 
sudo ir-keytable -w /pathToFile/your.toml
sudo ir-keytable -r
sudo ir-keytable -t 

Please find below my terminal output for comparison:

pi@raspberrypi:~ $ sudo ir-keytable -c
Old keytable cleared

pi@raspberrypi:~ $ sudo ir-keytable -w Elegoo.toml
Wrote 21 keycode(s) to driver
Protocols changed to nec

pi@raspberrypi:~ $ sudo ir-keytable -r
scancode 0x0007 = KEY_DOWN (0x6c)
scancode 0x0008 = KEY_4 (0x05)
scancode 0x0009 = KEY_UP (0x67)
scancode 0x000c = KEY_1 (0x02)
scancode 0x000d = KEY_REPLY (0xe8)
scancode 0x0015 = KEY_VOLUMEDOWN (0x72)
scancode 0x0016 = KEY_0 (0x0b)
scancode 0x0018 = KEY_2 (0x03)
scancode 0x0019 = KEY_EQUAL (0x0d)
scancode 0x001c = KEY_5 (0x06)
scancode 0x0040 = KEY_PLAYPAUSE (0xa4)
scancode 0x0042 = KEY_7 (0x08)
scancode 0x0043 = KEY_FORWARD (0x9f)
scancode 0x0044 = KEY_BACK (0x9e)
scancode 0x0045 = KEY_POWER (0x74)
scancode 0x0046 = KEY_VOLUMEUP (0x73)
scancode 0x0047 = KEY_FN_S (0x1e3)
scancode 0x004a = KEY_9 (0x0a)
scancode 0x0052 = KEY_8 (0x09)
scancode 0x005a = KEY_6 (0x07)
scancode 0x005e = KEY_3 (0x04)
Enabled kernel protocols: lirc nec

pi@raspberrypi:~ $ sudo ir-keytable -t
Testing events. Please, press CTRL-C to abort.
749.430103: lirc protocol(nec): scancode = 0x18
749.430181: event type EV_MSC(0x04): scancode = 0x18
749.430181: event type EV_KEY(0x01) key_down: KEY_2(0x0003)
749.430181: event type EV_SYN(0x00).
749.480258: lirc protocol(nec): scancode = 0x18 repeat
749.480310: event type EV_MSC(0x04): scancode = 0x18
749.480310: event type EV_SYN(0x00).
749.610091: event type EV_KEY(0x01) key_up: KEY_2(0x0003)
749.610091: event type EV_SYN(0x00).
750.430096: lirc protocol(nec): scancode = 0x19
750.430167: event type EV_MSC(0x04): scancode = 0x19
750.430167: event type EV_KEY(0x01) key_down: KEY_EQUAL(0x000d)
750.430167: event type EV_SYN(0x00).
750.560106: event type EV_KEY(0x01) key_up: KEY_EQUAL(0x000d)
750.560106: event type EV_SYN(0x00).
751.710097: lirc protocol(nec): scancode = 0xd
751.710168: event type EV_MSC(0x04): scancode = 0x0d
751.710168: event type EV_KEY(0x01) key_down: KEY_REPLY(0x00e8)
751.710168: event type EV_SYN(0x00).
751.770263: lirc protocol(nec): scancode = 0xd repeat
751.770319: event type EV_MSC(0x04): scancode = 0x0d
751.770319: event type EV_SYN(0x00).
751.900086: event type EV_KEY(0x01) key_up: KEY_REPLY(0x00e8)
751.900086: event type EV_SYN(0x00).

If you have a similar behaviour and keys showed are the same you pressed, then your toml file is valid and working.

Make Your Mapping Permanent

We need now to make our configuration permanent after reboot.

Move your toml file to “/etc/rc_keymaps/”

sudo mv /pathToFile/your.toml /etc/rc_keymaps/

Edit /etc/rc_maps.cfg to add a row

sudo nano /etc/rc_maps.cfg

Add a row on the devices table referencing your toml file. Use * wildcard both on the driver and table columns. In my case, my file is named Elegoo.toml and my rc_maps.cfg section will appear as the following:

.....
.....
# Table to automatically load the rc maps for the bundled IR's provided with the
# devices supported by the linux kernel
# driver table file
*    *                      Elegoo.toml
*    rc-adstech-dvb-t-pci   adstech_dvb_t_pci.toml
*    rc-alink-dtu-m         alink_dtu_m.toml
*    rc-anysee              anysee.toml
.....
.....

Test configuration loading:

sudo ir-keytable -a /etc/rc_maps.cfg -s rc0

This should return something like the following (keycodes number and protocol may vary according to your toml:

Old keytable cleared
Wrote 21 keycode(s) to driver
Protocols changed to nec

Moreover, “ir-keytable -r” terminal command should show your mapping.

To make it permanent after reboot, edit /etc/rc.local

sudo nano /etc/rc.local

and add loading configuration command before “exit 0” final row:

.....
.....
  printf "My IP address is %s\n" "$_IP"
fi

ir-keytable -a /etc/rc_maps.cfg -s rc0

exit 0

Reboot and check if it is persistent.

Enjoy!

peppe8o

Open source and Raspberry PI lover

View Comments

  • thank you for your very usefull article.
    I had my IR-receiver installed in no time and it works.
    Great.
    The only thing after a reboot, it did not work anymore.
    I had to put sudo in front of the line in rc.local file:
    sudo ir-keytable -a /etc/rc_maps.cfg -s rc0
    After that it worked after a reboot as well.

      • hy peppe80
        I removed the sudo in the rc.local file as you stated that it runs as root.
        Then I performed a reboot and bingo, it did work.
        Just to be sure, I powered off, powered up, and it still works.
        So why it did not after the very first try, I don't know. The rc.local file is like you posted.
        Thanks again.

  • This is THE BEST tutorial for enabling your Raspberry Pi to see IR input.... I've worked thru quite a few!
    Thank you!

      • Yes, thank you again!
        Over the past two days, I've mapped keys on my remote and made some keybindings (using a method I found elsewhere) to make buttons initiate a shutdown or reboot of the host Raspberry Pi. Next, I'm going to use the IR remote to control a string of RGB LEDs.... seems like a good match. I'm thinking the approach should be based on a python script that watches for inputs and gives outputs.
        Have you done anything like this in your tutorials or playing around with the Pi...?

        • This is a very good idea. This shouln't be too complicated from theorical perspective as with python subprocess library you can execute shell commands. But requires time, as you should manage a command running in background (ir-keytable when collecting test data) and at same time ask user what key he pressed to save matching. But the most time with programs is managing exceptions, differences between a huge IR hardware world and so on. Writing new programs is a quite simple job, but the hard part is managing them

  • I would have loved to meet this guide 6 hours ago..... just golden. Funny enough I have the same remote control. super eaaaasy.

  • I just wanted to say Thanks! I've been struggling with my IR receiver and my Buster raspberryOS install for weeks. I've read countless tutorials with different ways to get my various IR remotes to work with my RaspberryPi and none of them completely worked. Your information here worked 1st try. I am running a headless Pi and am going to use an old IR remote to control my Mopidy install.

Published by
peppe8o

Recent Posts

Some links in this post may be affiliate links. We may get paid if you buy something or take an action after clicking one of these, but without addictional costs for you compared to direct buying.

SPI communication between two Arduinos

In this tutorial, we will use two Arduino Uno to demonstrate the Serial Peripheral Interface…

1 week ago

Automatic irrigation system with Arduino and Sensors

In this tutorial, we will be making an automatic irrigation system (AIS) with Arduino and…

2 weeks ago

Beginner’s Guide to Use Python Virtual Environment with Raspberry PI (venv)

This tutorial will show you how to use Python Virtual Environment with Raspberry PI computer…

3 weeks ago

Get Betting Odds with Raspberry PI and Odds-API (free)

This tutorial will show you how to get betting odds with Raspberry PI by using…

1 month ago

Backup Raspberry PI (computer) Data with Rsync to Remote NAS

This tutorial will show you how to perform the backup of Raspberry PI (computer board)…

1 month ago

Honeygain and Raspberry PI: Earn by Sharing Internet Connection

This tutorial will show you how to install Honeygain on a Raspberry PI computer board…

1 month ago