Even though many modern home appliances have moved to Bluetooth or WiFi (or in some cases some custom radio-based communication) controls, many of them are still controlled via IR. Having a universal IR control attached to an SBC located somewhere in a room is a very powerful feature for a smart home or even a public area. Turning on, raising volume on a TV with a smartphone? Scheduled AC power-up with a target temperature in a hospital waiting room? No problem! In this article we’re going to build a prototype with RasPi Zero, some IR receiver/transmitter diodes and LIRC to record and replay IR commands for a TV. We’ll make our RasPi turn on the TV at a scheduled time and Isaax will help us deploy and update the code.
What is LIRC
When I first thought of controlling my TV via alternative means, the idea was to use Arduino with IR diodes and a desktop PC / SBC to talk to Arduino. While there is a couple of decent IR libraries for Arduino IDE I felt they were a bit bulky to use. Its hard to detect and map commands and add new remote controls if they have different IR protocols. I mean it’s totally doable, just a little bit hard to manage. LIRC on the other hand, significantly reduces the burden of IR command detection and mapping and since RasPi Zero W is a Linux-based SBC and is very comparable to most Arduino/ESP boards price-wise – I’d say it wins as a universal IR control big time. And to add to this: LIRC has wrappers for most modern languages (Python, Node.js, Go, etc.)!Hardware Setup
Ok, so here is the list of what we will use for the prototype:- a Raspberry Pi Zero W
- a transmitting IR diode
- a receiving IR diode (I used TSOP1738)
- the IR remote control from the device you want to control (mine was a Samsung TV)
- some regular pins to be soldered to the RasPi for the dupont wires (optional)
- dupont wires (optional)
GPIO17
and IR transmitter to GPIO27
.
Note: If you want a more robust hardware IR solution, take a look at this nice RasPi HAT: https://www.crowdsupply.com/anavi-technology/infrared-phat
LIRC Setup
While LIRC installation is no different from a usual Linux app, the configuration is a bit tricky. LIRC moved to systemd and devmapper driver as default recently (since 0.9.4), but all of the guides for LIRC+RasPi out there refer to upstart / hardware.conf config. So you might find yourself lost on how to configure LIRC the devmapper way for RasPi. To tackle this we will switch the driver from devmapper to ‘default’, then just add the usualhardware.conf
and configure LIRC the old way.
Note: If you do know how to configure LIRC on RasPi with devmapper we would love to see your solution down in the comments.
Here is step by step guide for RasPi on Raspbian Stretch:
Install LIRC:
$ sudo apt-get update
$ sudo apt-get install lirc
Switch from devmapper
to default
in your /etc/lirc/lirc_options.conf
:
driver = default
device = /dev/lirc0
Create /etc/lirc/hardware.conf
file with the following content:
LIRCD_ARGS="--uinput"
LOAD_MODULES=true
DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
LIRCD_CONF=""
LIRCMD_CONF=""
In your /boot/config.txt
:
dtoverlay=lirc-rpi,gpio_in_pin=17,gpio_out_pin=27
GPIO17
for IR input, GPIO27
for output, remember?
Restart LIRC:
sudo systemctl stop lircd.service
sudo systemctl start lircd.service
Check LIRC status:
sudo systemctl status lircd.service
And finally reboot:
sudo reboot
Test
Let’s check if our setup works. Stop LIRC:sudo systemctl stop lircd.service
Use mode2
command to test IR receiver:
mode2 -d /dev/lirc0
Now grab the remote and press some buttons, you should see something like this:
If you see similar output, treat yourself – you are halfway there!
Recording Commands
Now is the time for real LIRC magic – command recording. Make sure LIRC is not running and type this:irrecord -d /dev/lirc0
Then follow the guide and record some commands from your remote. You will be prompted to press random buttons first to ‘generate dots’, then press a single button as fast as you can, etc – real fun! After you’re done LIRC will generate the remote configuration file with the recorded commands.
I ended up with a file the looks like this /etc/lirc/lircd.conf.d/tv.lircd.conf
:
begin remote
name tv
bits 16
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 4484 4536
one 529 1710
zero 529 594
ptrail 532
pre_data_bits 16
pre_data 0xE0E0
gap 108055
toggle_bit_mask 0x0
frequency 38000
begin codes
key_power 0x40BF
key_volumeup 0xE01F
key_volumedown 0xD02F
end codes
end remote
Notice that I have three commands recorded here : key_power
, key_volumeup
and key_volumedown
. Pretty obvious, I guess. LIRC has reserved keywords for command names (you won’t be able to enter custom ones), to list them type:
irrecord --list | less
Lets see if we can send the recorded commands. To power up the TV, type:
irsend send_once tv key_power
If your TV went online, treat yourself once again – you are almost there!
If not, here are some tips to troubleshoot:
- use
irsend send_start ...
to start repeating the command and look at your transmitting IR diode through a camera. Digital cameras detect IR light and you should see it blinking. By the way, that’s how night vision works: you ‘light up’ the scene with invisible IR light (remember those numerous LEDs around surveillance cameras?) and the camera ‘sees’ the scene clearly. - if the transmitter is blinking but TV doesn’t react, make sure there are no obstacles between the diode and the TV receiver and the diode ‘is looking directly’ at it. I used a cheap IR LED and it really needed to be directed straight at the TV. But the original IR transmitter from the TV’s remote worked even through the palm of my hand!
- if the transmitter doesn’t blink – make sure that all the contacts are soldered/connected properly and GPIO config is correct
irrecord
. Sending configuration is more advanced but, you can, for example, set target value for temperature and set swing mode with one ‘packet’ (i.e. set temperature to 24, swing off). And as you already may have guessed, you can’t set target volume with a TV remote command – only increase/decrease. Detecting and replaying AC configs is a different story and is out of scope of this article, but its is still possible with LIRC.
Wrapping It Up
Now why don’t we control LIRC from our application? I guess there is no reason why we couldn’t call a command and handle its output with any programming language we like. But LIRC has been around for a while and is now quite mature, so mature in fact that convenience wrappers have emerged in many languages. Some languages even have multiple wrappers, some have LIRC/HTTP wrappers, and there is a wrapper for Node-RED too! As I’m a Node.js guy – I’ll demonstrate it using lirc_node npm package. The code is pretty trivial: the TV is powered up on scheduled time each day. I won’t go into detail, you can look at the code here: https://github.com/yentsun/node-lirc-isaax-example One small thing to note is, I set the hour and minute for the schedule with env vars. This is done to easily change them via Isaax envars – no code commits needed.Isaax Setup
If you have no idea how to setup a new project and register a device on Isaax – you are welcome to go through the guides here: User Manual. Before we register our RasPi as an Isaax device, we need to do two things:- set up project’s envars for the schedule:
- change the project’s post-update script so Isaax Agent will install npm packages after each update (but before the apllication actually starts running):