||6 years ago|
|AnslutaDemoCode||6 years ago|
|PCB||6 years ago|
|SPI_Data||6 years ago|
|images||6 years ago|
|ProtoSch.jpg||6 years ago|
|README.md||6 years ago|
|RemoteSnif.jpg||6 years ago|
|anslutaOr.JPG||6 years ago|
|cc2500module.jpg||6 years ago|
IKEA Ansluta 2.4Ghz remote controller
The Ansluta (OMLOPP) line of Ikea lamps only let u use one remote controller for each light.
I wanted to use multiple remotes to control one string of lights.
Another caveat of the original remotes is that it can only cycle through the different brightness levels. It cycles though: 0% - 50% - 100% - 50% - 0% - ....
I would like to turn it on to 50% brightness and turn it off without cycling to 100%.
This project is based around an CC2500 2.4Ghz wireless controller and an Atmega328 (ex Arduino Nano).
The choice for the CC2500 was easy because the original Ansluta Remote uses this IC, so it's definately possible to use this for controlling the lamp.
Some code is loosely based on:
Article Number Remote: 802.883.28
Article Number Transformer: 803.007.64 / 103.201.81
I had a look inside an orginal Ansluta remote, it uses an texas instrument uC (MSP430G2221) and an CC2500.
The CC2500 communicates over an SPI bus to the uC. So I've connected a "Bus Pirate" to the SPI bus of the uC and sniffed the commands and data packets to the wireless chip.
The settings for the bus pirate were (SPI sniffer utility):
Clock Edge= 0, Polarity= 1 RawData= 0
The sniffed data is in the file: "SPI_DATA.txt"
Every time the button is pressed a sequence is repeated 50 times: 2 data strobes are sent followed by a burst of data followed by a final strobe.
Together with the datasheet we can decode the data:
//Strobe 1: 5B 5B 5C 5C 36 36 0F 0F 5D 5D //0x36 SIDLE Exit RX/TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable //Strobe 2: 5B 5B 5C 5C 3B 3B 0F 0F 5D 5D //0x3B SFTX Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states. //Burst of data: 5B 5B 5C 5C 7F 7F 0F 0F 5C 5C //0x7F Burst access to TX FIFO 06 06 0F 0F 5C 5C 55 55 0F 0F 5C 5C 01 01 0F 0F 5C 5C 3E 3E 0F 0F 5C 5C //Address byte 1 94 94 0F 0F 5C 5C //Address byte 2 02 02 0F 0F 5C 5C //Indicates the light intensity 01=OFF; 02=50%; 03=100% AA AA 0F 0F 5C 5C FF FF 0F 0F 5D 5D //Final strobe: 5B 5B 5C 5C 35 35 0F 0F 5D 5D //0x35 STX In IDLE state: Enable TX.
So the module is awakened from sleep mode, the send buffer is cleared, data is loaded into the buffer and finaly the data is transmitted. This is repeated 50 times presumable to ensure that the data is received at least one time.
Clearly some data is missing (configuration of the CC2500).
When the battery's are inserted in the remote some initializing data is sent to the CC2500 (without pressing a button).
Indicating that the module is powered on continuously and a power-down method is used for preserving the battery's.
SPI Data Register Value 5B [5C 30 0x30(0F 0x0F)5D ] 5B [5C 00 0x00(0F 0x0F)5C 29 0x29(0F 0x0F)5D ] // IOCFG2 0x29 5B [5C 02 0x02(0F 0x0F)5C 06 0x06(0F 0x0F)5D ] // IOCFG0 0x06 5B [5C 06 0x06(0F 0x0F)5C FF 0xFF(0F 0x0F)5D ] // PKTLEN 0xFF 5B [5C 07 0x07(0F 0x0F)5C 04 0x04(0F 0x0F)5D ] // PKTCTRL1 0x04 5B [5C 08 0x08(0F 0x0F)5C 05 0x05(0F 0x0F)5D ] // PKTCTRL0 0x05 5B [5C 09 0x09(0F 0x0F)5C 01 0x01(0F 0x0F)5D ] // ADDR 0x01 5B [5C 0A 0x0A(0F 0x0F)5C 10 0x10(0F 0x0F)5D ] // CHANNR 0x10 5B [5C 0B 0x0B(0F 0x0F)5C 09 0x09(0F 0x0F)5D ] // FSCTRL1 0x09 5B [5C 0C 0x0C(0F 0x0F)5C 00 0x00(0F 0x0F)5D ] // FSCTRL0 0x00 5B [5C 0D 0x0D(0F 0x0F)5C 5D 0x5D(0F 0x0F)5D ] // FREQ2 0x5D 5B [5C 0E 0x0E(0F 0x0F)5C 93 0x93(0F 0x0F)5D ] // FREQ1 0x93 5B [5C 0F 0x0F(0F 0x0F)5C B1 0xB1(0F 0x0F)5D ] // FREQ0 0xB1 5B [5C 10 0x10(0F 0x0F)5C 2D 0x2D(0F 0x0F)5D ] // MDMCFG4 0x2D 5B [5C 11 0x11(0F 0x0F)5C 3B 0x3B(0F 0x0F)5D ] // MDMCFG3 0x3B 5B [5C 12 0x12(0F 0x0F)5C 73 0x73(0F 0x0F)5D ] // MDMCFG2 0x73 5B [5C 13 0x13(0F 0x0F)5C A2 0xA2(0F 0x0F)5D ] // MDMCFG1 0xA2 5B [5C 14 0x14(0F 0x0F)5C F8 0xF8(0F 0x0F)5D ] // MDMCFG0 0xF8 5B [5C 15 0x15(0F 0x0F)5C 01 0x01(0F 0x0F)5D ] // DEVIATN 0x01 5B [5C 16 0x16(0F 0x0F)5C 07 0x07(0F 0x0F)5D ] // MCSM2 0x07 5B [5C 17 0x17(0F 0x0F)5C 30 0x30(0F 0x0F)5D ] // MCSM1 0x30 5B [5C 18 0x18(0F 0x0F)5C 18 0x18(0F 0x0F)5D ] // MCSM0 0x18 5B [5C 19 0x19(0F 0x0F)5C 1D 0x1D(0F 0x0F)5D ] // FOCCFG 0x1D 5B [5C 1A 0x1A(0F 0x0F)5C 1C 0x1C(0F 0x0F)5D ] // BSCFG 0x1C 5B [5C 1B 0x1B(0F 0x0F)5C C7 0xC7(0F 0x0F)5D ] // AGCCTRL2 0xC7 5B [5C 1C 0x1C(0F 0x0F)5C 00 0x00(0F 0x0F)5D ] // AGCCTRL1 0x00 5B [5C 1D 0x1D(0F 0x0F)5C B2 0xB2(0F 0x0F)5D ] // AGCCTRL0 0xB2 5B [5C 1E 0x1E(0F 0x0F)5C 87 0x87(0F 0x0F)5D ] // WOREVT1 0x87 5B [5C 1F 0x1F(0F 0x0F)5C 6B 0x6B(0F 0x0F)5D ] // WOREVT0 0x6B 5B [5C 20 0x20(0F 0x0F)5C F8 0xF8(0F 0x0F)5D ] // WORCTRL 0xF8 5B [5C 21 0x21(0F 0x0F)5C B6 0xB6(0F 0x0F)5D ] // FREND1 0xB6 5B [5C 22 0x22(0F 0x0F)5C 10 0x10(0F 0x0F)5D ] // FREND0 0x10 5B [5C 23 0x23(0F 0x0F)5C EA 0xEA(0F 0x0F)5D ] // FSCAL3 0xEA 5B [5C 24 0x24(0F 0x0F)5C 0A 0x0A(0F 0x0F)5D ] // FSCAL2 0x0A 5B [5C 25 0x25(0F 0x0F)5C 00 0x00(0F 0x0F)5D ] // FSCAL1 0x00 5B [5C 26 0x26(0F 0x0F)5C 11 0x11(0F 0x0F)5D ] // FSCAL0 0x11 5B [5C 27 0x27(0F 0x0F)5C 41 0x41(0F 0x0F)5D ] // RCCTRL1 0x41 5B [5C 28 0x28(0F 0x0F)5C 00 0x00(0F 0x0F)5D ] // RCCTRL0 0x00 5B [5C 29 0x29(0F 0x0F)5C 59 0x59(0F 0x0F)5D ] // FSTEST 0x59 5B [5C 2C 0x2C(0F 0x0F)5C 88 0x88(0F 0x0F)5D ] // TEST2 0x88 5B [5C 2D 0x2D(0F 0x0F)5C 31 0x31(0F 0x0F)5D ] // TEST1 0x31 5B [5C 2E 0x2E(0F 0x0F)5C 0B 0x0B(0F 0x0F)5D ] // TEST0 0x0B 5B [5C 7E 0x7E(0F 0x0F)5C FF 0xFF(0F 0x0F)5D ] // ????? 0xFF -> unknown register 5B [5C 39 0x39(0F 0x0F)5D ]
####Pairing remote and transformer
When the button on the receiver is pressed (transformer) and the button on the transmitter is pushed (and held down) the receiver learns the address of the remote. The sniffed data can be found HERE.
//Strobe 1: 5B 5B 5C 5C 36 36 0F 0F 5D 5D //0x36 SIDLE Exit RX/TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable //Strobe 2: 5B 5B 5C 5C 3B 3B 0F 0F 5D 5D //0x3B SFTX Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states. //Burst of data: 5B 5B 5C 5C 7F 7F 0F 0F 5C 5C //0x7F Burst access to TX FIFO 06 06 0F 0F 5C 5C 55 55 0F 0F 5C 5C 01 01 0F 0F 5C 5C 3E 3E 0F 0F 5C 5C //Address byte 1 94 94 0F 0F 5C 5C //Address byte 2 FF FF 0F 0F 5C 5C //Indicates the pairing sequence AA AA 0F 0F 5C 5C FF FF 0F 0F 5D 5D //Final strobe: 5B 5B 5C 5C 35 35 0F 0F 5D 5D //0x35 STX In IDLE state: Enable TX.
The sniffed SPI data shows first a standard button press (because the button is pressed) and afterwards the same sequence with only one byte changed. The byte that dictates the status of the light (Off - 50% - 100%) is replaced by 0xFF.
Just like a standard button press the sequence is repeated 50 times.
We can also conclude that the remote never receives any data and dependig of the button presses always sends the same data.
The CC2500 is readily available as module on ebay with integrated antenna and capacitors so no RF design is needed. Only an SPI connection and power supply is needed. I chose a cheap ebay module with a real CC2500 IC (no glob top).
To communicate with the wireless module by SPI, I used an arduino nano because I had it laying around.
For connecting the nano to the CC2500 we have to be carefull with the different voltages. The CC2500 is 3V and the nano is 5V.
An easy (dirty) way to connect them is using a resistor (about 1K) in series with the data lines comming for the arduino (MOSI, CLK, CS). The data line comming from the CC2500 (MISO) doesn't need a resistor (a high level from CC2500 is 3V and the nano's input detects it as a high level without modifications).
The lineair voltage regulator (3.3V) on the nano is used as power source for the wireless module.
Now we have the necessary SPI data we and hardware we can write some basic code for the nano.
The resulting code can be found HERE.
The configuration of the module is mostly the same as the original IKEA remote except the output power is changed to the maximal TX power by setting the first byte of the PATABLE with 0xFF.
The IDLE mode isn't used because after we configure the module we immediately send the data.
The SPI settings (found by looking at the graph in the datasheet "Configuration Register Write and Read Operations") are:
- SPI Mode 0
- MSB First
- Max speed: 6Mhz (no need to use extra delays)
The prototype code has been updated (see changelog.txt).
Demo code flow:
- First it initializes the CC2500
- Tries to listen to another (original remote) and extract the address.
- Sends the command to turn the light on 50%
- Sends the command to turn the light on 100%
- Sends the command to turn the light off
- Sends the command to pair the remote and the receiver
The standard address is 0x01 0x01, this can be changed in the code.
Now that the prototype works it's time to make a couple of remotes to control the light.
##Designing a PCB
###PCB design goals
- A seperate button for each light intensity (so no need to cycle through every intensity).
- No low power modes (if possible) only battery usage when a button is pressed.
- Small outline < 50mmx50mm
- Thin PCB design so no high components.
- (Temporary) Connection for ICSP.
I could use 2 buttons, one for 50% On and one for 100% on. Then the first press turns the light on and the second press turn the light off. With this configuration it's necessary to save the state of the light. This could be done in RAM but then continuous power is needed. This could be done in EEPROM but this doesn't have a lot of write cycles. So I've chosen to use 3 seperate buttons (On 50%, On 100%, OFF).
For the height constraint I didn't want to use elco's so I've used tantalium capacitors for buffering the power rails.
As battery I've chosen the CR2032 coin battery. To save space I left an opening in the PCB.
When pushing a button power is supplied to the capacitors and the atmega through a diode. At the same time a digital port is pulled high so the atmega knows which button is pushed. I hope the capacitors can store enough energy to send the data to the lights. The atmega can be powered on al the time by soldering a jumperpad.
The xtal is 4Mhz so the uC would work with voltages as low as 1.8V
For the ICSP I drew a edge connector with a standard pinout.
The CC2500 antenna sticks out of the PCB because the PCB would shield the signal.
DISCLAIMER: The designed PCB is UNTESTED, I'm waiting for the board house to test the PCB's.