Infrared

We communicate with many of our devices in the home using infrared light. Your television remote control sends pulses of invisible infrared light to the television to change channels. Many toys have infrared remote controls. Our Launchpad computer can send and receive these signals, with the addition of an inexpensive infrared LED and infrared receiver.

My friend Ken Shirriff has written a library for the Arduino that takes most of the work out of decoding the signals. This library also works on the Launchpad, and comes included with Energia. There are several examples in the File | Examples menu.

There are millions of ways to encode data onto a stream of pulses of light. Due to patents, trade secrets, and other competitive barriers to standardization, there are hundreds of schemes currently in use. The infrared library included with Energia supports six common schemes -- NEC, Sony, RC5, RC6, Dish, and Sharp. So if you own a universal remote control, you can set it to one of those, and the Launchpad can receive its signals.

To receive the signals, you want an infrared receiver module.

This is a three terminal device (power, ground, and output). They come in different frequencies, but the most common is 38,000 hertz. Most remotes us 38,000 hertz. Those that use nearby frequencies (31,000 hertz, 36,000 hertz, etc.) will work with a 38,000 hertz receiver module, but the range will be smaller.

Connecting the receiver module to the Launchpad is simple.

Power and ground are obvious, and the output (connected above to P2.5) can be connected to any Launchpad input pin.

The program to read the infrared signals and send the results to the Serial Monitor is fairly simple.

When you press a button on the remote, the Serial Monitor shows something like this:

Type is UNKNOWN: Value is 66207555
Type is UNKNOWN: Value is 66207555

The type is listed as UNKNOWN because I was using a DirecTV remote, which uses a different protocol than than those the library knows about. Two values are shown because most remotes send the code more than once for each button press, to make sure the message gets through. Sometimes a special code is used for 'repeat'. For our purposes here, we can ignore that special code.

Suppose we want to use the remote to control a robot. The remote has some buttons that form a little circle, and we can interpret those buttons as forward, backwards, left, right, and the middle button can be beep, or fire, or whatever you like. If we push the buttons in that order, we see:

Type is UNKNOWN: Value is 4064352766​
Type is UNKNOWN: Value is 3028878891​
Type is UNKNOWN: Value is 3308754100​
Type is UNKNOWN: Value is 197779206​
Type is UNKNOWN: Value is 1974032039​​
Type is UNKNOWN: Value is 744425775​​

The center button, marked SELECT, sends one code multiple times while the button is held down, then another code when the button is up. We will interpret that as Fire! and Cease Fire! respectively.

Now we can write a new program, that shows us the commands that we would use to control our robot:

Pressing the keys on the remote now shows us:

Forward
Forward
Forward
Backward
Backward
Backward
Left
Left
Left
Right
Right
Right
Fire!
Fire!
Fire!
Cease Fire!
Fire!
Fire!
Fire!
Fire!
Fire!
Fire!
Fire!
Cease Fire!

 

Sending infrared codes from the Launchpad to some other device is also fairly simple, thanks to the infrared library. We will need an infrared LED to send the signals.

We can use the infrared LED the same way we use a visible light LED. However, it is not possible to tell whether it is working just by looking at it, because you can't see infrared light. But we can use a trick. You can aim a camera (such as the one in your phone) at the infrared LED, and watch the flashes on the camera's screen, since the digital sensor in the camera is sensitive to infrared.

Connect the LED to P2.3 and ground. The long lead is the cathode (which connects to ground). The short lead is the anode, and it connects to P2.3.

We are now going to use the infrared LED to control a small toy tank.

We can use the previous program to see what the signals from the tank's remote look like. Unfortunately, they are not sent using one of the coding methods known by the library. However, we can extend the library so that we can control the tank.

The library collects the bits that the remote sends to the Launchpad. We can print out those 'raw' numbers, and they tell us how long the LED was on and how long it was off, for each of the flashes the remote makes as it sends the code. By looking at those numbers, I found that the tank's remote started each command with a flash that lasts 1.772 seconds. Then there was a dark period of 0.34 seconds. That sequence marked what we will call the header.

To send a ONE bit, the tank flashes the LED for 0.36 seconds, followed by a dark period of 0.82 seconds.

To send a ZERO bit, the dark period is only 0.34 seconds.

There are 5 bits send for each command. That allows 32 different commands to be sent.

Using this information, we can now extent the library's IRsend() class. We will call our class 'tank', and inherit all of the functions of the IRsend class by telling Energia that our 'tank' class inherits from IRsend. The line that does that looks like this:

struct tank : public IRsend

So let's see what the code for our new 'tank' class looks like:

We have created a new method, called sendTank(), that will flash the infrared LED in just the right sequence to send our commands to the tank. Now we can look at the rest of the program, as it uses our new class to send commands to the tank:

We send the tank forward, then spin right for a while, and then make it move backwards.

Sending the number 0b00001 (that's just the number 1) to the tank moves it's left tread forward. Sending a 0b0010 to it (the number 2) moves the left tread backwards. Sending a 5 moves both treads forward, and so on.