Milight RF control

Milight bulbs and Milight remote experiments are what this page is all about. These are sold not only under the Milight brand but also as Easybulb and LimitlessLED. This page focusses on the RF method of communication with the bulbs. RF is the way that the milight bridge communicates with the bulb also.

I used the Milight 6W RGBWW bulb costing €7.98 and this remote control suitable for the RGBW bulb which costs €7.13. In addition i have bought two CW WW remotes which cost €6,47. Opening the bulb you find a PL1167 RF transmitter/receiver and the STM8S003F3P6 microcontroller. After buying these i found that there was a new development with additional possibilities. These are this remote costing €8.48 and this 8W RGBWW & CW bulb costing €14.33. The difference is that there is saturation control and a colour temperature control. There is a separate page dedicated to this type as they are very different from the other remotes due to the encryption.

I wanted to see if it would be possible to mimic the Philips Hue by adding more functionality to the milight bulbs. To do that the first steps are to see how the bulbs are controlled. There are two options which various people have also started to do. I found that Henryk Plötz had already discovered the protocol and i used his code to transmit the signals using an arduino.

I actually used a nRF24L01+ to transmit to the PL1167 on the milight bulb and also receive from the milight remote control. The second method uses a PL1167 to do the transmission as demonstrated by Authometion. Woodster has published the code on how to do that. So in order to do a brain transplant of the milight bulb it would be needed to receive the RF 2.4GHz signal and translate that to the status of the RGB leds. Below you can see my attempts on an arduino with my own nRF24L01 prototype board and the nRF24L01 fitted.

CMD byte = 0x00 means one of the touch sliders was used and released.
The remote streams every intermediate value immediately with no resends, but then adds the customary amount of resends –with CMD 0x00 after you let go. In this case the sequence number can increment more than 1. The least significant bit of the upper nibble in the CMD byte indicates a long press on the corresponding button:
0x11 is “all: white”, 0x12 is “all: night mode”, 0x13 is “group 1: white”, and so on.
This applies to all buttons even to the disco mode buttons (but doesn’t seem to trigger any functionality in the bulb).
The value of the sliders are as follows:
Color. Goes from 0x00 to 0xFF.
0x00 is 9 o’clock (purple), 0x40 is 6 o’clock (yellow), 0x80 is 3 o’clock (green), 0xC0 is 12 o’clock (blue). See color wheen below.
Brightness: Goes from 0x90 at the leftmost end to 0x20 in the middle, after getting to 0x00 it jumps to 0xF8 and then reduces to 0xB0 on the rightmost end. The increments are in 0x08.
When pressing the disco button the modes are cycled and the current disco mode is reflected in the lower nibble of the first byte. This cycles from 0xB0 to 0xB8 and then cycles back to 0xB0. This disco mode is maintained when pressing other buttons, but reset on touching the color wheel.

Below on the left you can see the button numbers and on the right the so called “disco” mode and what this means.
0x0E means the brightness slider and 0x0F is the color slider.

Here you can download the whole thing including the attachments. Below you can see the output of the program showing both incoming and outgoing transmissions. This is indicated by the leading arrow. To the left <– is incoming and to the right –> outgoing.

Sending routine:
Type in 7 hexcodes back to back without space.
Eg B05465CCC001E2……..
The letters A-F can be upper or lower case.
Type a number of “.” characters at end this will repeat the message and make the transmission reliable
X gives you extended commands:
You can toggle the receiver with r
You can repeat the last transmission with “.”
In the PL1167_nRF24.cpp file you can uncomment the //#define DEBUG_PRINTF to get additional information about the package and the conversion to human readible bytes.
The Milight bulbs uses the PL1167 chip for transmission. In the table below you can see how the transmission of a certain 7 byte message is padded with preamble, sync word CRC and trailer to get a certain sequence of bits on air. To mimic that using the nRF24L01 chip you have to manipulate the transmission quite a bit because the different bits are processed in a different way and put on air differently. Below you can see how this can be done to get the same sequence of bits on air. Similarly decoding the packets also needs this manipulation to recover the actual message.
Below you can see how the nRF24L01 is manipulated to transmit the message conform the milight protocol.

The syncword is different for the three different remotes i tested as was the transmitter channels.
Remote type Sync word Transmission channels
RGBW 0x147A 0x258B 9, 40, 71
CW WW 0x0a0A 0x55AA 4, 39, 74

Observations from light bulb operations.
RemoteID = (2 bytes) This is stored into the bulb’s EEPROM during remote-bulb sync at power on,
max of 4 per bulb, syncing a 5th RemoteID drops the first one that is stored in that bulb.
When clearing the bulb it removes all 4 remote ids from the bulb
Checksum = See checksum calc function code below. 2 Bytes
Uses Channel 9 2411MHz
Repeat again using Channel 40 2442MHz
Repeat again using Channel 71 2473MHz
Repeat again 5 to 40 times to ensure the bulbs receive the command.

Controller PCB for bulb control

So next step now that i could receive the 2.4GHz signal from the transmitter was to design a circuit that could replace the STM8S003F3P6 and PL1167 on the original controller board on the milight bulb. It would be simpler to program the STM8S003F3P6 controller with a new software but i do not know how to do that. If anyone does please let me know. Below you can find my design for this circuit. Its a very small print of 25 x 23 mm so that it replaces the current microprocessor and RF receiver. You can see the panel PCB that i had made which reduces the cost of making the PCB significantly. It takes about 10-15mins to solder all the components to the PCB and then you are good to go.

I have now tested this circuit and it works as advertised. The next steps in the project are to write the software to control the milight bulb from the remote using the above. I will then be able to modify the functionality of the bulb using first the remote. At this moment i am cleaning up the code and trying to make the RGBW and CW WW remotes work on the same Milight bulb.

Once the circuit is built you need to program the bootloader into it. This is done by connecting it to an arduino as per the diagram below. You can see that it uses the arduino X3 connector and a software which you can download from here. The link to the original software has disappeared so this is a local copy. The function of the X3 interface and how to use it is described here. This is the reason the RESET pin has the prominent position on the board.

I use the optiboot bootloader which you can download. Please use the appropriate version. I used the optiboot_atmega328.hex file as that is the processor and clock speed i used 16MHz. The fuse settings are as follows for an Atmega328. hfuse = DA lfuse = FF efuse = 05. If you use a different processor you need different fuse settings. Once the bootloader is programmed you can use a normal FTDI cable connected as shown (Please observe colors) below and program the device using the arduino IDE.

It is not possible to use CS or MOSI together with PWM. To solve this problem there are two solutions. Use a non SPI pin such as the PD4 together with softPWM. With softPWM you can get PWM on any pin without using the pins required for SPI. Another solution is to use software SPI. This way you can use pins 10 and 13 intended for SPI for PWM operation and use any other pin for software SPI. I opted for using both software solutions. (softPWM and softSPI) The software SPI is infact included in the nRF24 software. You need to install the library from here https://github.com/greiman/DigitalIO Then you simply enable the #define SOFTSPI in the RF24_config.h file.

Replacing the Milight LED PCB

Below is the schematic for the milight LED PCB replacing the original. The original 6W RGBW Milight bulb has LED’s which depending on the version of the PCB are 5730 or 2835. In both cases there are 10 pcs. In addition there are 4 pcs of RGB led’s which provide the colour on the original milight print. The white LED’s on the milight PCB can be WW or CW but not both.
This new designed PCB has a total of 20 pcs of LED for regular 5730 or 5630 LED’s. It is constructed in such a way that 10 pcs of cold white and 10 pcs of warm white can be controlled independantly. You could also choose to place all 20 pcs with the same white colour for more brightness. There is also a jumper present so that you can control all the LED’s using only 4 channels from the controller print. There are no vias and so i made the backside just a copper layer which should conduct the heat very well to the aluminium heat sink. You attach the PCB using the two small holes which screw into the heat sink. To drive this you need a total of 5 channels from the driver PCB which is provided for. It means the PCB has the capability to control the white channels independantly changing the white tone.
In addition there are 4 regular RGB LED chips which provide the colour. These are controlled by three independant channels from the controller board.

Two versions of the original Milight LED PCB with 5630 and 2835 LED sizes. The clone LED PCB is designed for the larger 5630 LED’s.

Donor Milight lamp

There are two methods for making a DIY milight compatible lamp.
Firstly you can use a donor Milight bulb. You need to open this up and desolder the print with the processor and PL1167. You then solder the controller PCB in its place.
this way you use the Milight casing and also the original power supply. It is also possible to replace the LED PCB in addition which gives the advantage of more LED’s and the ability to use both WW and CW led’s.

Cloning Milight from scratch

The second method you do the whole thing from scratch. You buy a bulb which comes with a base and lid. Taking off the lid leaves you with the base. The 220V parts are connected to wires. You can solder these to the power supply. This regulates 12V for use by the controller PCB above. A diode drops the voltage to 11.3V and then the AMS1117 regulator makes 5V out of it on which the microprocessor works. The 12V is passed through to the LED circuit so that this is the voltage on which that works. There is also a aluminium disc which serves as a heat sink. You need to be very carefull to mount the power supply as the inside of the housing is also aluminium and this of course conducts electricity and could shock you. With the milight version the power supply is already mounted in the base. As the cost of the bulb is below 8€ including delivery its hardly worth making the effort for the total DIY solution. To give you an idea I paid 1.19€ for the power supply and 1.70€ for the base, lid and heat sink but with an additional 2.56€ shipment per piece. I think the latter can be done more cheaply if you look around. Then you need some epoxy resin to glue the PCB in place which costs around 1€. So in all its also around 6.50€ vs 7.98€ for a complete Milight cone. So no brainer use a donar lamp.

Software

Still work in progress i’m afraid. Soon.
Below is a small piece of software that is able to distinguish between a RGBW remote and a CW WW remote.
I want to use this to automatically react to both types of remotes. The above software is working with RGBW only.
If you want to change the above software to work with the CW WW remote you need to change retval = _pl1167.setSyncword(0x147A, 0x258B); on line 42 of MiLightRadio.cpp to retval = _pl1167.setSyncword(0x050A, 0x55AA); and in addition change the channels static const uint8_t CHANNELS[] = {9, 40, 71}; to 4, 39 and 74.
Of course the meaning of the buttons are different so interpretation also needs to be adjusted.