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.


Up  Down Play Pwr
0x3A 0xBA 0x82 0x02

Red  Grn  Blu  Wht
1A   9A   A2   22

2A   AA   92   12

0A   8A   B2   32

38   B8   78   F8

18   98   58   D8

RUp  GUp  BUp  Quick
28   A8   68   E8

RDn  GDn  BDn  Slow
08   88   48   C8

DIY1 DIY2 DIY3 AUTO
30   B0   70   F0

DIY4 DIY5 DIY6 Flash
10   90   50   D0

JMP3 JMP7 Fade Fade7
20   A0   60   E0

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.

9 Responses to “Reversing an RGB LED remote”

  1. a reader says:

    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!

  2. navycook86 says:

    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.

    • jean says:

      i’m sure its a software bug in the controller, got the same issue after a few powerup’s

  3. cypherpunks says:

    I got a similar device and spent a while playing with it.

    Mine uses a fixed PWM period of 6400 µs (156.25 Hz), divided into 80 × 80 µs ticks (12.5 kHz PWM clock). The LEDs are wired common anode so the low side can be switched.

    The 8 dim levels are 12.5, 25, 37.5, … 100% on, 10, 20, … 80 out
    of 80 ticks of on time.

    The “DIY” buttons support 28 dimming levels, which are 0, 3, 6, …, 75, 78 or 80 ticks of on time.

    The fades use single-tick increments.

    Internally, there’s an 8-pin PIC12F5xx microcontroller (with the P/N sanded off, but the power pin locations give it away) connected to an Atmel 24C02N I2C EEPROM.

    The pin assignments are:

    1- Vcc (generated by a series diode, 680Ω R, and 4.7V zener)
    2- SCL (10K pull-up)
    3- SDA (5.1K pull-up)
    4- IR input (another giveaway this is a Microchip part)
    5- Blue output (470Ω to gate of low-side transistor)
    6- Red output
    7- Green output
    8- GND

    There’s a 0.1 µF capacitor in parallel with the zener diode.

    The IR receiver is powered trough a 100 ohm resistor followed by a second 0.1 µF decoupling cap.

    I haven’t tried dumping the PIC program ROM.

  4. paulolondres says:

    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.

  5. paulolondres says:

    sorry i meant bulb light

  6. darius says:

    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

    thanks

  7. darius says:

    My congratulations on your RGB LED remote howitworks

    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.

    thanks

    darius

    hfexchange at gmail.com

    • admin says:

      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.