0

I have installed Domoticz on Raspberry Pi and bought an RfxCom 433MHz emitter/receiver. It works well for example with Chacon DiO 54781 door sensor. I want to create my own sensor with Arduino that would be recognized by Domoticz as a native RF 433MHz device. In first place, I want to make a flooding sensor, I also need an On/Off information. I would like to implement X10 protocol because it seems to be the simplest one.

asked Aug 10, 2016 at 7:46

1 Answer 1

2

I finally found a documentation about RF X10 protocol: X10 RF Receiver.pdf

With following Hardware :

I've created the following working code for Arduino Nano :

/*
* Custom sensor (base code)
*
* Emission in RF 433MHz with the X10 protocol for Domoticz
*
* Hardware :
* Arduino Pro Mini 5V (4€) https://www.amazon.fr/gp/product/B00QPUEFNW/ref=oh_aui_search_detailpage?ie=UTF8&psc=1
* RF 433MHz emitter/receiver (3€) https://www.amazon.fr/HDigiWorld-metteur-cepteur-commande-Arduino/dp/B00JTQI39G/ref=sr_1_3?s=computers&ie=UTF8&qid=1470813610&sr=1-3&keywords=433
* Note: only the emitter is used
* 3 wires : VCC, GND, Signal (on Arduino pin 2)
*
* Documentation found for RF X10: http://www.printcapture.com/files/X10_RF_Receiver.pdf
*
* Example of malformed data received in RfxMngr in mode "nodec" (before this code was correctly debugged) :
*
* Packettype = UNDECODED RF Message
* UNDECODED NEC:1C515C86F0 
*
*
* Correct data that is now receveived by RfxMngr with this program :
*
*------------------------------------------------
* Packettype = Lighting1
* subtype = X10
* Sequence nbr = 13
* housecode = D
* unitcode = 1
* Command = On
* Signal level = 7 -64dBm
*------------------------------------------------
* Packettype = Lighting1
* subtype = X10
* Sequence nbr = 14
* housecode = D
* unitcode = 1
* Command = Off
* Signal level = 7 -64dBm
*------------------------------------------------
*/
const int pin_emit = 2; // Signal pin for RF433 emitter
const int pin_led = 13; // Internal LED : it will be ON when the "On" command is sent in RF, and OFF the the "Off" command is sent (changed each 60s)
const unsigned int X10_A1_ON = 0x00; 
const unsigned int X10_A1_OFF = 0x20;
const unsigned int X10_address = 5; // this is Housecode. In my case 5 results in "D" house code
unsigned int X10_data = X10_A1_ON; // command. I have implemented only On/Off for unit code 1
void setup() {
 pinMode(pin_led, OUTPUT);
 pinMode(pin_emit, OUTPUT);
 digitalWrite(pin_emit, LOW);
}
/**
* Bit to 0 : 1.125ms between rising edges, so before next bit
*/
void X10_sendBit_zero()
{
 digitalWrite(pin_emit, HIGH);
 delayMicroseconds(555); // Arbitrary value: I took around 1.125ms divided by two for the "VCC" state.
 digitalWrite(pin_emit, LOW);
 delayMicroseconds(570); // Total 555+570 : 1125μs = 1.125ms
}
/**
* Bit à 1 : 2.25ms entre les "rising edges"
*/
void X10_sendBit_one()
{
 digitalWrite(pin_emit, HIGH);
 delayMicroseconds(555); // Arbitrary value: I took around 1.125ms divided by two for the "VCC" state.
 digitalWrite(pin_emit, LOW);
 delayMicroseconds(1695); // Total 555+1695 : 2250μs = 2.250ms
}
void X10_send8bits(unsigned int data)
{
 // - Send the 8 bits, and then the complementary of the 8 bits.
 // from documentation: "Within each byte, bit7 is received first and bit0 last"
 int mask = 0x80;
 for(int i = 0; i < 8; i++)
 {
 int bit = mask & data;
 if (bit == 0)
 X10_sendBit_zero(); 
 else
 X10_sendBit_one();
 mask = mask >> 1;
 }
}
/**
* Sending a byte consists of sending this byte, and then sending the opposite of the same byte.
* As we send the opposite as well as the data, the total duration is always the same : 8 * (1.125ms+2.250ms) = 8 * 3.375 = total of 27ms
*/
void X10_sendByte(unsigned int data)
{
 X10_send8bits(data);
 X10_send8bits(~data);
}
/**
* Send a complete X10 packet
*
* Total duration :
* (9ms + 4.5ms) + (27ms + 27ms) + 0.555ms + 40ms = 108.055 ms
* from doc: "It appears, from articles on the 'net, that other people have seen a range from 95 msec to 116 msec for various transmitters and that standard X-10 transceivers can tolerate timing variations of 30-35% from nominal."
*/
void X10_sendState_once(unsigned int data)
{
 // - Header
 digitalWrite(pin_emit, HIGH); // "Burst" de 9ms
 delayMicroseconds(9000);
 digitalWrite(pin_emit, LOW); // Silence de 4.5ms
 delayMicroseconds(4500);
 // - Data
 X10_sendByte(0x50); // - Address
 X10_sendByte(data); // - Data
 // - Send a last rising edge to validate last bit
 digitalWrite(pin_emit, HIGH);
 delayMicroseconds(555); // Arbitraty value (but always the same), for "VCC" state.
 // - Footer
 digitalWrite(pin_emit, LOW); // Silence de 40ms pour signifier la fin de l'émission
 delayMicroseconds(40000);
}
/**
* Send a complete packet multiple times (this X10 protocol has not ACK))
* From doc: "Most X-10 RF transmitters send a minimum of five copies of the code separated by 40 msec silences although some can send single bursts." 
*
* 5 times 108.055ms = 540.275 ms, half a second
*/
void X10_sendState(unsigned int data)
{
 // - "clean" to be sure to have a zero for the first rising edge on init
 digitalWrite(pin_emit, LOW);
 delay(1);
 // - Send 5 time complete packet
 for(int repeat=0 ; repeat<5 ; repeat++)
 X10_sendState_once(data);
}
void loop() {
 if(X10_data == X10_A1_ON)
 digitalWrite(pin_led, HIGH);
 else
 digitalWrite(pin_led, LOW);
 X10_sendState(X10_data);
 delay(60000); // 1 minute
 // - I change state each 60 seconds to see changes in Domoticz
 if(X10_data == X10_A1_ON)
 X10_data = X10_A1_OFF;
 else
 X10_data = X10_A1_ON;
}

By changing House code and data, it is now possible to create our own RF sensors.

answered Aug 10, 2016 at 7:46
1
  • Just to say, since my previous answer, I concluded it was too much effort for each new sensor to find how to implement a new protocol. So I finally tried and adopted "MySensors", because I only need to feed it with payload. Commented May 29, 2017 at 11:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.