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)

Here is the self-explanatory fritzing:

We wire IR receiver signal to 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 usual hardware.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_powerkey_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

Note: Bear in mind that AirCon controls (the ones with LCD displays on them) behave differently from TV-like controls. They send configuration, not commands, so you won’t be able to record them with 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):

Ok, we are ready to register our RasPi and launch it as an Isaax project’s device. If everything went well, you should see the output in the Isaax ‘Notifications’ pane. In my case, when I update the schedule via envars I see:

And when the time comes and the IR command is sent I see:

That’s it! You are now prepared for the ultimate IR control hub deployment!
Manipulate TVs, heaters, AC units, colored lamps and what not with you RasPi and LIRC… and Isaax.

Illustration by Victorgrigas


isaax

Isaax is a Continuous Delivery service for IoT devices. Update thousands of devices with 1 action. You can build IoT systems more easily.

2 Comments

Sulerhy · 2019-07-24 at 11:30

Thank so much for your guide. I spent a lot of time to find out hardware.conf as the hundred guidelines on the internet. Finally, I found this page, thank you so much

Raymond Day · 2019-09-03 at 21:13

Mine will not record but the test it sees my remote like this:

space 16777215
pulse 272
space 766
pulse 279
space 1826
pulse 278
space 770
pulse 286
space 761
pulse 287
space 1818
pulse 284
space 763
pulse 281
space 777
pulse 282
space 760
pulse 282
space 768
pulse 279
space 769
pulse 285
space 12704
pulse 281
space 762
pulse 280
space 1824
pulse 282
space 774
pulse 275
space 770
pulse 289
space 1824
pulse 280
space 789
pulse 248
space 764
pulse 280
space 772
pulse 284
space 763
pulse 281
space 772
pulse 286
space 12699
pulse 290
space 757
pulse 282
space 1821
pulse 284
space 763
pulse 283
space 767
pulse 288
space 1816
pulse 278
space 793
pulse 268
space 762
pulse 283
space 771
pulse 290
space 763
pulse 278
space 776
pulse 270
space 12710
pulse 328
space 707
pulse 336
space 1765
pulse 286
space 761
pulse 284
space 767
pulse 279
space 1824
pulse 282
space 765
pulse 291
space 760
pulse 283
space 765
pulse 300
space 755
pulse 281
space 771
pulse 279
space 12707
pulse 277
space 773
pulse 278
space 1819
pulse 272
space 768
pulse 286
space 766
pulse 281
space 1822
pulse 283
space 764
pulse 280
space 772
pulse 286
space 762
pulse 283
space 770
pulse 287
space 760
pulse 284
space 12720
pulse 267
space 780
pulse 261
space 1833
pulse 285
space 756
pulse 286
space 760
pulse 287
space 1815
pulse 286
space 761
pulse 282
space 771
pulse 288
space 759
pulse 284
space 771
pulse 277
space 767
pulse 288
space 12710
pulse 354
space 694
pulse 276
space 1831
pulse 288
space 748
pulse 274
space 769
pulse 306
space 1806
pulse 281
space 762
pulse 283
space 764
pulse 281
space 772
pulse 285
space 762
pulse 286
space 766
pulse 287
space 12702
pulse 286
space 764
pulse 333
space 1771
pulse 281
space 805
pulse 290
space 728
pulse 315
space 1785
pulse 270
space 773
pulse 288
space 763
pulse 297
space 746
pulse 285
space 757
pulse 284
space 767
pulse 278
space 12706
pulse 278
space 772
pulse 284
space 1817
pulse 287
space 761
pulse 292
space 763
pulse 277
space 1825
pulse 281
space 769
pulse 317
space 735
pulse 277
space 764
pulse 281
space 774
pulse 280
space 766
pulse 285
space 12699
pulse 275
space 767
pulse 287
space 1815
pulse 288
space 761
pulse 284
space 768
pulse 278
space 1823
pulse 281
space 766
pulse 295
space 762
pulse 281
space 764
pulse 307
space 747
pulse 286
space 798
pulse 253
pulse 125662
space 2465659
space 2442507
pulse 272
space 768
pulse 286
space 1827
pulse 279
space 763
pulse 282
space 1822
pulse 289
space 1811
pulse 286
space 1816
pulse 277
space 1823
pulse 281
space 782
pulse 276
space 758
pulse 285
space 767
pulse 279
space 9528
pulse 275
space 771
pulse 276
space 1823
pulse 275
space 770
pulse 286
space 1817
pulse 287
space 1815
pulse 278
space 1822
pulse 282
space 1819
pulse 284
space 762
pulse 288
space 764
pulse 287
space 760
pulse 287
space 9511
pulse 284
space 765
pulse 281
space 1828
pulse 280
space 774
pulse 278
space 1815
pulse 281
space 1828
pulse 278
space 1829
pulse 274
space 1818
pulse 291
space 755
pulse 286
space 756
pulse 277
space 801
pulse 263
space 9502
pulse 276
space 771
pulse 284
space 1818
pulse 286
space 760
pulse 284
space 1820
pulse 295
space 1845
pulse 255
space 1821
pulse 303
space 1792
pulse 278
space 780
pulse 278
space 753
pulse 288
space 765
pulse 278
space 9515
pulse 273
space 770
pulse 302
space 1802
pulse 280
space 772
pulse 285
space 1813
pulse 285
space 1816
pulse 279
space 1823
pulse 335
space 1775
pulse 283
space 764
pulse 278
space 770
pulse 284
space 768
pulse 279
space 9514
pulse 275
space 763
pulse 281
space 1823
pulse 280
space 768
pulse 278
space 1824
pulse 280
space 1822
pulse 281
space 1821
pulse 285
space 1818
pulse 286
space 763
pulse 284
space 765
pulse 279
space 775
pulse 286
space 9519
pulse 279
space 769
pulse 270
space 1826
pulse 279
space 764
pulse 280
space 1821
pulse 282
space 1819
pulse 284
space 1820
pulse 285
space 1816
pulse 278
space 768
pulse 286
space 765
pulse 281
space 766
pulse 292
space 9520
pulse 285
space 759
pulse 281
space 1888
pulse 217
space 762
pulse 288
space 1817
pulse 322
space 1795
pulse 260
space 1812
pulse 280
space 1821
pulse 282
space 766
pulse 290
space 763
pulse 283
space 763
pulse 282
space 9522
pulse 282
space 779
pulse 264
space 1856
pulse 251
space 766
pulse 294
space 1811
pulse 276
space 1823
pulse 289
space 1811
pulse 275
space 1820
pulse 284
space 764
pulse 280
space 769
pulse 296
space 754
pulse 282
space 9514
pulse 285
space 763
pulse 284
space 1827
pulse 286
space 759
pulse 278
space 1826
pulse 278
space 1827
pulse 282
space 1818
pulse 280
space 1846
pulse 271
space 742
pulse 283
space 773
pulse 273
space 770
pulse 286
space 9511
pulse 287
space 760
pulse 285
space 1819
pulse 285
space 765
pulse 281
space 1822
pulse 283
space 1825
pulse 283
space 1818
pulse 280
space 1831
pulse 276
space 815
pulse 255
space 749
pulse 286
space 799
pulse 258
space 9494
pulse 273
space 766
pulse 288
space 1818
pulse 277
space 772
pulse 286
space 1816
pulse 286
space 1814
pulse 278
space 1824
pulse 280
space 1827
pulse 281
space 765
pulse 289
space 765
pulse 281
space 771
pulse 277
space 9519
pulse 269
space 767
pulse 278
space 1824
pulse 281
space 766
pulse 289
space 1821
pulse 278
space 1820
pulse 284
space 1818
pulse 286
space 1817
pulse 286
space 761
pulse 282
space 768
pulse 278
space 770
pulse 285
space 9537
pulse 268
space 765
pulse 279
space 1822
pulse 277
space 762
pulse 282
space 1827
pulse 278
space 1819
pulse 284
space 1817
pulse 305
space 1796
pulse 278
space 772
pulse 285
space 763
pulse 284
space 768
pulse 287
space 9522
pulse 272
space 773
pulse 282
space 1821
pulse 279
space 759
pulse 283
space 1823
pulse 281
space 1817
pulse 286
space 1816
pulse 279
space 1824
pulse 280
space 769
pulse 286
space 761
pulse 295
space 756
pulse 278
pulse 128934
^C
root@Dad:~#

I just press key_1 then key_OK as fast and it did these number fast. But when I go to record it it just shows.

Now hold down button “key_2”.
Something went wrong: Cannot decode data
Please try again. (0 retries left)

Now hold down button “key_2”.
Something went wrong: Cannot decode data
Too many errors.
Check TROUBLESHOOTING in irrecord(1) manpage.
Or try using the -f option.
Unrecoverable error: Cannot decode data

Giving up
Check TROUBLESHOOTING in irrecord manpage.

It’s like it can’t record this but it does see it.

-Raymond Day

Leave a Reply

Your email address will not be published. Required fields are marked *