Tag Archives: 433 MHz RF

IMG_20160527_004843x

Adding RF to a non-RF ITEAD Sonoff

Yes, sure! You can buy a Sonoff RF and you are good to go, I guess. But I didn’t and I was not so sure about the no-named RF receiver so I ended thinking about adding my own.

But first things first. The Sonoff is an ESP8266 based smart switch by ITEAD which comes with a custom firmware that communicates with the manufacturer cloud to provide “smart” capabilities like remote switching or scheduling. The cool thing is that it has a line of pins that expose the VCC, GND, RX and TX pins of the ESP8266 and a buttons attached to GPIO0 so very soon it got hacked and there are a number of firmwares already available. I’m not an early adopter and some work has been done and reported by Peter Scargill, Javier or even in instructables.

The ITead Sonoff Smart WiFi Switch after a small hack to use the Avidsen RF remote to toggle it

The ITead Sonoff Smart WiFi Switch after a small hack to use the Avidsen RF remote to toggle it

Continue reading

Decoding 433MHz RF data from wireless switches. The data

[UPDATE 2013-03-01] I have added links to the encoder chips these two remote use and removed some miss-assumptions for the Noru remotes. The explanation now is simpler, but the main questions about the Noru codes remain.

In my previous post I explained how I decoded the data from two wireless outlet remotes using a couple of libraries for Arduino and a Bus Pirate in logic analyser mode. Now I want to go more in-depth, showing the captures from OLS and the data I obtained.

A bit of theory

Just a little bit. These remotes send the information using a common type of modulation called Amplitude-Shift Keying (ASK). This is the digital equivalent to the Amplitude Modulation (AM) used in long distance radio broadcast. The information is encoded as an increase or decrease in the amplitude of a carrier wave of (in this case) 433.92MHz. The information itself is sent at lower frequencies (some tens of KHz).

Since ASK is meant for digital communications, the information itself is encoded as a stream of 0’s and 1’s. A pattern of 0’s and 1’s define a “state”. The remotes like the Avidsen I have use 3 different states, code bits or tribits. They all begin with a high pulse (a 1) and end with a low pulse (a 0). The next image shows the pattern for these 3 states:

Tribits

Note that you can speak these patterns in different ways: as a succession of pulse lengths, like “short long short long” or “1313” (the long pulses are three times longer that the short ones) for the tri-bit 0, or as a tuple of bits like “00” (1 for a long high, 0 for a short high).

Now, the full signal is a series of code bits, a code word. 12 for the two remotes I have checked. These 12 code bits can be writen down as “11111FF0FFF0” (this is the ON command for outlet C in channel 31 for the Avidsen remotes).

Since the tribits are, well, 3-state bits, you can think of the previous code as a base-3 number, where the ‘F’ is a ‘2’: 111112202220. the RemoteSwitch library has a method that accepts the decimal equivalent for this base-3 number, with in this case is (read back-wards, the least significative bit is the rightmost one):

0*3^0 + 2*3^1 + 2*3^2 + 2*3^3 +
0*3^4 + 2*3^5 + 2*3^6 + 1*3^7 +
1*3^8 + 1*3^9 + 1*3^10 + 1*3^11 = 266649

But this number is just a convenience and we are moving away from the actual signal representation.

Avidsen remote

These remotes use the PT2262 parallel to serial encoder (datasheet). These chips have 12 parallel input lines you can individually set to HIGH, LOW o leave them floating for the three different states or tri-bits. When the input lines are set you assert low the TE pin and the data is encoded and output through the DOUT pin. They are supported by existing Arduino libraries (more or less, see the patch for the RCSwitch library in my previous post). The code word is a stream of 12 tribits arranged this way:

  • The first set of 5 are the channel (the one you configure in the dip switch of the remotes and the outlets). This is a value from 0 to 31 which is actually encoded in binary where the tribit 1 represents a 1 and the tribit F represents a 0.
  • The second set of 5 tribits is the outlet identification you configure in the second set of 5 dip switches of each outlet. All the tribits in this set must be set to F except for one, which represents the outlet selection in the remote from A to E.
  • The last set of 2 tribits represent the action, and it can be “F0” for ON, or “0F” for OFF.

Now, some captures.

Channel 00, Outlet A ON - FFFFF0FFFFF0

Channel 00, Outlet A, ON – FFFFF0FFFFF0

Channel 31, Outlet C ON - 11111FF0FFF0

Channel 31, Outlet C ON – 11111FF0FFF0

Channel 31, Outlet A OFF - 111110FFFF0F

Channel 31, Outlet A OFF – 111110FFFF0F


With these information you can actually control up to 32*5=160 different outlets from your favourite microcontroller.

Noru remote

This remote uses the HS1527 programmable encoder (datasheet). These chips have a hardcoded preamble of 20 bits (normal 0/1 bits) and 4 data lines to set 4 data bits. The total length of the message is the 24 bits. Mind these are normal bits: 0 is encoded as a short high pulse followed by a long low one whilst 1 is encoded as a long high pulse followed by a short low one.

The message length is thus the same as in the previous remote but it is not 100% compatible with the Arduino libraries since you can encode a forth combination of highs and lows, a fourth state or tetra-bit mimicking the naming convention:

Tetrabits

The codes for the 14 buttons of the Noru remote are (in binary format and tetra-bit format):

Button Binary Tetrabits
ON1 110100000000001101011000 1F000001FFX0
OFF1 110100000000001101010110 1F000001FFFX
SET1 110100000000001101011101 1F000001FF1F
ON2 110100000000001101011100 1F000001FF10
OFF2 110100000000001101010100 1F000001FFF0
SET2 110100000000001101011011 1F000001FFX1
ON3 110100000000001101011010 1F000001FFXX
OFF3 110100000000001101010010 1F000001FF0X
SET3 110100000000001101011110 1F000001FF1X
1H 110100000000001101011001 1F000001FFXF
2H 110100000000001101010111 1F000001FFF1
4H 110100000000001101010011 1F000001FF01
8H 110100000000001101010001 1F000001FF0F
ALL OFF 110100000000001101010101 1F000001FFFF

As you can see the first 20 bits are always de same. It’s the identification hardcoded in the HS1527. Only the four rightmost bits change. There are 16 possible combinations and 14 are being used by the 14 buttons (only the 00 and 11 endings are missing from the table). But, is there any pattern in this 4 bits?

There are some clues to start working with:

  • Some codes are common for all the outlets (the timeouts and the ALL OFF button)
  • Some codes are specific for a certain outlet (ON, OFF and SET)
  • When you start using an outlet you first have to set it in learning mode and press the ON button in the remote for the number you want to assign to it. From then on the outlet will start responding to that button, but also to the OFF and SET buttons for the same number. So there has to be some pattern that links ON, OFF and SET buttons for the same outlet.
  • According to the documentation an outlet can learn more than one code. The same code can be linked to more than one outlet and one outlet can respond to more than one code. I don’t know if this is somewhat useful to figure out the pattern but it’s cool!

Some captures for a couple of Nero remote signals and enough for now.

Outlet 1 ON - 1F000001FFX0

Outlet 1 ON – 1F000001FFX0

Outlet 2 SET - 1F000001FFX1

Outlet 2 SET – 1F000001FFX1

Decoding 433MHz RF data from wireless switches

[Update 2013-03-01] I have added more documentation on the codes these remotes use in a different post.

I’m starting to move towards not only gathering information but also acting. My first project in this subject will be controlling some lights and the house heaters. So last week I visited the urban market of “Els Encants” in Barcelona and bought some very cheap wireless outlets.

Two different remotes

I bought two sets of three wall plugs, each set with it’s own remote. They all transmit in the 433MHz frequency and I already had a set of transmitter and receiver for that frequency so as soon as I had some time I started trying to intercept and reproduce the codes the remotes were sending.

Sample outlets from each set plus remotes

Sample outlets from each set plus remotes

In the image above you can see an outlet and the remote for each of the sets. The left one is branded “Noru” and each outlet is rated 3kW (good for the heaters) and it features auto switch off time (1, 2, 4 or 8 hours). The remote can control a maximum of 3 outlets and apparently it is programmable, since you first have to sync the outlets with the remote.

The right one is branded “Avidsen”, also 433Mhz but rated 1000W, just below the consumption of my house electrical heaters, but good to control lights and other appliances. It’s got the very common dip switch to sync the remote and up to five outlets. There are 32 different channels available. So if your lights switch on and off randomly maybe you neighbour is using the same channel you are, then you better change the channel.

Available libraries for Arduino

I started reading documentation about the protocol these devices use and found out there is some very useful information out there. In fact there are even a couple of libraries for Arduino. The first one is called RemoteSwitch and it is a little old, it has not been ported to Arduino 1.0 but if you are like me you will keep a copy of Arduino 0023 just for this kind of situations.

The second library is called RCSwitch and I have to say it is a neat piece of code. It has been ported to the Raspberry Pi, although the port is not as updated as the original Arduino library.

My first tests with the RemoteSwitch library were encouraging. The Show_received_code sketch dumped the codes for the Avidsen remote one by one. I though: if it can decode it, it should be able to recreate it. And it worked from scratch. Good!

But by then I knew I wanted to use the newer library. There were several reason for this: it is being actively developed, it supports more protocols, the code is much more elegant and object oriented and it has a port to RPi, which I plan to use as a central gateway soon. So I checked which one of the RCSwitch protocols matched the one I had successfully used with RemoteSwitch and started doing some more tests…

Slightly different protocol

Here was when things started to get complicated. The thing did not work. So I spent a couple of hours studying the code for both libraries, decoding the codes the RemoteSwitch library had dumped before and trying to find the difference. Until I found it: RCSwitch.cpp, line 239, that ‘0’ should be a ‘1’… and everything started working again. Very good! I started a thread in the library forum to find out whether this is a bug or a slightly different protocol.

Index: RCSwitch.cpp
===================================================================
--- RCSwitch.cpp	(revision 219)
+++ RCSwitch.cpp	(working copy)
@@ -284,7 +284,7 @@
         if (sGroup[i] == '0') {
             sDipSwitches[j++] = 'F';
         } else {
-            sDipSwitches[j++] = '0';
+            sDipSwitches[j++] = '1';
         }
     }

By the way, the protocol of these things is pretty interesting. It’s worth a look at Sui’s post to get an overview of the implementation. The tri-bit concept is really awkward.

Using the Bus Pirate and OLS Logic Analyser

Then I moved to the other set of outlets. These are rated 3000W so I plan to use them to control my house heaters, which is the main reason for all this work. I followed the same steps, starting with getting the codes with the Show_received_code sketch. But weird enough the library was only able to decode some of the button presses… Only the SET button for outlet #1, the ON and OFF buttons for outlet #2, the ALL OFF button or the 2, 4 and 8H timeout buttons seemed to work.

This time it was going to be harder, since I didn’t even have all the codes. Well, a good opportunity to use my Bus Pirate!

Bus Pirate to the rescue!

Bus Pirate to the rescue!

So I plugged the RF receiver to the Bus Pirate and launched the OLS Logic Analyser to capture the signal from the remote.

You don’t have to configure anything to use the Bus Pirate as a (low speed) logic analyser. But since I wanted to power the radio receiver with the BP I had to enable the Power Supply mode. To do so you have to open a terminal session, type ‘?’ to get a prompt, select one of the modes that allow enabling the power supply typing ‘m’ and selecting the mode (like UART, for instance) and then type ‘W’ (uppercase to enable, lowercase to disable). Then you can close the session and it will keep the power on the 5V and 3V3 lines as long as it is plugged to the computer. Mind you have to free the port so the logic analyser software can use it. I had problems doing it with screen or minicom, but it worked great with picocom.

After some tests with the Avidsen remote (I knew what the codes were so I could compare the signal output with the actual code) I started getting the signals for each and every button in the Noru remote.

The image below shows the signal for the ON button for the outlet #1.

Signal for the #1 ON button of the Noru remote

Signal for the #1 ON button of the Noru remote

Now, since the RemoteSwitch library was able to decode some of the signals, the protocol could not be that different. So I started to decode manually all the signals applying the same protocol. The signal is a series of 12 tri-bits plus a sync-bit. For the Avidsen-like remotes there are 3 different tri-bit values (logically), they are called 0, 1 and F, for “floating”. Each tri-bit has a pulses shape. The following tables describes the pulses:

Tri-bit Pulses
0 short high + long low + short high + long low
1 long high + short low + long high + short low
F short high + long low + long high + short low

The long pulses are about 3 times the length of the sort ones. The overall period is a characteristic of each remote. There is also a trailing high pulse followed by a long low which is called “sync bit”.

A fourth tri-bit?

Decoding the signals from the Noru remote I found out that there was a fourth tri-bit value (well maybe I should call them tetra-bits now). In fact it is obvious since there is a forth option for an alternate sequence of 4 highs and lows. I’ve named the new tetra-bit X (for unknown, but also after my name :P). The full table for the Noru remotes is:

Tretra-bit Pulses
0 short high + long low + short high + long low
1 long high + short low + long high + short low
F short high + long low + long high + short low
X long high + short low + short high + long low

Now the previous image for the ON#1 button can be decoded as 1F000001FFX0S. With a small patch I could make this work with the RCSwitch library. The library cannot create the code but you can feed it to the sendTriState method to generate the signal.

Index: RCSwitch.h
===================================================================
--- RCSwitch.h	(revision 219)
+++ RCSwitch.h	(working copy)
@@ -106,6 +106,7 @@
     void sendT0();
     void sendT1();
     void sendTF();
+    void sendTX();
     void send0();
     void send1();
     void sendSync();
Index: RCSwitch.cpp
===================================================================
--- RCSwitch.cpp	(revision 219)
+++ RCSwitch.cpp	(working copy)
@@ -441,6 +441,9 @@
         case '1':
           this->sendT1();
         break;
+        case 'X':
+          this->sendTX();
+        break;
       }
       i++;
     }
@@ -561,6 +564,16 @@
 void RCSwitch::sendTF() {
   this->transmit(1,3);
   this->transmit(3,1);
+}
+
+/**
+ * Sends a Tri-State "X" Bit
+ *            ___   _
+ * Waveform: |   |_| |___
+ */
+void RCSwitch::sendTX() {
+  this->transmit(3,1);
+  this->transmit(1,3);
 }

 /**

And this is a sample code for Arduino that switches on and off outlet #1 every 2 seconds.

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {

  Serial.begin(9600);

  // Transmitter is connected to Arduino Pin #11
  mySwitch.enableTransmit(11);

  // Optional set pulse length.
  mySwitch.setPulseLength(302);

  // Optional set protocol (default is 1, will work for most outlets)
  mySwitch.setProtocol(1);

  // Optional set number of transmission repetitions.
  mySwitch.setRepeatTransmit(6);

}

void loop() {
    mySwitch.sendTriState("1F000001FFX0");
    delay(2000);
    mySwitch.sendTriState("1F000001FFFX");
    delay(2000);
}

Again, comments are more than welcome!