Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
fpga_fan_controller [2016/08/11 11:26]
joel
fpga_fan_controller [2017/12/06 11:18] (current)
Line 1: Line 1:
 ====== FPGA Fan Controller ====== ====== FPGA Fan Controller ======
 +My Ceiling fan is controlled by a [[https://www.amazon.com/Hunter-27185-Light-Remote-Control/dp/B00002NC0D|Hunter Fan Co 27185]] remote control, which transmits control messages over RF at 350MHz.
 +
 {{:hunter_fan:20160612-ceiling-fan.jpg?0x250|}} {{:hunter_fan:20160612-ceiling-fan.jpg?0x250|}}
 {{:hunter_fan:20160612-controller-front.jpg?0x250|}} {{:hunter_fan:20160612-controller-front.jpg?0x250|}}
 {{:hunter_fan:20160612-controller-back.jpg?0x250|}} {{:hunter_fan:20160612-controller-back.jpg?0x250|}}
  
 +Internally the device uses a [[http://www.futurlec.com/Datasheet/Others/HT12E.pdf|HT12E]] encoder chip driving a 350MHz LC oscillator.
 +
 +It has a 4-bit DIP switch that controls the id of the fan that will be controlled.
 +===== Capture =====
 +==== Gqrx ====
 {{:hunter_fan:20160618-gqrx-capture.jpg?0x500|}} {{:hunter_fan:20160618-gqrx-capture.jpg?0x500|}}
  
 +I used my RTLSDR and [[http://gqrx.dk/|Gqrx]] to capture transmissions from the remote, which revealed the following things...
 +
 +  * When buttons are pressed, bunches of packets are transmitted in [[https://en.wikipedia.org/wiki/On-off_keying|OOK]] (On-off keying).
 +  * The carrier frequency is not at all accurately tuned to 350MHz, and drifts significantly based on the transmitter's relative to other objects, and to temperature. This is to be expected with an LC oscillator with no accurate frequency reference.
 +
 +
 +==== Inspectrum ====
 {{:hunter_fan:20160612-inspectrum.jpg?500x|}} {{:hunter_fan:20160612-inspectrum.jpg?500x|}}
  
 +[[https://github.com/miek/inspectrum|Inspectrum]] is a promising open source project that enables very quick and easy analysis of narrow-band signals contained in IQ-data captures.
 +
 +Analysis of the transmissions captured by Gqrx revealed that the packets are sent in a PWM (pulse-width modulation) scheme over OOK.
 +==== GNU Radio ====
 {{:hunter_fan:20160612-envelope-detector.png?750x|}} {{:hunter_fan:20160612-envelope-detector.png?750x|}}
  
 {{:hunter_fan:20160612-threshold.png?0x350|}} {{:hunter_fan:20160612-threshold.png?0x350|}}
 +
 +With the modulation of the packets now known, I used GNU radio to construct a real-time version of the Inspectrum demodulator.
 +
 +==== Packet Format ====
 +Data is transmitted by a 2/3rd / 1/3rd PWM scheme at ~2000bps.
  
 {{:hunter_fan:pwm-modulation.png|}} {{:hunter_fan:pwm-modulation.png|}}
 +
 +^ Command     ^ Preamble  ^^ 4-bit Fan Id   ^^^^ 7-bit Payload             ^^^^^^^
 +^ Off         | 0   | 0      | LSB | ⋅   | ⋅   | MSB | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
 +^ Speed 1     | ::: | :::    | ::: | ::: | ::: | ::: | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
 +^ Speed 2     | ::: | :::    | ::: | ::: | ::: | ::: | 1 | 1 | 1 | 0 | 0 | 1 | 0 |
 +^ Speed 3     | ::: | :::    | ::: | ::: | ::: | ::: | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
 +^ Lamp On/Off | ::: | :::    | ::: | ::: | ::: | ::: | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
 +
 +===== iCE40 FPGA Implementation =====
 +I wanted to make use of the [[http://www.clifford.at/icestorm/|Yosys/Arachne-PNR/IceStorm]] open FPGA synthesis  tool-chain for the [[http://www.latticesemi.com/Products/FPGAandCPLD/iCE40.aspx|iCE40]], a small FPGA made by Lattice.
 +
 +Because of the simple modulation scheme, it's possible to transmit the 350MHz packets by simply wiggling a pin with a flying lead attached, which acts as a monopole antenna.
 +
 +The source is available on [[https://github.com/jhol/hunter-fan-controller|github]]. The final implementation allows the fan to be controlled through push-buttons and over serial-over-USB via the board's FT2232 USB interface.
  
 {{:hunter_fan:20160612-ice40hx8k-board.jpg?0x250}} {{:hunter_fan:20160612-ice40hx8k-board.jpg?0x250}}
Line 18: Line 55:
 {{:hunter_fan:20160612-transmit-signal.png?0x250|}} {{:hunter_fan:20160612-transmit-signal.png?0x250|}}
 {{:hunter_fan:20160618-completed-unit.jpg?0x250|}} {{:hunter_fan:20160618-completed-unit.jpg?0x250|}}
 +
 +==== Performance ====
 +The ideal quarter-wave antenna length for a monopole 350MHz is ~214mm. With a flying lead of this length, I found that the FPGA could transmit to a distance of 150m. This range is quite excessive, so I trimmed the antenna to ~50mm which the reduced the transmission range to a more reasonable distance.
 +
 +Given that there are only 16 id-codes possible with the 4-bit DIP switch, and that the transmit range is so long, and that the fans in my housing complex are presumably all the same type, it would be easy to prank the neighbors in the housing complex by transmitting random commands to all the ids at once. 
fpga_fan_controller.1470929219.txt.gz · Last modified: 2017/12/06 11:18 (external edit)