Saturday 14 June 2014

How to decode a 433Mhz RF signal (Arduino)

So you have a device which has a 433Mhz RF remote control and you would like to have an Arduino with a RF transmitter emulate the remote and control the device directly.
The first thing is to order a couple of parts that you will need. You will want a 433Mhz transmitter and receiver and you can get the ones advertised for the Arduino very cheaply off ebay. You will also need a prototype board and some jumper wires to temporarily connecting the RF receiver.
Next you will need a logic analyser so you can view the signal and decode it. I bought a 'USB Logic Analyser' from the ebay seller EllieShang. This logic analyser is programmable and there is a good guide that you should read about programming it to work with different software on jwandrews.co.uk. My logic analyser happened to already be set to work with the Salae Logic analyser software (can be freely downloaded) so I didn't need to reprogram it.

Now that you have all that you need connect the RF receiver to the prototype board. You can use the 5V and GND from the Arduino to power the RF receiver. You dont need to solder an additional antenna to the RF receiver as it will work fine if you just hold the transmitter remote control within a few cm. Connect the logic analyser to the GND and its first input to the RF receiver data pin and you are ready to go.


Now you should be able to hold the remote near the RF receiver, hold down a button and capture the waveform in the Saleae software. It should look something like this
Head over to Tinkerman's blog for instructions on how to decode the waveform. The only thing not mentioned there is how to calculate the pulse length. A 'short' is one pulse width wide and a 'long' is 3 pulse widths. So you can see that each of the four possible values are 8 pulse widths in length. There are twelve codes so that give 12*8=96. In addition there is also a synchronisation pulse at the end followed by 31 low pulse widths. So overall the transmission is 128 pulse widths. So you can calculate the pulse width as 39.24ms/128 = 307us. If you wish to make sure your Arduino is spot on with its timing you can just capture its signal and compare and tweak the timing as required.

To see how to program an Arduino with this data have a look at my blog entry Controlling Bye Bye Standby devices using an Arduino


Controlling Bye Bye Standby devices using an Arduino

Note: Since the receivers are learning and the old Bye Bye units had a switch to select the channel and a 'house code' I don't know if all the transmitters are the same. It would make sense if they were not otherwise two neighbours could interfere with each others devices. Therefore the codes below probably wont work straight away but you could teach your devices to use these codes. If you wish to still use your existing remote then take a look at my next blog which gives instructions on how to decode the RF signal yourself.

First you will need a 433Mhz RF transmitter which can be bought cheaply off ebay. You will also need to download the RCSwitch library.
The Bye Bye Standby units use a quad state code which the RCSwitch library does not support. However on Tinkerman's blog he details the few changes that need to be added to get this supported. Its a very good blog so well worth reading any way.
The RF transmitter can work with a supply voltage up to 12V and with a good antenna can have a range of many hundreds of meters. A good option when interfacing with an Arduino is to run it off the built in 5V supply and solder a 17cm long wire to the antenna pad. I found that I was able to reliably control a device behind the TV in the front downstairs room from the back bedroom.
Next all you need are the codes for the Bye Bye Standby which I have included in the following sketch.
#include <RCSwitch.h>
#define MAX_STRING_LEN 25

RCSwitch mySwitch = RCSwitch();
String lineinput = "";

void setup() {
  Serial.begin(9600);
  mySwitch.enableTransmit(10);
  mySwitch.setProtocol(1);
  mySwitch.setRepeatTransmit(10);
  mySwitch.setPulseLength(300); // Bye Bye Standby
}

void loop() {
  while (Serial.available() > 0)
  {
    char c = Serial.read();
    if (c != '\n')
    {
      lineinput += c;
    }
    else {
      // handle entered data or request
      Serial.println("Entry='" + lineinput + "'");
      lineinput.trim();
      if (lineinput == "1on")
      {
          mySwitch.sendTriState("X0X1F00XXX11");
      }
      if (lineinput == "1off")
      {
          mySwitch.sendTriState("X0X1F00XXXF1");
      }
      if (lineinput == "2on")
      {
          mySwitch.sendTriState("X0X1F00XXX1F");
      }
      if (lineinput == "2off")
      {
          mySwitch.sendTriState("X0X1F00XXXFF");
      }
      if (lineinput == "3on")
      {
          mySwitch.sendTriState("X0X1F00XXXX1");
      }
      if (lineinput == "3off")
      {
          mySwitch.sendTriState("X0X1F00XXX01");
      }
      if (lineinput == "4on")
      {
          mySwitch.sendTriState("X0X1F00XXX1X");
      }
      if (lineinput == "4off")
      {
          mySwitch.sendTriState("X0X1F00XXXFX");
      }
      if (lineinput == "5on")
      {
          mySwitch.sendTriState("X0X1F00XXX10");
      }
      if (lineinput == "5off")
      {
          mySwitch.sendTriState("X0X1F00XXXF0");
      }
      if (lineinput == "6on")
      {
          mySwitch.sendTriState("X0X1F00XXXXX");
      }
      if (lineinput == "6off")
      {
          mySwitch.sendTriState("X0X1F00XXX0X");
      }
      if (lineinput == "allon")
      {
          mySwitch.sendTriState("X0X1F00XXXXF");
      }
      if (lineinput == "alloff")
      {
          mySwitch.sendTriState("X0X1F00XXX0F");
      }
      lineinput = "";
    }
  }
}