How to decode X10 RF protocol

In this article I will describe the method I used to decode the X10 RF protocol with a Raspberry Pi.

Before starting you have to setup correctly a Raspberry and a RF receiver @ 433Mhtz as I described in a previous post.

You can find all the code attached to this post on github: https://github.com/vdemay/433Rpi

Needed hardware

300px-RaspberryPi

 A Raspberry Pi

 Websitehttp://www.raspberrypi.org/

 Price: less than 50$ (Amazon)

Mine is a B Model

rf433k

 433Mhz RF link kit

 Price: less than 5$ (Amazon)

Build the hardware to snif RF

Now You get the right hardware you have to make a simple breakout:

RPi

The Antenna should be a 17cm long simple wire. Here on my exemple there are both emitter and receiver connected to the Raspberry. Obviously only the receiver is needed

photo

 

Install the software

Now it’s to prepare the software. My Raspberry is running a Raspbian. Once ssh’ed on it, install wiringPi (a lib to help to manage GPIO)

 

pi@raspberrypi ~ $ git clone git://git.drogon.net/wiringPi
...
pi@raspberrypi ~ $ cd wiringPi/wiringPi
pi@raspberrypi ~/wiringPi/wiringPi $ sudo su
...
root@raspberrypi:/home/pi/wiringPi/wiringPi# ./build

Test the install

root@raspberrypi:/home/pi/wiringPi/wiringPi# gpio readall
+----------+-Rev1-+------+--------+------+-------+
| wiringPi | GPIO | Phys | Name   | Mode | Value |
+----------+------+------+--------+------+-------+
|      0   |  17  |  11  | GPIO 0 | IN   | Low   |
|      1   |  18  |  12  | GPIO 1 | IN   | Low   |
|      2   |  21  |  13  | GPIO 2 | IN   | Low   |
|      3   |  22  |  15  | GPIO 3 | IN   | Low   |
|      4   |  23  |  16  | GPIO 4 | IN   | Low   |
|      5   |  24  |  18  | GPIO 5 | IN   | Low   |
|      6   |  25  |  22  | GPIO 6 | IN   | Low   |
|      7   |   4  |   7  | GPIO 7 | IN   | Low   |
|      8   |   0  |   3  | SDA    | IN   | High  |
|      9   |   1  |   5  | SCL    | IN   | High  |
|     10   |   8  |  24  | CE0    | IN   | High  |
|     11   |   7  |  26  | CE1    | IN   | High  |
|     12   |  10  |  19  | MOSI   | IN   | High  |
|     13   |   9  |  21  | MISO   | IN   | High  |
|     14   |  11  |  23  | SCLK   | IN   | High  |
|     15   |  14  |   8  | TxD    | ALT0 | High  |
|     16   |  15  |  10  | RxD    | ALT0 | High  |
+----------+------+------+--------+------+-------+

Ok, we are ready to go

Start to decode rf signal

First of all you have to know that signal received by the receiver is based on logical state changes. Here is a typical exemple  of signal received via RF:

signal

So the idea is to mesure time between each signal state changes (0 to 1 or 1 to 0) in order try to decode the binary message. It’s also necessary to start to measure signal change only after the signal started and not during the noise period.

Most of protocol are based on a lock to indicate the start of the signal. A Lock is a long period (ms) when the emitter send a 0 or a 1 (or a sequence of long 0 and 1) to indicate the signal will start:

lock

 

So first of all we’ll try to handle a lock programmatically with a simple C++ code: The goal of the soft is to attach interrupt each time the signal is falling or rising in order to mesure the time needed for a signal change. If the time to change is long, we can expect a lock is received.

Write a soft to try to understand x10 rf protocol

The aim here is to decode signal send by this device :


X10 3 Unit Slimline Wireless Wall Switch + Dimming
41WZKMXA2WL
$15 on Amazon
 

 

Here is a program waiting for a long period and then display duration of 0 and 1

Here is the output when I press a button:

Lock started
11224
===============================11224 316 25 139 89 286 64 25 126 82 14 136 60 128 21 100 109 88 22 74 30 75 22 92 23 74 27 82 41 56 
Lock started
11293
===============================11293 327 15 141 82 86 98 79 15 94 86 16 83 17 88 15 79 17 78 16 82 15 95 16 78 15 57 24 256 99 
Lock started
26783
===============================26783 390 8083 4069 471 532 470 1537 466 1553 448 547 466 540 471 528 480 527 480 536 469 1535 467 547 461 558 457 1536 467 1534 
Lock started
27166
===============================27166 8096 4068 464 531 482 1524 469 1540 464 560 447 560 447 555 454 551 460 539 470 1532 469 552 453 561 450 1550 452 1549 458 
Lock started
27155
===============================27155 8107 4077 457 543 465 1528 475 1533 467 549 462 538 476 539 459 555 452 552 460 1534 473 535 471 540 469 1545 456 1550 451 
Lock started
27160
===============================27160 8110 4072 458 552 451 1543 470 1523 478 541 467 552 453 555 452 553 455 556 450 1546 466 545 464 545 461 1541 457 1545 459 
Lock started
26445
===============================26445 800 8007 4089 459 550 455 1552 450 1542 466 550 459 542 466 546 460 642 149 24 148 639 449 1573 405 561 440 552 479 1524 
Lock started
27230
===============================27230 8055 4054 448 594 408 1604 417 1539 447 612 418 620 396 561 440 567 440 513 484 1592 421 521 483 534 464 1537 465 1610 416 
Lock started
27152
===============================27152 8115 4066 468 534 472 1522 477 1541 462 548 464 542 465 548 455 558 451 550 461 1535 476 527 479 552 454 1531 472 1543 456 
Lock started
24229
===============================24229 2968 8043 4106 455 559 444 1571 448 1523 473 533 474 549 455 553 458 550 457 557 449 1544 463 556 457 551 458 1535 463 1550 
Lock started
15903
===============================15903 18727 347 251 182 15 293 14 125 14 238 132 13 132 210 13 216 13 342 13 149 169 14 167 6422 14 476 321 15 187 
Lock started
11785
===============================11785 333 75 15 81 95 16 67 24 126 103 96 16 59 23 109 91 17 62 23 98 17 89 92 15 70 23 88 16 70

The program detect noise or signal from elsewhere, but when I press a button lot of output with a first values around 2700 are displayed. So we will suppose the lock code started by a value between around 2700us. If we look at the second value and third value when the first one is around 2700 we get something around 800us for the second value and 400us for the third one. So the lock seems to be:

  • 2700us
  • 800us
  • 400us

 

I stopped to consider the lock at this point because other values are much smaller. Reminder each value is a duration of a 0 state or of a 1 state. So If we imagine the first state is 0 we get the following lock:

lockVal so now we will try to understand the rest of the data taking as exemple the following

Lock started
27152
===============================27152 8115 4066 468 534 472 1522 477 1541 462 548 464 542 465 548 455 558 451 550 461 1535 476 527 479 552 454 1531 472 1543 456

As each value is duration of a 0 or a 1, the rest of the data should be consider  by pair (RF binary is often encoded with different duration between hight level and low level):

468 534
472 1522
477 1541
462 548
464 542
465 548
455 558
451 550
461 1535
476 527
479 552
552 1531
472 1543
456...

It seems we get a pattern : sometimes 450 and 550 and sometimes 4500 and 1500. Wahoo we get something : lockVal+value   Binary is usually encoded over RF on the following way  

  • 0 encoded with hight and low level with the same duration
  • 1 encoded with hight level longer than low level or hight level shorter than the low one.

 So here it seems we get 0110000010011… lockVal+value+decode   At this point we are not sure to get all needed changes to decode the signal. So I will update the soft to take into account our new knowledge:  

  • Handle the 3 changes making the lock (with a big tolerance)
  • Dump more changes to try to find out the right needed number (70)


Now when I press a button I get

Lock started
26983
Lock started 2
8011
Lock started 3
4106
===============================26983 8011 4106 442 581 381 1513 492 1530 443 511 481 559 448 542 500 500 461 515 480 1537 467 505 482 515 486 1512 527 1505 446 1496 481 1546 460 1492 481 552 450 525 476 546 461 509 487 543 461 512 485 522 480 546 466 1507 473 1556 434 1509 475 1546 454 1508 483 1538 449 1500 481 1547 453 26967 7997 
Lock started
26948
Lock started 2
8065
Lock started 3
4063
===============================26948 8065 4063 467 520 452 1525 463 1504 480 522 480 524 535 473 477 521 472 537 465 1509 481 524 479 518 479 1514 477 1527 465 1512 470 1518 475 1511 480 520 481 527 476 520 481 526 480 518 476 522 479 525 475 526 475 1525 469 1509 477 1518 475 1514 471 1534 460 1512 475 1509 478 1524 471 26941 8029

If you look at the 2 last changes, it seems to be the beginning of a new lock. If we count the number of changes we get :

 Number_of_dump - Lock_at_begging - beggining_of_lock_at_the_end = 70 - 3 - 2 = 65.

As wee need 2 changes to make a bit, I suppose that 421 before the beggining of the lock at the end is useless. Let update the program

  • We have to reduce the number of change to sniff to 67 (3 locks + 64 changes — bits)
  • And we are going to display bits instead of duration

 

Now we get the following

Lock started
26937
Lock started 2
7995
Lock started 3
4096
=============================== 01100000 10011111 00000000 11111111
Lock started
26926
Lock started 2
8047
Lock started 3
4091
=============================== 01100000 10011111 00000000 11111111
Lock started
26929
Lock started 2
7862
Lock started
26899
Lock started 2
8065
Lock started 3
4081
=============================== 01100000 10011111 00100000 11011111
Lock started
26925
Lock started 2
8049
Lock started 3
4068
=============================== 01100000 10011111 00100000 11011111

So we get bytes. It seems that the second byte is the complment from the first one and fourth one is the complement from the third one.

How to decode the binary signal

Decoding the binary signal is more tricky. So I asked my frind google to help me with this task. Here is the link needed to continue:

http://www.printcapture.com/files/X10_RF_Receiver.pdf
First all, it seems our reversed engineering is ok: Capture d’écran 2014-04-21 à 11.30.31 And the interesting section at this point is the table of byte values and meaning: Capture d’écran 2014-04-21 à 11.32.54   So if the next phase, we’ll try to transform our binary signal to a real value: I firstly did it only for Axx command. I’ll try to continue to maintain the code here: https://github.com/vdemay/433Rpi All you need to decode X10 Protocol is here: https://github.com/vdemay/433Rpi/blob/master/SignalReciever

And here is the output now:

 01100000 10011111 00000000 11111111
60 9f 00 ff 
A1 ON
 01100000 10011111 00000000 11111111
60 9f 00 ff 
A1 ON
 01100000 10011111 00110000 11001111
60 9f 30 cf 
A2 OFF
 01100000 10011111 00110000 11001111
60 9f 30 cf 
A2 OFF
 01100000 10011111 00001000 11110111
60 9f 08 f7 
A3 ON
 01100000 10011111 00001000 11110111
60 9f 08 f7 
A3 ON
 01100000 10011111 00100000 11011111
60 9f 20 df 
A1 OFF
 01100000 10011111 10011000 01100111
60 9f 98 67 
A DIM 005

2 Comments

Leave a Comment.