Controlling a ceiling fan and light with an Arduino
How the remote control works
The remote control is typically mounted on the wall and has several buttons that can be used to adjust the brightness of the light and the speed of the fan, as well as a set of switches that can be used to identify the remote control. When the user presses one of the buttons, a microcontroller inside the remote control generates a stream of ones and zeros based on the setting of the switches and the button pressed. For example, the code to toggle the state of the light is 1111111111111110000011010
. Each one is then encoded as a short pulse, and each zero is encoded as a long pulse.
This waveform is then output to the RF oscillator. When the output signal is high, the RF oscillator is oscillating at around 304 MHz, and when the signal is low, the oscillator is off. The receiver in the ceiling fan will listen for this 304 MHz signal and decode the received instruction.
Reverse engineering the commands
When I replaced the ceiling fan controller, I kept the old one, as it used the same frequency. Inside the old controller, there was a receiver module which outputs a digital 1 if it detected the 304 MHz signal was detected, and a digital 0 otherwise. I was able to use this module to listen to the signal transmitted by the new remote control and determine the packet structure and timing for the signal.
Each packet consists of 25 bits. The first 13 bits are ones, the next 4 bits are the code as configured by the switches on the remote, and the last 8 are the command. Each packet is transmitted four times with a 12 millisecond delay in between.
Code | Command |
---|---|
0001 1010 | Toggle lights |
0000 0001 | Fan on high |
0000 0010 | Fan on medium |
0000 0011 | Fan on low |
0000 0000 | Fan off |
0001 1011 | Toggle lights (for some models this may be a different set of lights) |
1001 1010 | Power button (switches fan and light) |
0011 0000 | Variable/random fan speed |
0001 1110 | Blink on, then off, then on |
0001 1111 | Turn light off with 20s delay. Only works after 0001 1110 |
1001 1011 | Turn light and fan off |
Using the old remote with an Arduino
As shown in the image above, the old remote control contained two circuit boards. The right half held the buttons and was mounted to the front of the remote control. The left half contained the regulator and the RF oscillator/transmitter. The circuit board on the right would generate the digital signal and feed it into the DOUT
socket on the left board. Pin 7, +5V
and GND
on the Arduino were connected to the DOUT
, VDD
, and GND
sockets on the left circuit board respectively. The Arduino was programmed to accept a serial command and send a command to the ceiling fan as described above. TODO: link code
This method worked, but I wanted to keep the old receiver and remote control together and intact, so I had to search for a different transmitter. Looking through my collection of old circuit boards, I found a wireless doorbell that operated at a frequency of 315 MHz.
Modifying and using the wireless doorbell
The wireless doorbell contained a main circuit board, which generated the binary stream, and a satellite board, that contained the RF oscillator and transmitter. The oscillator circuit was based on the PT4455 chip, which contains a phase-locked loop for generating the high frequency, as well as a power amplifier. The oscillator circuit also contained a 9.844 MHz crystal, which was multiplied by 32 by the PT4455 to get the 315 MHz needed for transmission. Thus, all that needed to be done to change the transmission frequency was to change the crystal frequency to 9.5 MHz (304 MHz / 32). I had no 9.5 MHz oscillator or crystal, but I was able to use my DE0-Nano FPGA module to synthesize the appropriate frequency using one of its internal phase-locked loops.
However, actually getting the PT4455 to output the 304MHz signal was much more difficult, as simply injecting the 9.5 MHz signal into the XIN
input did not work. I also had to inject the complementary signal (180 degrees out of phase) to the XOUT
pin. This was done with a transformer, with the primary connected to the output of the FPGA through a resistor and the secondary connected across the old 9.844 MHz crystal.
Despite the 100 MHz bandwidth of my oscilloscope, I was able to verify that the PT4455 was generating the correct frequencies by using the scope's FFT function. This lets me look at the frequencies present in a signal, even if they are not apparent in the signal itself. It was evident that the modification caused the output frequency to change from 315 MHz to 304 MHz.
Comments
Post a Comment