:: Home Easy ::

Home Easy is a wireless home automation range operating on 433MHz AM.

The the Home Easy Hacking Wiki contains hardware guides and protocol details.

Libraries

A fully functional Home Easy library to send and receive signals is now available on the Home Easy Hacking Google Code Page or with additional fixes at github

The beginnings of a library to send Home Easy signals is also available. Unzip the following file in the Arduino libraries folder:

Attach:HomeEasyCtrl.zip

HomeEasy/Nexa Library with absolute dim support at github

Blogs

See martgadget's blog for more Arduino HomeEasy stuff in the future hopefully.

Still experimenting with Home Easy and Arduinos and posting on my weblog as I go. jtonline

Hooking up a Microcontroller to HomeEasy home automation devices ...and making an awesome alarm clock.

Initial scripts

I was originally using the Domia Lite Specification as a starting point, but Barnaby very kindly provided the following scripts, which was lucky because the remote I have uses the new protocol! jtonline

The code below doesn't have support for setting devices to a specific dim level, and the comments on how you would do so are slightly incorrect. The code says:

  1. * There's extra support for setting devices to a specific dim-level that you get
  2. * with the HE100 ultimate remote control. I think this involves sending a Wire 11 at
  3. * the on/off flag position and then the message is longer with another 4 bits for dim
  4. * level.
  5. * Need to look into this.
which is nearly right, except you have to send wire 00 at the on/off flag position.

  1. /*
  2.  * AM-HRR3 receiver for homeeasy simple protocol
  3.  * This handles the simple homeeasy protocol compatible with the domia lite
  4.  * units.
  5.  *
  6.  * This is emitted by the HE200 remote control.
  7.  *
  8.  * The protocol consists of house code A-P and unit number 1-16. The messages received
  9.  * by the arduino are emitted out on the serial link, one message per line.
  10.  *
  11.  * See the Technical forum on:
  12.  * http://www.byebyestandby.com/forum/
  13.  * Particularly the pdf for the Protocol Specification.
  14.  *
  15.  * Barnaby Gray 12/2008
  16.  */
  17.  
  18. int ledPin = 13;
  19. int rxPin = 12;
  20.  
  21. void setup()
  22. {
  23.   pinMode(ledPin, OUTPUT);
  24.   pinMode(rxPin, INPUT);
  25.  
  26.   Serial.begin(9600);
  27. }
  28.  
  29. boolean readBit()
  30. {
  31.   unsigned long t;
  32.   do {
  33.     t = pulseIn(rxPin, HIGH);
  34.   } while (t < 300 || t > 1500);
  35.  
  36.   return t > 750;
  37. }
  38.  
  39. void latch()
  40. {
  41.   boolean b = readBit();
  42.   while (!b) {
  43.     b = readBit();
  44.   }
  45. }
  46.  
  47. void loop()
  48. {
  49.   int i = 0;
  50.   unsigned long d = 0;
  51.   unsigned int data = 0;
  52.   unsigned long t;
  53.  
  54.   while (i < 25) {
  55.     // wait for first pulse to latch
  56.     t = pulseIn(rxPin, HIGH, 1500);
  57.     // pulses are expected to be either 375us or 1125us, but there's
  58.     // some tolerance here.
  59.     if (t < 250 || t > 1250) {
  60.       // pulse timing off or timeout - reset
  61.       i = 0;
  62.       data = 0;
  63.       continue;
  64.     }
  65.  
  66.     if (i % 2 == 0) {
  67.       if (t > 400) {
  68.         // should be zero pulses
  69.         i = 0; data = 0;
  70.         continue;
  71.       }
  72.     }
  73.     else {
  74.       data = (data>>1) + (t > 400 ? 0x800 : 0);
  75.     }
  76.  
  77.     ++i;
  78.   }
  79.  
  80.   int group = data & 15;
  81.   int unit = (data >> 4) & 15;
  82.   int cmd = (data >> 8) & 15;
  83.  
  84.   Serial.print(" group: ");
  85.   Serial.print(group+65, BYTE);
  86.   Serial.print(" unit: ");
  87.   Serial.print(unit+1);
  88.   Serial.print(" cmd: ");
  89.   Serial.print((cmd == 14 ? "ON" : (cmd == 6 ? "OFF" : "UNK")));
  90.   Serial.println();  
  91.  
  92. }

  1. /*
  2.  * AM-HRR3 receiver test
  3.  *
  4.  * Homeeasy protocol receiver for the new protocol.
  5.  *
  6.  * This protocol isn't documented so well, so here goes (this is largely from memory).
  7.  *
  8.  * The data is encoded on the wire (aerial) as a Manchester code.
  9.  *
  10.  * A latch of 275us high, 2675us low is sent before the data.
  11.  * There is a gap of 10ms between each message.
  12.  *
  13.  * 0 = holding the line high for 275us then low for 275us.
  14.  * 1 = holding the line high for 275us then low for 1225us.
  15.  *
  16.  * The timings seem to vary quite noticably between devices.  HE300 devices have a
  17.  * low for about 1300us for a 1 whereas HE303 devices seem to have a low of about
  18.  * 1100us.  If this script does not detect your signals try relaxing the timing
  19.  * conditions.
  20.  *
  21.  * Each actual bit of data is encoded as two bits on the wire as:
  22.  * Data 0 = Wire 01
  23.  * Data 1 = Wire 10
  24.  *
  25.  * The actual message is 32 bits of data (64 wire bits):
  26.  * bits 0-25: the group code - a 26bit number assigned to controllers.
  27.  * bit 26: group flag
  28.  * bit 27: on/off flag
  29.  * bits 28-31: the device code - a 4bit number.
  30.  *
  31.  * The group flag just seems to be a separate set of addresses you can program devices
  32.  * to and doesn't trigger the dim cycle when sending two ONs.
  33.  *
  34.  * There's extra support for setting devices to a specific dim-level that you get
  35.  * with the HE100 ultimate remote control. I think this involves sending a Wire 11 at
  36.  * the on/off flag position and then the message is longer with another 4 bits for dim
  37.  * level.
  38.  * Need to look into this.
  39.  *
  40.  * Barnaby Gray 12/2008
  41.  * Peter Mead   09/2009
  42.  */
  43.  
  44. int rxPin = 12;
  45.  
  46.  
  47. void setup()
  48. {       pinMode(rxPin, INPUT);
  49.         Serial.begin(9600);
  50. }
  51.  
  52.  
  53. void loop()
  54. {
  55.         int i = 0;
  56.         unsigned long t = 0;
  57.  
  58.         byte prevBit = 0;
  59.         byte bit = 0;
  60.  
  61.         unsigned long sender = 0;
  62.         bool group = false;
  63.         bool on = false;
  64.         unsigned int recipient = 0;
  65.  
  66.         // latch 1
  67.         while((t < 9480 || t > 10350))
  68.         {       t = pulseIn(rxPin, LOW, 1000000);
  69.         }
  70.  
  71.         // latch 2
  72.         while(t < 2550 || t > 2700)
  73.         {       t = pulseIn(rxPin, LOW, 1000000);
  74.         }
  75.  
  76.         // data
  77.         while(i < 64)
  78.         {
  79.                 t = pulseIn(rxPin, LOW, 1000000);
  80.  
  81.                 if(t > 200 && t < 365)
  82.                 {       bit = 0;
  83.                 }
  84.                 else if(t > 1000 && t < 1360)
  85.                 {       bit = 1;
  86.                 }
  87.                 else
  88.                 {       i = 0;
  89.                         break;
  90.                 }
  91.  
  92.                 if(i % 2 == 1)
  93.                 {
  94.                         if((prevBit ^ bit) == 0)
  95.                         {       // must be either 01 or 10, cannot be 00 or 11
  96.                                 i = 0;
  97.                                 break;
  98.                         }
  99.  
  100.                         if(i < 53)
  101.                         {       // first 26 data bits
  102.                                 sender <<= 1;
  103.                                 sender |= prevBit;
  104.                         }      
  105.                         else if(i == 53)
  106.                         {       // 26th data bit
  107.                                 group = prevBit;
  108.                         }
  109.                         else if(i == 55)
  110.                         {       // 27th data bit
  111.                                 on = prevBit;
  112.                         }
  113.                         else
  114.                         {       // last 4 data bits
  115.                                 recipient <<= 1;
  116.                                 recipient |= prevBit;
  117.                         }
  118.                 }
  119.  
  120.                 prevBit = bit;
  121.                 ++i;
  122.         }
  123.  
  124.         // interpret message
  125.         if(i > 0)
  126.         {       printResult(sender, group, on, recipient);
  127.         }
  128. }
  129.  
  130.  
  131. void printResult(unsigned long sender, bool group, bool on, unsigned int recipient)
  132. {
  133.         Serial.print("sender ");
  134.         Serial.println(sender);
  135.  
  136.         if(group)
  137.         {       Serial.println("group command");
  138.         }
  139.         else
  140.         {       Serial.println("no group");
  141.         }
  142.  
  143.         if(on)
  144.         {       Serial.println("on");
  145.         }
  146.         else
  147.         {       Serial.println("off");
  148.         }
  149.  
  150.         Serial.print("recipient ");
  151.         Serial.println(recipient);
  152.  
  153.         Serial.println();
  154. }

  1. /*
  2.  * AM-HRR3 transmitter test.
  3.  * Connect two push switches up to onPin and offPin, pulled high.
  4.  *
  5.  * Emits a homeeasy simple protocol ON message when the onPin is brought low,
  6.  * and vice versa for offPin.
  7.  *
  8.  * Barnaby Gray 12/2008.
  9.  */
  10.  
  11. int txPin = 13;
  12. int onPin = 12;
  13. int offPin = 11;
  14.  
  15. void setup()
  16. {
  17.   pinMode(txPin, OUTPUT);
  18.   pinMode(onPin, INPUT);
  19.   pinMode(offPin, INPUT);
  20.  
  21.   Serial.begin(9600);
  22. }
  23.  
  24. void sendBit(boolean b) {
  25.   if (b) {
  26.     digitalWrite(txPin, HIGH);
  27.     delayMicroseconds(1125);
  28.     digitalWrite(txPin, LOW);
  29.     delayMicroseconds(375);
  30.   }
  31.   else {
  32.     digitalWrite(txPin, HIGH);
  33.     delayMicroseconds(375);
  34.     digitalWrite(txPin, LOW);
  35.     delayMicroseconds(1125);
  36.   }
  37. }
  38.  
  39. void sendPair(boolean b) {
  40.   sendBit(false);
  41.   sendBit(b);
  42. }
  43.  
  44. void switchcode(boolean b)
  45. {
  46.  
  47.   // house code 1 = B
  48.   sendPair(true);
  49.   sendPair(false);
  50.   sendPair(false);
  51.   sendPair(false);
  52.  
  53.   // unit code 2
  54.   sendPair(true);
  55.   sendPair(false);
  56.   sendPair(false);
  57.   sendPair(false);
  58.  
  59.   // on = 14
  60.   sendPair(false);
  61.   sendPair(true);
  62.   sendPair(true);
  63.   sendPair(b);
  64.  
  65.   sendBit(false);  
  66. }
  67.  
  68. void transmit(boolean b) {
  69.   switchcode(b);
  70.   delayMicroseconds(10000);
  71.   switchcode(b);
  72.   delayMicroseconds(10000);
  73.   switchcode(b);
  74. }
  75.  
  76. void loop() {
  77.   int val = digitalRead(onPin);
  78.   if (val == LOW) {
  79.     transmit(true);
  80.   }
  81.   val = digitalRead(offPin);
  82.   if (val == LOW) {
  83.     transmit(false);
  84.   }
  85. }

Extended scripts

  1. /*
  2.  * HE300 Automatic Protocol Transmitter 'Simulator'
  3.  *
  4.  * This demo code emits a homeeasy automatic protocol ON message
  5.  * then 3 seconds later, an off message
  6.  *
  7.  * You dont need to learn the Arduino into the socket, because it can
  8.  * pretend to be a transmitter you already have.
  9.  *
  10.  * Use the Automatic protocol reciever code above to find out
  11.  * your transmitter address 8-)
  12.  *
  13.  * *Only* tested with one HE300 transmitter (HE Address 272946) with its
  14.  * slider switch set to 1 which appears to be 0 in fact.
  15.  * Seems to work with a switch socket (HE302S) and can turn it on and off
  16.  * without the ardunio being learned into the socket.
  17.  *
  18.  * Martyn Henderson 02/10/2009  http://martgadget.blogspot.com
  19.  *
  20.  * Cheers to Barnaby and Peter, because without the code above
  21.  * that shows the receiver output this wouldnt have been possible!
  22.  *
  23.  * If you make something cool using HomeEasy and Arduino, please
  24.  * post back here with a link to your code so we can all enjoy.
  25.  */
  26.  
  27.  
  28. bool bit2[26]={};              // 26 bit global to store the HE device address.
  29. int txPin = 2;                 // 433mhz transmitter on pin2
  30.  
  31. void setup()
  32. {
  33.  
  34.   pinMode(txPin, OUTPUT);      // transmitter pin.
  35.   Serial.begin(9600);         // console port
  36.  
  37.   Serial.println("go");
  38.  
  39.   itob(272946,26);            // convert our device code..
  40.  
  41.   transmit(true);            // send ON
  42.   delay(10);                 // wait (socket ignores us it appears unless we do this)
  43.   transmit(true);            // send ON again
  44.  
  45.   delay(3000);               // wait 3 sec
  46.  
  47.   transmit(false);           // and off again.
  48.   delay(10);
  49.   transmit(false);
  50.  
  51.  
  52.   Serial.println("stop");    // done.
  53.  
  54. }
  55.  
  56. void loop()
  57. {
  58.   // we dont use the arduino loop, this is a one-shot transmit in this example.
  59. }
  60.  
  61.  
  62. void transmit(int blnOn)
  63. {
  64.   int i;
  65.  
  66.   // Do the latch sequence..
  67.   digitalWrite(txPin, HIGH);
  68.   delayMicroseconds(275);     // bit of radio shouting before we start.
  69.   digitalWrite(txPin, LOW);
  70.   delayMicroseconds(9900);     // low for 9900 for latch 1
  71.   digitalWrite(txPin, HIGH);   // high again
  72.   delayMicroseconds(275);      // wait a moment 275
  73.   digitalWrite(txPin, LOW);    // low again for 2675 - latch 2.
  74.   delayMicroseconds(2675);
  75.   // End on a high
  76.   digitalWrite(txPin, HIGH);
  77.  
  78.   // Send HE Device Address..
  79.   // e.g. 1000010101000110010  272946 in binary.
  80.   for(i=0; i<26;i++)
  81.   {
  82.     sendPair(bit2[i]);
  83.   }
  84.  
  85.   // Send 26th bit - group 1/0
  86.   sendPair(false);
  87.  
  88.   // Send 27th bit - on/off 1/0
  89.   sendPair(blnOn);
  90.  
  91.   // last 4 bits - recipient   -- button 1 on the HE300 set to
  92.   // slider position I in this example:
  93.  
  94.   sendPair(false);
  95.   sendPair(false);
  96.   sendPair(false);
  97.   sendPair(false);
  98.  
  99.   digitalWrite(txPin, HIGH);   // high again (shut up)
  100.   delayMicroseconds(275);      // wait a moment
  101.   digitalWrite(txPin, LOW);    // low again for 2675 - latch 2.
  102.  
  103. }
  104.  
  105.  
  106. void sendBit(boolean b) {
  107.   if (b) {
  108.     digitalWrite(txPin, HIGH);
  109.     delayMicroseconds(310);   //275 orinally, but tweaked.
  110.     digitalWrite(txPin, LOW);
  111.     delayMicroseconds(1340);  //1225 orinally, but tweaked.
  112.   }
  113.   else {
  114.     digitalWrite(txPin, HIGH);
  115.     delayMicroseconds(310);   //275 orinally, but tweaked.
  116.     digitalWrite(txPin, LOW);
  117.     delayMicroseconds(310);   //275 orinally, but tweaked.
  118.   }
  119. }
  120.  
  121. void sendPair(boolean b) {
  122.   // Send the Manchester Encoded data 01 or 10, never 11 or 00
  123.   if(b)
  124.   {
  125.     sendBit(true);
  126.     sendBit(false);
  127.   }
  128.   else
  129.   {
  130.   sendBit(false);
  131.   sendBit(true);
  132.   }
  133. }
  134.  
  135.  
  136. void itob(unsigned long integer, int length)
  137. {  //needs bit2[length]
  138.   // Convert long device code into binary (stores in global bit2 array.)
  139.  for (int i=0; i<length; i++){
  140.    if ((integer / power2(length-1-i))==1){
  141.      integer-=power2(length-1-i);
  142.      bit2[i]=1;
  143.    }
  144.    else bit2[i]=0;
  145.  }
  146. }
  147.  
  148. unsigned long power2(int power){    //gives 2 to the (power)
  149.  unsigned long integer=1;          
  150.  for (int i=0; i<power; i++){      
  151.    integer*=2;
  152.  }
  153.  return integer;
  154. }


Below is a class for adding HomeEasy Transmitter code to your project, in a convenient form.

  1. <!--HomeEasyTransmitter.h--!>
  2.  
  3. #ifndef HomeEasyTransmitter_h
  4. #define HomeEasyTransmitter_h
  5.  
  6. class HomeEasyTransmitter
  7. {
  8.  
  9.   public:
  10.     //Constructor.
  11.     //arg1 = pin to connected to 434Mhz transmitter
  12.     HomeEasyTransmitter(short);
  13.     //arg1 = true to turn switch on, false for off
  14.     //arg2 = the 26 bit long transmitter ID as found by the Pete and Banarby's recevier code
  15.     //arg3 = the 4 bit recipient code, seems to be on a dial for mains switches, 1010 (6 in decimal) for my light fittings
  16.     void setSwitch(boolean,unsigned long, short);
  17.   private:
  18.     short txPin;  // 433mhz transmitter on pin2
  19.  
  20.     void transmit(boolean, unsigned long, short);
  21.     void sendBit(boolean);
  22.     void sendPair(boolean);
  23.  
  24. };
  25.  
  26. #endif
  27.  
  28.  
  29. <!--HomeEasyTransmitter.cpp--!>
  30.  
  31. /*
  32.  * HE300 Automatic Protocol Transmitter 'Simulator'
  33.  * David Edmundson 21/11/2009
  34.  *
  35.  * This class allows use of the homeeasy automatic protocol to be used in any Arduino program
  36.  *
  37.  * Based heavily on demo code by
  38.  * Martyn Henderson 02/10/2009  http://martgadget.blogspot.com
  39.  *
  40.  * The code has been moved into a class, for easy re-usage and has been optimised
  41.  * in regards to calculating and storing the transmitter address.
  42.  *
  43.  * You dont need to learn the Arduino into the socket, because it can
  44.  * pretend to be a transmitter you already have.
  45.  *
  46.  * Use the Automatic protocol reciever code above to find out
  47.  * your transmitter address, and reciepient ID.
  48.  *
  49.  * Original code from Martyn
  50.  * *Only* tested with one HE300 transmitter (HE Address 272946) with its
  51.  * slider switch set to 1 which appears to be 0 in fact.
  52.  * Seems to work with a switch socket (HE302S) and can turn it on and off
  53.  * without the ardunio being learned into the socket.
  54.  *
  55.  * Edited code works with a HE305 transmitter, connecting to a HEXXX light fitting. The reciepient code for these
  56.  * appears to be 0b1010. I based my timings based on actual timings received from /my/ transmitter.
  57.  * These seem to match the numbers used by Barnaby and Peter but not from Martyn. Adjust if needed.
  58.  *
  59.  * Cheers to Barnaby and Peter, because without the code above
  60.  * that shows the receiver output this wouldnt have been possible!
  61.  *
  62.  * If you make something cool using HomeEasy and Arduino, please
  63.  * post back here with a link to your code so we can all enjoy.
  64.  *
  65.  */
  66.  
  67. #include "WProgram.h"
  68. #include "HomeEasyTransmitter.h"
  69.  
  70.  
  71. HomeEasyTransmitter::HomeEasyTransmitter(short pin)
  72. {
  73.   txPin = pin;
  74.   pinMode(txPin, OUTPUT);      // transmitter pin.
  75. }
  76.  
  77.  
  78. //sends either an on/off signal to the main switch
  79. //always seems to work best if we send it twice..
  80.  
  81. void HomeEasyTransmitter::setSwitch(boolean on, unsigned long transmitterId, short recipient)
  82. {
  83.   transmit(on, transmitterId, recipient);
  84.   delay(10);
  85.   transmit(on, transmitterId, recipient);
  86.  
  87. }
  88.  
  89.  
  90. //sends either an on/off signal to the main switch
  91. void HomeEasyTransmitter::transmit(boolean blnOn,unsigned long transmitterId, short recipient)
  92. {
  93.   int i;
  94.   // Do the latch sequence..
  95.   digitalWrite(txPin, HIGH);
  96.   delayMicroseconds(270);     // bit of radio shouting before we start.
  97.   digitalWrite(txPin, LOW);
  98.   delayMicroseconds(2585);     // low for 9900 for latch 1
  99.   digitalWrite(txPin, HIGH);   // high again
  100.  
  101.   // End on a high
  102.   digitalWrite(txPin, HIGH);
  103.  
  104.   // Send HE Device Address..
  105.   // This is a 26 bit code.
  106.   // Start at MSB and iterate through to the lowest
  107.   for(i=25; i>=0; i--)
  108.   {
  109.     //The typecasting seems a bit overkill, but 26 bits needs a long and the arduino compiler seems to love trying to
  110.     //convert everything to an standard int.
  111.     //creates bitmask of only relevant bit. Check and send a 1 or 0 as applicable.
  112.     boolean bitToSend = (unsigned long)(transmitterId & ((unsigned long)1 << i)) != 0;
  113.     sendPair(bitToSend);
  114.  
  115.   }
  116.  
  117.   // Send 26th bit - group 1/0
  118.   sendPair(false);
  119.  
  120.   // Send 27th bit - on/off 1/0
  121.   sendPair(blnOn);
  122.  
  123.   // last 4 bits - recipient   -- button 1 on the HE300 set to
  124.   // slider position I in this example:
  125. //  for(i=4; i>=0; i--)
  126. //  {
  127. //  }
  128.     sendPair(true);
  129.     sendPair(false);
  130.     sendPair(true);
  131.     sendPair(false);
  132.  
  133.   digitalWrite(txPin, HIGH);   // high again (shut up)
  134.   delayMicroseconds(275);      // wait a moment
  135.   digitalWrite(txPin, LOW);    // low again for 2675 - latch 2.
  136.  
  137. }
  138.  
  139. void HomeEasyTransmitter::sendBit(boolean b)
  140. {
  141.   if (b)
  142.   {
  143.     digitalWrite(txPin, HIGH);
  144.     delayMicroseconds(275);
  145.     digitalWrite(txPin, LOW);
  146.     delayMicroseconds(1240);
  147.   }
  148.   else
  149.   {
  150.     digitalWrite(txPin, HIGH);
  151.     delayMicroseconds(258);
  152.     digitalWrite(txPin, LOW);
  153.     delayMicroseconds(258);
  154.   }
  155. }
  156.  
  157. void HomeEasyTransmitter::sendPair(boolean b)
  158. {
  159.   // Send the Manchester Encoded data 01 or 10, never 11 or 00
  160.   if(b)
  161.   {
  162.     sendBit(true);
  163.     sendBit(false);
  164.   }
  165.   else
  166.   {
  167.     sendBit(false);
  168.     sendBit(true);
  169.   }
  170. }
  171.  

Share