My goal now is to send commands to air conditioners and other devices in the house. Originally, these devices have only infrared (IR) remote control. To solve this problem, I’m going to use a Raspberry Pi and IR transceiver hat.

Google told that the problem can be solved using LIRC (Linux Infrared Remote Control). During the research I found that LIRC works with both transmitters and receivers of IR signals, it can decode received signal and execute external commands by these signals. I don’t need to receive signals now, but in the future may be helpful. If you’re going to experiment yourself, reading of the LIRC Configuration Guide is highly recommended.


If you have a Raspberry Pi with a Raspbian, you can install LIRC on it.

Recording of signals

First you need to create a configuration file with data sequences for all required commands. I further call this file lircd.conf, but actually each device will have own file my_device_name.lircd.conf in the directory /etc/lirc/lircd.conf.d.

The file format is described here. If there is a remote control, then it is possible to record the signals transmitted by it to a file using the irrecord utility.

irrecord analyses the sequence and tries to determine the protocol and timing. In some cases, irrecord fails in the analysis, so there is an opportunity to save the sequence as it was accepted, in the “raw” form. This mode is activated by the option --force.

But even with --force, irrecord tries to analyze something, and it can also fail. Then you can write sequences by the command mode2 and create the file yourself.

mode2 prints in sequence the duration of the presence (‘pulse’) and absence (‘space’) of a signal in the transmitted data. Duration is measured in microseconds (1e-6 seconds). In raw format of the lircd.conf, the same duration is specified, starting with ‘pulse’ (the leading ‘space’ is not needed). Accordingly, there must always be an odd number of numbers (it starts and ends with the presence of a signal - ‘pulse’).

I made a small tool to process the mode2 output. It asks the name of the command for the lircd.conf, runs mode2 for 5 seconds, then prints the result in format ready for lircd.conf:

Once the file has been created, you can again try to “recognize” with irrecord --analyse. It does not always pass well, do not rush to throw out the original file. My statistics are as follows: the LG TV remote was analyzed by irrecord successfully, all air conditioners and vacuum cleaner require mode2 and my tool, the vacuum cleaner was then processed by --analyse.

My configs, just for memory:

Standard command names

The LIRC in its intended purpose should convert the received and recognized IR signal into a Linux input event. Therefore, by default, it requires to use in lircd.conf command names from the standard list. You can see the list of valid names:

Commands of standard conditioners are absent in this list. The --disable-namespace option allows the use of any names:


The mode2 command prints all received signals. You can use it to check the receiver.

Easiest way to check the transmitter is to use another receiver and the mode2. In hopeless cases you can change GPIO output yourself (see section “GPIO” in this article) and then check physical signal by tester or oscilloscope.

{$ gist 6f08c0e7b052dd2a69d395da426992d4 %}

You can monitor logs by the journalctl command. It can help, for example, find mistakes in the configuration file.

Command sending

To send the recorded commands there is a utility irsend. It can also show a list of known devices, and list of known commands for each device. Notice the “empty arguments” in the example below, they are needed there.

irsend is a client for the lircd, so if something doesn’t work properly, look at the logs (see above how to).

Theoretically there is one more possibility - send commands to the lircd daemon through its socket. Didn’t research it.

How to call by Python

I researched a few libraries for the Python. Most of them are boilerplate for using the irsend command. Only one uses an API through a socket, but it requires version which is unavailable on Raspberry.
So using of library doesn’t make sense, just to run command is easy:


I use manufactured hat for Raspberry, there are lots of them on Amazon and AliExpress. It uses GPIO 17 as out, and GPIO 18 as in, you can see it in config files above.

There is room on the board for the second (optional) LED D2, which is not installed by default. Two LEDs are connected in series. Therefore, in the absence of the D2 LED, you need to close the SJ1 jumper. I was surprised to find that the jumper was initially open on all my boards. Had to to finish with a soldering iron.


Some conclusions

It works: the signal is transmitted, the devices see it and correctly recognise it.

Much depends on the position of the LED emitter, it must be precisely aimed at the receiver. One stationary transmitter cannot control all devices in the room. Clone Raspberry Pi solution for each gadget is expensive, I need or modify the emitter to “cover a larger area,” or find a cheaper platform.

LIRC was originally created to convert IR signals into standard Linux input device events. So it is natural that one button is one code. For some home devices (most of the air conditioners, for example) this is not the case: the remote transmits a data packet containing the full state of the device (including operation mode, required temperature, fan operation modes, time, timer setting, etc.) LIRC has no feature to assemble composite packet, so it’s good quick out-of-the-box tool, but can be replaced in future by something else.