Raspberry Pi IR Receiver

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.

close up

close up

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.

close up

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