As should be obvious from this blog, I am somewhat drawn to clever and minimalistic implementations of consumer electronics. Sometimes quite a bit of ingeniosity is going into making something “cheap”. The festive season is a boon to that, as we are bestowed with the latest innovation in animated RGB Christmas lights. I was obviously intrigued, when I learned from a comment on GitHub about a new type of RGB light chain that was controlled using only the power lines. I managed to score a similar product to analyze it.
The product I found is shown below. It is a remote controlled RGB curtain. There are many similar products out there. What is special about this one, is that there are groups of LEDs with individual color control, allowing not only to set the color globally but also supporting animated color effects. The control groups are randomly distributed across the curtain.

The same type of LEDs also seems to be used in different products, like “rope-light” for outside usage. A common indication for this LED type seems to be the type of remote control being used, that has both color and animation options (see above).
There seems to be an earlier version of similar LEDs (thanks to Harald for the link) that allows changing global color setting in a similar scheme but without the addressability.
Physical analysis
Let’s first take a quick look at the controller. The entire device is USB powered. There is a single 8 pin microcontroller with a 32.768kHz quarz. Possibly to enable reliable timing (there is a timer option on the remote controler) and low power operation when the curtain is turned off. The pinout of the MCU seems to follow the PIC12F50x scheme which is also used by many similar devices (e.g. Padauk, Holtek, MDT). The marking “MF2523E” is unfamiliar though and it was not possible to identify the controller. Luckily this is not necessary to analyze the operation. There are two power mosfets which are obviously used to control the LED string. Only two lines connect to the entire string, named L- (GND) and L+.
All 100 (up to 300 in larger versions) LEDs are connected to the same two lines. These types of strings are known as “copper string lights” and you can see how they are made here (Thanks to Harald from µC.net for the link!). It’s obvious that it is easier to change the LED than the string manufacturing process, so any improvement that does not require additional wires (or even a daisy chain connection like WS2812) is much easier to introduce.

Close up images of a single LED are shown above. We can clearly see that there is a small integrated circuit in every lightsource, and three very tiny LED chips.
Trying to break the LED apart to get a better look at the IC surface was not successful, as the package always delaminated between carrer (The tiny pcb on the left) and chips (still embedded in the epoxy diffusor on the right). What can be deduced however, is that the IC is approximatly 0.4 x 0.6 = 0.24 mm² in area. That is actually around the size of a more complex WS2812 controller IC.
LED Characterization
Hooking up the LEDs directly to a power supply caused them to turn on white. Curiously there does not seem to be any kind of constant current source in the LEDs. The current changes direclty in proportion to the applied voltage, as shown below. The internal resistance is around 35 Ohms.
This does obviously simplify the IC a lot, since it basically only has to provide a switch instead of a current source like in the WS2812. It also appears that this allows to regulate the overall current consumption of the LED chain from the string controller by changing the string voltage and control settings. The overall current consumption of the curtain is between 300-450 mA, right up to the allowable maximum of power draw of USB2.0. Maybe this seemingly “low quality” solution is a bit more clever than it looks at the first glance. There is a danger of droop of course, if too much voltage is lost over the length of the string.
How Is It Controlled?
Luckily, with only two wires involved, analyzing the protocol is not that complex. I simply hooked up one channel of my oscilloscope to the end of the LED string and recorded what happened when I changed the color settings using the remote control.
The scope image above shows the entire control signal sequence when setting all LEDs to “red”. Some initial observations:
- The string is controlled by pulling the entire string voltage to ground for short durations of time (“pulses”). This is very simple to implement, but requires the LED controller to retain information without external power for a short time.
- We can directly read from the string voltage whether LEDs are turned on or off.
- The first half of the sequence obviously turns all LEDs off (indeed, the string flickers when changing color settings), while the second half of the sequence turns all LEDs on with the desired color setting.
Some more experimentation revealed that the communication is based on messages consisting of an address field and a data field. The data transmission is initiated with a single pulse. The count of following pulses indicates the value that is being transmitted using simple linear encoding (Which seems to be similar to what ChayD observed in his string, so possibly the devices are indeeed the same). No binary encoding is used.
Address and data field are separated by a short pause. A longer pause indicates that the message is complete and changes to the LED settings are latched after a certain time has passed.
My findings are summarized in the diagram above. The signal timing seems to be derived from minimum cycle timing of the 32.768kHz Crystal using with the microcontroller, as one clock cycle equals ~31 µs. Possibly the pulse timing can be shortened a bit, but then one also has to consider that the LED string is basically a huge antenna…
Address Field | Function |
0 | Unused / No Function |
1 … 6 | Address one of six LED subgroubs (zones), writes datafield value into RGB Latch. |
7 | Address all LEDs at once (broadcast), adds datafield value to RGB latch content. |
RGB Latch Value | RGB encoding |
0 (000) | Turn LEDs off (Black) |
1 (001) | Red |
2 (010) | Green |
3 (011) | Yellow (Red+Green) |
4 (100) | Blue |
5 (101) | Magenta (Red+Blue) |
6 (110) | Cyan (Green+Blue) |
7 (111) | White |
The address field can take values between 1 and 7. A total of six different zones can be addressed with addresses 1 to 6. The data that can be transmitted to the LED is fairly limited. It is only possible to turn the red, green and blue channels on or off, realizing 7 primary color combinations and “off”. Any kind of intermediate color gradient has to be generated by quickly changing between color settings.
To aid this, there is a special function when the address is set to 7. In this mode, all zones are addressed at the same time. But instead of writing the content of the data field to the RGB latch, it is added to it. This allows, for example, changing between neighbouring colors in all zones at once, reducing communication overhe