Reversing an RGB LED remote

I have this dream to someday light our basement with RGB LEDs. They often come with remotes and controllers, which are surprisingly inexpensive. The problem with the remotes you get for cheap on ebay is that you *have* to use the remote to change the lights, and that of course limits you to the buttons on the remote.

I’d like to make an in-wall dimmer/color changer for LED mood lighting, but with the added feature of being compatible with the existing cheap LED remotes on the market.

That means reverse-engineering one. And here it is:

Hardware

What’s the first thing I do when I get a new gadget? Take it apart, of course. Inside, it’s pretty simple:

There’s a 256-Byte two-wire serial EEPROM in the top left, a 5V linear regulator along the lower edge, and an unmarked 16-pin IC that is the main controller. Three transistors along the side drive the three colors of LEDs, and an external IR receiver connects to the board via the Red/Blue/Black triad.

I’m really not sure what the serial EEPROM is there for–perhaps the memory setting I couldn’t get to work?

IR Protocol

I soldered a couple leads to appropriate points and hooked it up to the oscilloscope to capture the incoming signals. Some day I hope to own a logic analyzer, but for now the oscope will suffice, especially when I only need one or two channels.

Run a Single trigger, press a button on the remote, and here’s what I got:

A bunch of zooming/shifting/saving/etc later, I had a bunch of data captured. Here’s the signal you get when pressing the “Red” button (click for big):

When the IR LED is on, the signal goes low, and when it’s off, the signal goes high.

There’s a 9ms low pulse, a 4.5ms high pulse, and then the data starts. Off I ran to find some IR protocols. I found myself in a familiar place–SBProjects, which contains a remarkably thorough knowledgebase on IR remotes and protocols. As it turns out, the protocol is the NEC protocol Each bit is encoded by a 560uS on pulse followed by an off pulse of varying length–560uS off is a logical 0, 1680uS off is a logical one. There are 32 bytes total. The first byte is an address, the second is the inverse of the address, the third is the command, and the fourth is the inverse of the command, with a final on pulse after the last bit. It’s little-endian, so least-significant bit comes first for each byte.

I mapped out all the remote’s buttons, and here’s the result. For all buttons, the address was 0xFF. Only in the command did it differ. The following table contains the buttons and commands. Note that these are little-endian, and written in hex.

It’s pretty much a binary key matrix–the remote is just sending a code for the key that was pressed, rather than RGB values or anything more complex. The first four rows have A as the second nybble (little-endian, though!), the next four have 8 (0xA minus 0x1), the last three have 0 (0x8 minus 0x8). The second column is the same as the first column except for the first bit being flipped. The third column is the same as the first, except the second bit is flipped, and the third column has both the first and second bits flipped compared to the first column.

All the decoding must be done in the controller.

Outputs

The controller outputs a PWM signal for each color. I noticed that the PWM frequency didn’t seem all that high–I could at times detect the flashing. (As an aside, it drives me nuts that car companies use stupidly low PWM frequencies for LED tail/brake lights, but that’s another subject) So I checked out the wave form for the outputs.

Each output is turned on for 840uS per cycle. To vary the brightness, the controller adjusts the off time. That varies from 5.36mS at the dimmest setting to 320uS at the brightest. That means the controller only gets up to about 72% duty cycle at its brightest setting, and down to 14% at the lowest setting. Since humans percieve brightness logarithmically, there’s a big low end that’s getting missed, although it might be too dim at that end to be useful.

Where am I going next with this? I’m not sure yet, but at least it’s now documented.

This entry was posted on Thursday, May 10th, 2012 at 00:22 and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed.
Both comments and pings are currently closed.

9 Responses to “Reversing an RGB LED remote”

Great work! I have the same (or a very similar) rgb led lamp aquired from dealextreme. I, too, wanted to find out about the protocol. I got as far as to know its the NEC protocol. Now i know the remote sends key matrix codes. Would have been nice if it had sent rgb codesm but oh well.
Anyway, thanks for sharing!

This may be a little off topic, but I have a couple of IR control boxes for my LED strips. When I got them in the mail, they worked fine. Yesterday, I plugged one in and it lit up blue. The remote control has new batteries and I have tried multiple light strips and control boxes. I’m not sure why it’s not changing colors. Any help would be greatly appreciated.

Hi guys, I was thinking to use these rgb lamp with arduino and make a chromotherapy bed . On the top of the bed use a system like a printer, with a step motor and an especific time, the light go foward and change the color.

Than I think could use the matrix code to change the color of the light instead of the remote control.

Hello,
I could I contact author of this manual.
I have got alike RGB LED remote and would like to replace it by computer generated IR codes to control RGB LED from a computer via IT port (IRDA) in my laptop.

Please email me since discussion is 1 year old.
hfexchange at gmail.com

Tell me at what wavelength operates IR diode in remote for RGB LED
since I would like to replace standard remote with IRDA port in laptop
not sure if IR wavelengths match or how to discover the correct wavelength.

The IrDA port almost certainly uses the correct wavelength, but I don’t know enough about how IrDA works. My guess is that it won’t work–the modulation frequency may be totally different (or nonexistent), the bitrate is probably different, and the encoding is likely different as well.