md
Emulated IR Remote Control
Last update: May 17, 2020. First version: February 28, 2019
<-ir-keytable on the Orange Pi Zero --
<-Using Bare Metal IR on the Orange Pi Zero
 How to Use a $ 1,000 Desktop Computer to Emulate a $ 5 Infrared Remote Control 

The subtitle says it all. This note shows how I emulate an unusual infrared remote control for a rather old Curtis bookshelf sound system. That is a very pompous name for a fifteen-year-old radio and CD player. It is basically a non-portable boombox. The image below shows the state of the much-abused remote control that came with it.

old IR remote

The front is stained with coffee, the battery compartment cover on the back is held down with painter's tape. The plastic membrane is cracked along the VOL+ and VOL- buttons which will soon fall off. Indeed two buttons are already missing: the power button and the digit 1. I managed a long time without the "1" button, but the loss of the power button made the remote almost useless.

Here is the image of the emulator written in Free Pascal/Lazarus versions 3.3.1 and 2.10 respectively.

IR remote emulator

Three button at the bottom are greyed out as it appears that the corresponding buttons on the remote do not produce scan codes. There is an extra INFO button. When it is clicked, additional information (what else?) is displayed.

Extra information displayed

The radio stations assigned to the first four memory slots are displayed. This reminder of their frequency in handy when they have to be reloaded after a power outage of any length.

The IR hardware is an old HP OVU422000/6 media centre remote transceiver with an "IR-blaster" (HP IR Blaster Cable US Slr, from what I gather). I plugged the IR blaster cable connector into the 3.5 mm audio jack at the back of the transceiver labelled "1" and plugged the transceiver into a USB port on the desktop computer. The hardware is automatically enabled when the USB connection is made; typical udev voodoo.

USB-IR transceiver

That model of IR - USB transceivers is still available on eBay as "new old" stock. Mine came with an HP Windows computer running 32-bit Windows Vista, which shows its age.

The "driver" to transmit the IR signal is the ir-ctl utility from the v4l-utils package by the Linux TV group. Installation could not be simpler.

michel@hp:~$ sudo apt install -y v4l-utils

The utility can both read and write IR codes. To send an IR code produced by the On/Off button on the remote is not too complicated.

michel@hp:~$ sudo ir-ctl -S nec:0x14

Of course the protocol (nec) and the scan code (0x14) must be known. I have discussed this at length before.

The Free Pascal program that emulates the IR remote control by letting ir-ctl do the heavy lifting is mostly about the visual interface. The form is complex, the code is rather simple. When a button is clicked with the mouse, the common event handler ButtonClick calls on a function Send to send the IR code stored in the Tag field of the button and then it displays the function result in a label at the bottom of the form.

function Send(value: integer): string; var hex, outstr: string; res: boolean; begin hex := Format('nec:0x%.2x', [value]); res := RunCommand('sudo' , ['ir-ctl', '-S', hex], outstr, [poWaitOnExit]); result := 'ir-ctl -S '+hex; if not res then result := result + ' failed '; end; procedure TForm1.ButtonClick(Sender: TObject); begin with sender as TBitBtn do Label1.Caption := 'Last cmd: ' + Send(tag); end;

That is basically it except for four buttons. The volume up and down buttons of the real remote can be held down so that the volume is increased or decreased in small steps until the button is released. To do this in the emulator, the mouse events must be handled because the button OnClick event occurs only when the button is released. The OnMouseDown event handler called RepeatButtonMouseDown saves the button scan code and starts a timer. The OnMouseLeave and OnMouseUp event handlers stop the timer. In the between these events, whenever the timer fires, it sends the IR scan code.

Unfortunately, that approach, which is quite acceptable for the volume, does not work as well for the frequency up and down buttons. When one of these buttons is held down for a longer period, initiating a sequence of transmissions of an IR code, the radio receiver interprets these as an instruction to scan for the next radio station. A single IR scan code in an instruction to change the frequency up or down by 0.1 MHz. As the BitBtn38Click handler for the right most greyed out button on the bottom shows, it is not possible to send a second IR scan code quickly enough to mimic the real remote control.

It may be that there is a workaround the timing issue using recorded raw signal pulses and sending them back out. I have managed to record a single button press with the -r option. After removing all recorded lines that did not start with pulse or pause, it was possible to send the recorded raw scan code out again with success.

michel../ircurtis$ sudo ir-ctl -rscanup1 edit scanup1- removing timeout lines michel../ircurtis$ sudo ir-ctl -sscanup1

I tried to do the same recording a button press that was long enough to start a station scan, but I had no success sending it back. Nor did I manage to do anything worthwhile transmitting the working single button press recording multiple times with different gap times.

michel../ircurtis$ sudo ir-ctl -g101600 -sscanup1 -sscanup1

I quickly tired of this game; perhaps someone more patient could solve this riddle.

The program which is called ir_curtis is available in source code with the usual BDS style licence. As it is, it is more of a template which will have to be adjusted to particular circumstances. I am toying with the idea of making it into a "universal" remote. That is only a slight exaggeration; the IR remote to emulate still has to be supported by the ir-ctl. And of course because of the latter, this program only works on Linux as far as I know. It has been tested on Ubuntu 18.04 only.

Notice how root priviliges were needed to invoke ir-ctl when sending an IR scan code. So when launching ir_curtis it will be necessary to use the sudo prefix.

michel../ircurtis$ sudo ./ir_curtis

This can be avoided by adding an entry in the sudoers file for the default user.

michel@hp:~$ sudo visudo

... michel ALL=(ALL) NOPASSWD:ALL #includedir /etc/sudoers.d

Of course, michel should be replaced with the actual user name. Note how that the user will no longer need to supply a password when using its "super powers". That's not quite true, the operating system will still requre a password before doing certain things that could be very detrimental.

michel@hp:~$ which ir_curtis /home/michel/.local/bin/ir_curtis

As can be seen, I placed the binary in my local binary directory which is added to the search path so that Bash can find the application. A 128x128 pixel png file, ir_curtis_icon.png was placed alongside. I also added the following desktop file so that I can launch the application in the GUI.

michel@hp:~$ cat .local/share/applications/ir_curtis.desktop [Desktop Entry] Version=1.0 Encoding=UTF-8 Type=Application Icon=/home/michel/.local/bin/ir_curtis_icon.png Exec=/home/michel/.local/bin/ir_curtis Name=ir_curtis Categories=AudioVideo;Application

This little exercise has improved my life considerably. I no longer have to get up and step across the room to turn the radio on or off. And I no longer have to find the remote control to change the channel. That was often a challenge as it had the nasty tendency of burying itself under piles of paper or electronic junk strewn about the office.

<-ir-keytable on the Orange Pi Zero --
<-Using Bare Metal IR on the Orange Pi Zero