USB IR Toy v1 design
UPDATE: there is now a USB IR Toy v2!
Infrared remote controls are ubiquitous, they're used everywhere but we don't give them much thought. The goal of this project is to investigate the invisible signals emitted by remote controls.
This IR hacking tool can visualize infrared signals on a Java logic analyzer, record and replay infrared signals, and decode them. USB infrared remote control receiver transmitter is a mouthful, so we just call it the USB IR Toy.
- Control your computer with a remote using the IR decoder mode
- Visualize IR remote signals on a PC logic analyzer
- Raw IR IO mode receives, transmits, and clones IR signals
- Play the TV-B-Gone TV POWER codes
- USB upgradable
- Open source code and hardware
You can get an assembled USB IR Toy for $20, including worldwide shipping. Seeed Studio is currently hosting a preorder. The hardware will be manufactured the first week of February, but it might not get packed and shipped until later in February due to the Chinese New Year holiday.
Read about the design after the break.
There's lots of interesting infrared projects on the web. Serial port infrared PC remote control decoders have been popular for years, Ian published a USB version at Hack a Day. Jremin recently demonstrated an inexpensive wireless connection using an IR LED and receiver pair. The TV-B-Gone is a popular kit that turns most TVs off by transmitting POWER codes with infrared LEDs. The IR Toy combines all these projects into an upgradable USB dongle, with some extra functions, like a simple logic analyzer that visualizes remote control signals.
Click for a full size schematic image. Schematic and PCB are done in the freeware version of [www.cadsoft.de Cadsoft Eagle], download the project from our Google Code project page.
The Design is based on a 28pin PIC 18F2550 with USB. This chip is used in lots of hobby projects that need USB.
It runs at 5volts, so power is taken directly from the USB port without regulation. This 28pin chip has a single power supply pin that gets a 0.1uF decoupling capacitor (C1). The USB features require a 20MHz external oscillator (Q1, C5, C6).
The chip is initially programmed thorough a 5pin ICSP header. A 10K pull-up resistor (R1) and a diode (D1) on the MCLR pin protect the rest of the circuit from the 13volt signal used during programming.
An indicator LED (I) displays power, USB, and infrared mode status. The UART pins are exposed for debugging, and could be re-purposed as a serial port or general purpose IO.
The USB transceiver has an internal 3.3volt regulator that requires a 220nF (0.22uF) external capacitor. We always use two 0.1uF capacitors instead because they're so common. You could use a single 0.22uF capacitor in C3 and omit C2, as the manufactured version does.
We used a USB MINI-B connector (J1). This is a somewhat difficult part to solder. We initially tried a PCB-edge connector, but normal circuit boards aren't thick enough for solid contact.
The receiver connects to a PIC pin with an edge selectable interrupt (RB2/INT2) so we can detect the start of IR activity. RB2 has a Schmidt trigger to 'clean up' a noisy signal. The RX output is also connected to one of the interrupt-on-change pins (RB4) if you want to experiment with a different interrupt type and a TTL pin buffer.
An infrared LED (TX) is used to transmit signals. An infrared LED is like any other LED, with its color centered around 940nm. Current limiting resistor R4 gives the LED 20mA, though you could probably mod it with a smaller resistor for increased range (key calculation constants: 5volt supply, 1.5volts forward voltage).
Most IR 'emitters' are rated for short bursts of up to 100mA, but a PIC pin can only source 20mA. We put an NPN transistor (T1) between the PIC and the LED so the IR Toy can handle higher loads. Resistor R5 limits the current pulled though the PIC pin and dumped into the transistor base.
The transistor is connected to a PIC pin with a hardware pulse-width modulator. The PWM hardware makes it easy to create infrared pulses at frequencies visible to IR receivers.
We used the freeware version of Cadsoft Eagle to make the schematic and PCB. Download the latest designs and firmware from the project Google Code page. Seeed Studio sells the extra PCBs from our order.
The PCB is small and tightly packed, but it's not too difficult to solder. We found the SMD USB jack to be the most difficult part to solder because it's so close to the PIC.
|C1-C4||0.1uF capacitor (0805)|
|C5,C6||27pF capacitor (0805)|
|D1||Small signal diode (DO323)|
|IC1||PIC 18F2550-i/so (SOIC28W)|
|ICSP||0.1" pin header (1x05)|
|J1||USB MINI-B jack (SMD)|
|Q1||20MHz crystal (SMD/HC49UP)|
|R1||10,000 ohm resistor (0805)|
|R2||2700 ohm resistor (0805)|
|R3||390 ohm resistor (0805)|
|R4||180 ohm resistor (0805)|
|R5||1000 ohm resistor (0805)|
|T1||NPN transistor, hfe 30+, 200mA+ (0805)|
|I||indicator LED (0805)|
|RX||5volt 38kHz IR receiver (eg: TSOP38238)|
|TX||~940nm, 20mA IR LED (5mm)|
|S1||small tactile switch (optional)|
The firmware is written in C and compiled with the free Microchip C18 compiler. You can download the latest files from our Google Code project page. The v1 firmware has three primary modes: logic analyzer, raw input/output, and an IRman compatible remote control decoder.
We used the Microchip USB stack to run the 18F2550 as a virtual serial port. Microchip's code is open but not redistributable. If you want to compile the source, download the stack from Microchip, then drag the IR Toy source code into the install directory. See the detailed instructions at the top of main.c.
An alternate firmware plays TV POWER codes from the TV-B-Gone by Mitch Altman and Limor Fried, released under Creative Commons Attribution Share Alike. All files retain their original license.
You don't need a driver to use the USB IR Toy, but you will need a .inf file to tell Windows how to use the device. A suitable .inf is included in the project archive.
The virtual serial port (CDC) is an open standard, it should work on any modern operating system. We'll post link to instructions for Linux and Mac in the IR Toy manual.
Remote control decoder
The IR Toy default mode is a simple IRman compatible USB remote control decoder. Command your PC from a remote control with lirc/WinLIRC, Event Ghost, PC Remote Control, Girder, etc. The LED will blink very briefly each time it decodes an IR signal.
IRman has a simple handshake: when the PC says "IR", the IRman responds "OK". Decoded signals are sent as 6 byte packets. The device ID and command code are in the first two bytes, the rest are 0x00.
RC5 and RC5x are currently the only supported remote control protocols. RC5 is usually available as a low-number Phillips code on universal remote controls. We'd like to add more protocols in a future firmware upgrade.
A sampling receiver
A generic, sampling receiver is a popular idea, but it requires PC-side decoding support. Why? Because IR protocols have a few quirks that make the samples inconsistent.
Most protocols toggle a bit between 0 and 1 each time a button is pressed (shown in red). The receiver checks this bit to tell the difference between a long button press and multiple button presses. The toggle bit is only the same once every other button press, a waveform matcher won't recognize half of the transmissions.
Some protocols only send the command once, and then send a simple repeat blip while the button is held down (shown above). These remotes only generate an identical waveform once per button press, no matter how long you hold it down.
Without PC decoding support, a generic waveform sampling approach won't consistently detect button presses.
These commands are available in remote control decoder mode:
- 0x00 - Reset, return to RC decoder mode (all modes)
- 0x01 - SUMP run (captures and sends data to SUMP logic analyzer client)
- 0x02 - SUMP ID (responds: 1ALS )
- 0x52 ('r' or 'R') - IRman handshake (responds 'OK').
- 0x58 ('x' or 'X') - Enter raw IR/IO mode (responds 'X01')
- 0x24 ('$') - Trigger the bootloader (no jumper required)
SUMP logic analyzer
The IR Toy captures and displays remote control waveforms with the SUMP open source logic analyzer client. Sampling is triggered by a change on the IR receiver, it won't start capturing until it gets a valid IR source.
The logic analyzer mode currently operates at 10kHz with a fixed 1024 sample buffer. This isn't high-speed or long-sampling, but we were able to capture every mode we tested on a universal remote using these settings. Different speeds are possible, and could be added in a future firmware upgrade.
Remote control codes are generally carried on 38kHz modulated light, so data bits won't be shorter than 26us. The Nyquist sampling theorem suggests 76khz as the minimum sampling rate, twice the maximum data resolution. However, most IR receivers reject signals shorter that a few cycles so we can get away with much less.
The IR Toy has a SUMP protocol compatible state machine. It receives all commands correctly, but it only processes RESET, ID, and RUN; other commands are discarded. Future firmware might add a speed setting, but SUMP doesn't provide a lot of useful resolution in the low sampling frequency range of the IR Toy. It might also be possible to double the number of samples in a future firmware update.
SUMP is written in Java, and was originally intended for various FPGA setups. To use it, install Java, the rxtx serial port library, and the SUMP client. Jack Gassett at the Gadget Factory has a version compiled from the latest source code. He also has a Windows compile of SUMP for his ButterFly Platform that doesn’t require you to install Java. SUMP has a SourceForge page, but it’s not very active.
Capture with SUMP
Start SUMP and press the rocket button (or Device->capture from the menu) to configure an acquisition.
The important connection settings are shown above.
- In the Connection Settings box, choose the correct serial port and set the speed to 115200bps.
- In the Analyzer Settings box set recording size to 1K and make sure only the first channel group is selected. Set the sampling rate to 10kHz so the timing chart aligns properly, but this currently has no actual effect on the IR Toy sampling rate. All other settings are ignored by the IR Toy and don't impact SUMP performance.
- Press start to arm the IR Toy trigger and wait for a signal. The IR Toy LED lights.
- A change on the IR receiver triggers the sample timer. The LED turns off, and 1024 samples are taken at about 10kHz (every 100us).
- When capture is complete, the IR Toy dumps the samples back to SUMP. The IR Toy returns to remote decoder mode until SUMP is armed again.
Note that the IR Toy inverts the samples. The actual pin readings from the IR receiver are 0 active and 1 idle.
IRIO is a raw infrared input/output mode, it sends and receives raw IR waveforms. This mode can clone remote controls, and playback the signals to operate devices from a computer.
Click for full screenshot. In the screenshot we're running two IR toys on the same PC. One is in IRIO mode (left) the other is in RC5 decoder mode. First, we pressed #1 on a remote. The left screen shows the raw 10khz waveform samples (black text). The right screen shows the RC5 decoded output. We copied the waveform bitmap from the terminal and sent it back to the IR toy to transmit (pink text). The second IR toy received and decoded the signal just like it came from the original remote control.
IRIO mode is always in the receive state, except during transmission. Any activity on the IR receiver triggers sampling at 10kHz.
7F C0 1F E0 0F F8 07 FC 03 FE 01 FF 00 FF FF 80 3F E0 00 1F FF F8 07 FC 03 FE 01 FF 00 00 00 00 00
Each bit represents a sample of the IR signal state taken every 100us (10kHz), most significant bit first. Sampling stops after 40 consecutive samples (5 bytes) with no change on the IR receiver pin. The LED will light each time a sampling period starts, and turn off when it ends.
If there's ever so many samples that the IR Toy can't push data to the PC fast enough, the LED will stop blinking but data will continue. This is known as a buffer overflow. We haven't encountered it 10kHz, but it's a concern at higher sampling rates.
The IRIO mode exits the receive state and begins transmitting when it receives a data bitmap. Data bitmaps represent the IR waveform to reproduce in 100us (10kHz) segments.
Data bitmaps are single byte values that carry 7 'frames' of an IR transmission. The most significant bit of the byte is set to 1 to indicate a transmission bitmap. The remaining 7 bits toggle the modulated IR LED on (1) or off (0) for 1 time period. The default time period is 100us (10kHz).
The indicator LED will light while the transmitter is active. The IRIO mode returns to receive state when there's no data left to transmit.
- Reset 0x00 (returns to remote decoder mode)
- Setup sample timer 0x01 (send 2 bytes)
- Setup TX modulation 0x02 (send 2 bytes)
- 8bit TX enable 0x03
Send 'X' to put the IR Toy in raw infrared input/output mode. The IR Toy will respond 'X01', where 01 is the protocol version. Once in IRIO mode, use the commands to send and receive raw infrared signals.
0x00 returns the IR Toy to remote control decoder mode. This command is consistent across all modes (IRIO, SUMP), you can always send 0x00 to exit to remote control decoder mode.
Setup sample timer
IRIO mode starts with a 10kHz sample and playback timer. This can be changed by sending the the setup timer command, followed by two bytes that set the timer 1 offset. The first byte is the high 8bits, the second byte is the low 8bits. Use a PIC timer calculator to find the values (key calculation constants: timer 1, 1:1 prescaler, 48MHz fosc, 12MHz fcyc). See an example.
Setup TX modulation
The default infrared transmitter is modulated at 36kHz with a 50% duty cycle. This can be changed by sending the setup PWM command, a byte for the PR2 period register, and a don't care byte. The duty cycle is always 50%. Use a PIC timer calculator (update: our favorite online PWM calculator) to find the value (key calculation constants: timer 2/PR2, 48MHz fosc, 12MHz fcyc, 4x prescaler). See an example.
8bit TX enable
Send this command to enable 8bit transmit mode. The IR Toy transmits all 8bits of every byte it receives, instead of the 7bits described above. This mode works with the same 8bit values that the IRIO mode outputs when it receives a signal. It allows more data using fewer bytes, but there's no exit command. You'll have to unplug the IR Toy from the USB port to get out of raw mode.
TV-B-Gone firmware port
TV-B-Gone is a simple IR device that plays 130 POWER codes for TVs, the goal is a universal off (or on) button. Adafruit has a kit with source and excellent documentation. We ported the TV-B-Gone POWER codes to the IR Toy and wrote a simple player for the PIC microcontroller.
This feature doesn't need USB connectivity, so we put it in a separate firmware that uses the PIC sleep mode when it's not transmitting. Load it into the IR Toy with the USB bootloader (see the bootloader instructions below).
When the PIC starts, the POWER codes will play and the indicator LED will blink after each code is transmitted. The IR Toy will play the TV-B-Gone codes once, and then go to sleep. They can be played again by resetting the PIC, either by cycling the power, or temporarily connecting the MCLR pin to ground. The PCB has a footprint for a reset button (the button is not populated on the assembled version at Seeed, this is strictly DIY!).
The PIC architecture can't handle a single array with all 130 North American TV POWER codes, but we did manage to fit 120. If the codes were broken into smaller chunks, the PIC could hold both the NA and EU sets with plenty of room to spare. We didn't include the European codes because the original samples were missing from the project archive. We'll add the EU codes if the files are posted.
The IR Toy controls a single IR LED with an NPN transistor. The LED is set to 20mA current with a 180ohm resistor. A 'real' TV-B-Gone uses transistors to switch several IR LEDs at closer to 100mA, so the range of the IR Toy is only a fraction of the range of the TV-B-Gone.
Most IR emitters are rated for 100mA, so you could swap R4 (180ohms) with a 39ohm resistor to increase the power. Keep in mind that we used an NPN transistor rated for 200mA maximum, but you could also swap the transistor with a higher rated version and connect several high-power LEDs.
The IR Toy can be upgraded over the USB connection. It uses a modified version of the Diolan USB PIC bootloader. This is a great bootloader, written in ASM and released under the GPL, that enumerates as an HID device. The bootloader app is included in the project archive.
A neat thing about the IR Toy firmware is that it can be loaded with a normal programmer too. The firmware has a jump instruction at the appropriate location so that if a bootloader isn't present it will still work.
Follow these instructions to bootload a new firmware into the IR Toy.
Step 1. Activate the bootloader
Open a terminal to the IR Toy virtual serial port, type $. Alternately, place a jumper between the PGC and PGD pins, and then plug in the IR Toy.
The indicator LED will light when the bootloader is active.
Step 2. Upload the firmware
Run the bootloader app and upload a new firmware. Bootloader applications are available for Windows, Linux, and Mac.
Step 3. Reset the IR Toy
Unplug the IR Toy, remove the jumper, and plug it back in. The upgrade is complete.
Taking it further
The USB IR Toy is ready for hacking.
- The IRIO mode can be updated to capture and replay IR signals, including 2000 samples stored in the 256 byte internal EEPROM.
- Software to record remote control signals and automate TVs, cable boxes, etc.
- New speeds and sample lengths can be added to the SUMP logic analyzer mode.
- Additional protocols can be added to the remote control decoder.
- Add emulation of IR decoders besides IRman.
- Add a reset button to the footprint on the back.
We'll post the most recent firmware updates on our blog.You can also join the discussion in the USB IR Toy forum.