IR remote control – speed and position

iConor’s second LIRC configuration file,Combo_PWM.conf, allows us to use LIRC command ‘irsend’ to control the speed of a LEGO Power Functions Motor or the position of a LEGO Power Functions Servo Motor much like the 8879 IR Speed Remote Control.

This shell script sends a sequence of 7 increasingly values then returns to zero and repeat it in the opposite direction:

#!/bin/bash
#0
irsend SEND_ONCE LEGO_Combo_PWM 400B ; sleep  1.2
#1/7
irsend SEND_ONCE LEGO_Combo_PWM 401A ; sleep  1.2
#2/7
irsend SEND_ONCE LEGO_Combo_PWM 4029 ; sleep  1.2
#3/7
irsend SEND_ONCE LEGO_Combo_PWM 4038 ; sleep  1.2
#4/7
irsend SEND_ONCE LEGO_Combo_PWM 404F ; sleep  1.2
#5/7
irsend SEND_ONCE LEGO_Combo_PWM 405E ; sleep  1.2
#6/7
irsend SEND_ONCE LEGO_Combo_PWM 406D ; sleep  1.2
#7/7
irsend SEND_ONCE LEGO_Combo_PWM 407C ; sleep  1.2
#0
irsend SEND_ONCE LEGO_Combo_PWM 4083 ; sleep  1.2
#-1/7
irsend SEND_ONCE LEGO_Combo_PWM 40F4 ; sleep  1.2
#-2/7
irsend SEND_ONCE LEGO_Combo_PWM 40E5 ; sleep  1.2
#-3/7
irsend SEND_ONCE LEGO_Combo_PWM 40D6 ; sleep  1.2
#-4/7
irsend SEND_ONCE LEGO_Combo_PWM 40C7 ; sleep  1.2
#-5/7
irsend SEND_ONCE LEGO_Combo_PWM 40B0 ; sleep  1.2
#-6/7
irsend SEND_ONCE LEGO_Combo_PWM 40A1 ; sleep  1.2
#-7/7
irsend SEND_ONCE LEGO_Combo_PWM 4092 ; sleep  1.2

There is a total of 256 key codes in the configuration file (16 different values for the red plug x 16 different values for the blue plug). I used just the first subset of 16 so the first byte (for the blue plug) is always ’40’ but it doesn’t matter because I connected both Servo and M-motor to the red plug .

The sequence of key codes is not exactly the same as in the configuration file – I reordered the last 7 key codes.

The ‘sleep 1.2’  makes the script wait 1.2 seconds between each command. It is more or less the time the IR keeps the command active (bigger values would make the Servo return to center and the M-motor stop).

Infrared Remote Control

I discover this week that it is possible to use the headphone jack to send IR signals. The intructions are for a iPhone but one can use almost any audio source… even the computer audio card! And it is already suported in LIRC (Linux Infrared Remote Control), their page even includes a simple circuit!

LIRC – audio IR transmitter

Then I also found this lego-lirc repo in GitHub from a guy nicknamed iConor. It has the source code to generate LIRC configuration files for the LEGO Power Functions Infrared protocol… and also two configurations files:

The first file works like the 8885 – PF IR Remote Control and contains the usual FORWARD / BACKWARD / HOLD / BREAK codes; the second file works like the 8879 – PF IR Speed Remote Control and contains the codes to control the speed (duty cycle) of the motors.

So… why not give it a try?

I searched for more info about ‘lego-lirc’ but found nothing so I opened an issue asking iConor permission to publish those two files (and he promptly agreed, thank you iConor!).

My laptop has Ubuntu 14.10 x64. I installed LIRC and the required Portaudio library for using the audio card:

$ sudo apt-get install lirc libportaudio0

When LIRC is being installed it asks for an IR Receiver and an IR Transmitter, I chose ‘none’ twice.

Then I copied iConor configuration files to LIRC folder:

sudo cp Combo_Direct.conf /etc/lirc/lircd.conf
sudo cp Combo_PWM.conf  /etc/lirc/lircd.conf

and edited /etc/lirc/hardware.conf to create a LEGO_Combo_Direct transmitter associated to the audio card output:

(...)
#Chosen IR Transmitter
TRANSMITTER="LEGO_Combo_Direct"
TRANSMITTER_MODULES=""
TRANSMITTER_DRIVER="audio"
TRANSMITTER_DEVICE="hw@96000"
TRANSMITTER_SOCKET=""
TRANSMITTER_LIRCD_CONF="/usr/lirc/Combo_Direct.conf"
TRANSMITTER_LIRCD_ARGS=""
(...)

My audio card accepts sampling at 96 kHz but others may require lower values like 48 kHz.

I also edited /etc/lirc/lircd.conf to include both iConor configuration files

(...)
include "/etc/lirc/Combo_Direct.conf"
include "/etc/lirc/Combo_PWM.conf"
(...)

but I’m not sure if it is really needed since hardware.conf already has the right path.

I am also not sure if it is really needed or not but somewhere between my several tries I had to create a folder for lirc where it writes 2 files (one I think is a lock, the other contains just the process id)

~$ sudo mkdir /var/run/lirc/

Now let us start the lirc daemon:

~$ sudo service lirc start

and check if it is working:

~$ pgrep lirc
1234

and what kind of transmitter does it understands:

~$ irsend LIST "" ""
irsend: LEGO_Combo_Direct
irsend: LEGO_Combo_PWM

and also  what codes are available:

$ irsend LIST LEGO_Combo_Direct ""
irsend: 000000000000010e FLOAT_FLOAT
irsend: 000000000000011f FLOAT_FORWARD
irsend: 000000000000012c FLOAT_BACKWARD
irsend: 000000000000013d FLOAT_BRAKE
irsend: 000000000000014a FORWARD_FLOAT
irsend: 000000000000015b FORWARD_FORWARD
irsend: 0000000000000168 FORWARD_BACKWARD
irsend: 0000000000000179 FORWARD_BRAKE
irsend: 0000000000000186 BACKWARD_FLOAT
irsend: 0000000000000197 BACKWARD_FORWARD
irsend: 00000000000001a4 BACKWARD_BACKWARD
irsend: 00000000000001b5 BACKWARD_BRAKE
irsend: 00000000000001c2 BRAKE_FLOAT
irsend: 00000000000001d3 BRAKE_FORWARD
irsend: 00000000000001e0 BRAKE_BACKWARD
irsend: 00000000000001f1 BRAKE_BRAKE

OK, we’re ready! Now suppose we want to make both motors spin forward:

~$ irsend SEND_ONCE LEGO_Combo_Direct FORWARD_FORWARD

Yeah! The motor(s) spin for about 1 second.

So if we want shorter runs we can send a BREAK or a FLOAT after a short time, say 0.1 second:

~$ irsend SEND_ONCE LEGO_Combo_Direct FORWARD_FORWARD; sleep 0.1; irsend SEND_ONCE LEGO_Combo_Direct FLOAT_FLOAT

I faced some strange behaviours (delays, lags) until I better read the LIRC audio page and saw this warning:

“It takes some time to set up (50 ms or so) so when no clients are connected to lircd the first transmission will have some higher latency.

A workaround for this is to keep irw running with a bash script like this:

 #!/bin/bash
 while [ true ]; do
 irw || true
 sleep 1
 done

(…)”

So i created a ‘lirc-keepalive.sh’ file, gave it execution permissions and executed in the background:

~$ chmod +x lirc-keepalive.sh
~$ ./lirc-keepalive.sh &

And it makes a REALLY BIG difference.

For anyone who might get interested in this, I suggest first trying with just a headphone or 2 common LEDs (I used a pair of red). If there is a click or a blink then use 2 IR LEDs. Mine are L-934F3C – IR Emitter 3mm 940nm (€0.25 each) and no resistor at all but if you want to play safe use a small resistor like 8Ω.

You also need a cable (just cut the cable of a old headphone set) and a soldering iron. I also used heat shrinking tube but any kind of insulation material is OK.

The required materials:

And the completed cable:

Now about the LEDs…

These LEDs are from Kingbright, their specs say

1.2V Typ @ 20mA, 940 nm, 50° angle, 10 mW/sr Typ @20 mA

I also tried a pair of TSAL6100 950nm High Power Infrared Led from Vishay:

1.35V Typ@ 100 mA, 10° angle, 170 mW/sr @100 mA

but I got more or less the same results and as their emission angle is much smaller I needed to point more carefully to the PF RC receiver. so I kept the first pair. The audio output is intended for headphone so it isn’t much powerfull and might not give enough current to notice a difference – or i just made a mistake.

My first tests achieved a respectable 3 meter range. Not bad for something so simple and costing less than €1 – now everyone can programmaticaly control their LEGO models. Kudos for LIRC people for being so open-minded and for iConor for creating this configuration files.

Next I’m going to try the same with a LEGO Mindstorms EV3 and also a Raspberry Pi.