I recently got my hands on a IR Receiver and Transmitter module from a ELEGOO Upgraded 37 in 1 Sensor Modules Kit V2.0. I wanted to learn how the technology works and figure how to the IR transmitter with my Raspberry Pi 4.
EEVblog has an excellent video describing how the IR transmitter and receiver work in excellent detail. EEVblog #506 - IR Remote Control Arduino Protocol Tutorial
Signal Basics
The IR transmitter works by using OOK (on off keying) to modulate a carrier frequency. The carrier frequency is generated by producing a 32 kHz square wave that is transmitted by turning the transmitter LED on and off. A logical 1 is present when the carrier frequency is present, this is called a pulse. A logical 0 is present when the carrier frequency is absent, this is called a space. Data bits are encoded by a pulse of 600 us followed by either a space of 1600 us or 600 us. If a space of 1600 us follows the pulse then this is considered a 1. If a space of 600 us follows the pulse then this is considered a 0.
The key press from the IR transmitter has three parts: the header, pre-data, and payload. The header consists of a 9000 us pulse followed by a space of 4500 us. The pre-data is made up of 16 data bits that construct a value of 0x00ff. The payload is made up of 16 bits of payload data. This data is different for every button on the transmitter.
Raspberry Pi Setup
First the IR driver must be enabled. Un-comment the following line in the file /boot/config.txt
dtoverlay=gpio-ir,gpio_pin=17
Then make sure to install the lirc package. The Linux Infrared Remote Control. This is used to provide user space access to the IR driver and allow for easy integration into desktop tools.
The tool provides a debug executable to see raw data coming in from the infrared receiver. This program is called mode2 and output the values for all the pulses and spaces the driver receives.
mode2
...
pulse 9111
space 4438
pulse 637
space 521
pulse 605
space 527
pulse 582
space 549
pulse 581
space 551
pulse 577
space 555
pulse 581
space 550
pulse 605
space 527
pulse 579
space 553
pulse 605
...
LIRC provides a tool called irrecord which is used to make a configuration file for a remote transmitted and map all the payload values to a specific key value. This program unfortunately did not work for the several IR remotes I had lying around the apartment.
I instead created a python program to parse the output from mode2 to generate the config file. Here is the output of the python script. It decodes the payload for each button press.
Now that I have the payload of each key press from the IR transmitter I can create the configuartion script that lirc needs to process the raw payload into events that the rest of the OS can listen for. I copied a configuration script from another remote and modified the payload to match the keys. Here is the result.
begin remote
name elegoo
bits 16
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 9008 4466
one 598 1645
zero 598 550
ptrail 611
repeat 9005 2204
pre_data_bits 16
pre_data 0x00ff
gap 107536
toggle_bit 0
begin codes
KEY_POWER 0x000000000000a25d
KEY_VOLUMEUP 0x000000000000629d
KEY_STOP 0x000000000000e21d
KEY_PREVIOUS 0x00000000000022dd
KEY_PLAYPAUSE 0x00000000000002fd
KEY_NEXT 0x000000000000c23d
KEY_DOWN 0x000000000000e01f
KEY_VOLUMEDOWN 0x000000000000a857
KEY_UP 0x000000000000906f
KEY_EQUAL 0x0000000000009867
BTN_START 0x000000000000b04f
KEY_1 0x00000000000030cf
KEY_2 0x00000000000018e7
KEY_3 0x0000000000007a85
KEY_4 0x00000000000010ef
KEY_5 0x00000000000038c7
KEY_6 0x0000000000005aa5
KEY_7 0x00000000000042bd
KEY_8 0x0000000000004ab5
KEY_9 0x00000000000052ad
KEY_0 0x0000000000006897
end codes
end remote
This config file then just needs to be copied to /etc/lirc/lircd.conf.d with a file name of elegoo.lircd.conf and then the irw executable can be used to process key press events.
irw
0000000000ff30cf 00 KEY_1 elegoo
0000000000ff30cf 01 KEY_1 elegoo
0000000000ff30cf 02 KEY_1 elegoo
0000000000ff30cf 03 KEY_1 elegoo
0000000000ff38c7 00 KEY_5 elegoo
0000000000ff38c7 01 KEY_5 elegoo
0000000000ff38c7 02 KEY_5 elegoo
0000000000ff5aa5 00 KEY_6 elegoo
0000000000ff5aa5 01 KEY_6 elegoo