I remember all the excitement years ago on sites like HackADay regarding software-defined radio. I wanted so badly to jump on the bandwagon, but couldn’t think of a reason. Jump to earlier this year when I was looking for another remote for my RF controlled fan (I inherited the RF fan control with the house). I wanted another remote because I’d turn on the light at the wall-mounted RF switch as I entered the room and wouldn’t think to turn it off until I was already in bed. A bedside remote seemed like a good, simple solution. The problem: I couldn’t find a remote that was guaranteed to work with my fan. Hunter seemed to create fan remotes willy-nilly rather than having all of their fans work with the same remotes.

I finally had my reason to get into SDR and for the low-low price of $12, no less! After some initial failed attempts and a long break, I tried again due to my new interest in home automation. This time I headed over to fcc.io and looked up the FCC ID (IN2TX31) and discovered a litany of information. It’s a truly great resource. Armed with the information that the remote broadcast its signals at roughly 434MHz, I used SDR# (my linux install was busted at the time) and tuned in. Sure enough, I saw a blip each time I pressed a button on the fan’s transmitter. I didn’t know exactly what to do with this, though. A friend suggested I output the file and read it with something like Audacity. BITS!

Lots of bits. Too many bits to transcribe by hand. After watching a few of Samy Kamkar’s videos on YouTube, I checked out a tool called rtl_433. I started the tool in analyze mode and, after changing the frequency to 433.92MHz, I was getting consistent hex values for each key. I then attempted to correlate those values with the bit sequence in the wav file.

Beginning of rtl_433 output: 0000 0000 0001 0100 0101 1110 0110 0110 1011 1101 0000 1111 1001 0111

Beginning of rtl_433 output: 0000 0000 0001 0100 0101 1110 0110 0110 1011 1101 0000 1111 1001 0111

Pretty darn close! The preamble isn’t picked up correctly, but at least the majority of the command was decoded by rtl_433 so that I don’t need to figure it out by hand. The next step was to get a transmitter. Fortunately, 433ish MHz is pretty common and transmitters are cheap and readily available. I bought some that even came with receivers for a few bucks off Amazon. They’re super simple to operate. 3 pins: vcc, ground, and data. I hooked it up to my Raspberry Pi, wrote a quick python script to send a signal to the data pin, and ran it while I watched SDR#. Success! Wow, that was easy. Just a sanity check, but it was reassuring.

The next step was to write the script. This took some trial and error. The 3 fan speed buttons send a sequence twice, the light and fan-off buttons send 2 sequences twice. Each sequence sent has a preamble and begins the same way. I determined the approximate width of a pulse by highlighting the shortest high pattern in Audacity, looking at the number of samples, and dividing the number of samples by the sample rate. I crossed my fingers hoping the receiver wasn’t too strict (it isn’t). The shortest high pattern appears to be the same width as the lows that separate the signals. Armed with this information and guessing that a zero was the width of 2 ones, I created the script. I used the Audacity sample calculation to determine the delay between the resend of the signals too.

1,269 / 3,200,000 ~= 0.0004 seconds

In the image above, Audacity is displaying at a sample rate of 3.2 million samples per second. If we highlight the smallest pulse, we see that it consists of roughly 1,269 samples. So we have samples and samples per second, which means we can easily calculate the number of seconds (or in this case fractions of a second) a pulse is. 1,269 samples / 3,200,000 samples / second ~= 0.0004 seconds.

Now that the script was roughed out, it was time to see if the Pi was sending some semblance of a binary sequence. I started recording and ran the script. It looked good! Unfortunately, the fan didn’t react at all. What could it be? Maybe the transmitter was too weak or maybe the signal timing was off. Those are two real possibilities that would be difficult to prove and/or correct. I decided it was best to first compare the signals sent by the Pi with those sent by the remote. Hmm, the commands sent from the Pi are slightly different.

I made the necessary changes and ran the script. To my surprise, the fan turned on! I went through the same steps to get the rest of the buttons working. It was time for bed and I was happy with the progress I’d made. In the days that followed, I figured out how to run the script via the home automation software I’m using (Home Assistant). No more getting back out of bed to turn off the light or control the fan! I also plan to set up an automation that turns the fan off if the temperature (reported by my Nest thermostat) drops below a certain temperature.

The source code for this project can be found here. I did my best to explain how the script works. Below is an example of one of the “double” commands (either light or fan_off, I can’t remember).



Leave a Reply

Your email address will not be published. Required fields are marked *