Monday, November 26, 2012

Custom RGB LED Strip Control, Part 1: The Remote Control

I recently acquired two 5m lengths of RGB LED strip, both of which came with control boxes, remote controls, and power supplies. Right now they're basic mood lighting for a room in my apartment. The problem is that the control boxes each drive their own strips, but work off of the same remote control. As such, I'm controlling them "together" by virtue of having taped their IR sensors next to each other. This...doesn't always work properly.

So instead, I would like to make a custom control box, one that can control the strips separately or in tandem, but will still function using the included remote control. I will be adding an increased brightness range and individual control over the red, green, and blue channels in the process. The MCU driving all this will be an MSP430G2553. If possible, I will also add an audio input that the MSP430 can use to sync the lights to music / sound.

The LED strip remote. Source


The first step is reverse engineering the remote control and writing control codes for it. Thankfully this part has been taken care of for me, thanks to this post by Mohonri. Using a TSOP34838 38 kHz IR receiver and a Saleae Logic Probe, I was able to confirm that the IR protocol is the same from Mohonri's post.

The protocol works by sending IR pulses at a 38 kHz rate when active. The start of a sequence is indicated by an active period of around 9 ms, followed by an inactive period of around 4.5 ms. After this, data is transmitted by sending a short pulse of around 650 us, then pausing either 650 us or 1.65 ms before sending another short pulse. A short pause indicates a 1, and a long pause indicates a 0. Decoding the data this way, I verified Mohonri's statement that 4 bytes are sent: the inverse of the address byte, the address byte, the inverse of the data byte, and the data byte. If a short pause were taken to be a 0 and a long pause to be a 1, then the bytes and their inverses would be swapped. So really, it can be taken either way.

Anyway, after decoding the data this way, I noted that the address byte is 0x00, that the data byte varies depending on the button pressed. After a bit of mucking around, I realized that the most logical arrangement is if the data is read as being sent least significant bit first. Decoding the button presses this way yielded the following layout:

RGB Remote Codes
Up
5C
Down
5D
Forward
41
Power
40
Red
58
Green
59
Blue
45
White
44
54 55 49 48
50 51 4D 4C
1C 1D 1E 1F
18 19 1A 1B
Up Red
14
Up Grn
15
Up Blu
16
Quick
17
Dwn Red
10
Dwn Grn
11
Dwn Blu
12
Slow
13
DIY1
0C
DIY2
0D
DIY3
0E
Auto
0F
DIY4
08
DIY5
09
DIY6
0A
Flash
0B
Jump3
04
Jump7
05
Fade3
06
Fade7
07

Notice how the codes mostly make sense once you get past the third row of colors. It kind of annoys me that the sensible layout gets ditched for the top part of the remote, but oh well; it wouldn't have made a difference in the code anyway.

Rather than manually decode these button presses, I used some MSP430 coding to get the data for the above table. Using the MSP430 Launchpad, I connected the IR receiver output directly to the TimerA1 CCR0 module and had it trigger an interrupt every time the line changed. I used some simple state machine coding to have it detect the initial pulse, then to start reading out data based on the length of each pause. The TimerA1 was configured to count to 0xFFFF continuously, so I could detect length of pauses by subtracting a second capture value from a previous capture value. CCR1 was used to reset it to initial conditions if no state change occurred after a certain period of time. The interrupt routine stored the data to a circular buffer, which I then read out using the USCI peripheral, which was set up as a UART transceiver.

(Side note: The Launchpad, for whatever reason, has the TX and RX lines hooked up wrong for the MSP430G2553. I had to swap them with some jumper cables. That little detail held me up a bit...)

I have uploaded all of my code, written in the Code Composer Studio 5.2 IDE, to Google Drive. Also included are my personal VT100 library and my BCD converter assembly function, which I find useful any time I'm dumping data out over a terminal.

Link to CCS Project: https://docs.google.com/open?id=0B5dybbS2PoDtV1dIaWNVLWhZWTA

With this code implemented, it should be easy to deal with IR remote data in the main program loop, especially if I just have it read in the data to a 4-byte buffer instead of a circular buffer, like I am now.

In my next post, I'll be working out how I'm going to actually drive all the channels on the LED strips.

2 comments:

  1. fun i was just a whole day busy with my scope and writing code to figure out the remote codes.....
    a weird issue with the LED Controller is that after a few powerup's the color on the keyboard of the remote not match the color of the led's: example push red, get blue, push green: get red, push blue get green....the kb rows are shifted......

    ReplyDelete
  2. wow what a fantastic post that you have published From RGB LED Strip under cabinet lighting LED lighting projects to the perfect bar for your mancave, this 10 meter LED Strip kit is long enough for most applications.i hope you should countinue with this stuff as well

    RGB LED Strip

    ReplyDelete