Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

:: 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:

Library with Processing (Processing.org) example Attach:HomeEasyCtrl.zip

HomeEasy/Nexa Library with absolute dim support at GitHub

Other library easy to use at HomeEasy by Noopy (zip file: HomeEasyByNoopy.zip)

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.  * https://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 noticeably 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 don't 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 receiver 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 Arduino being learned into the socket.
  17.  *
  18.  * Martyn Henderson 02/10/2009  https://martgadget.blogspot.com
  19.  *
  20.  * Cheers to Barnaby and Peter, because without the code above
  21.  * that shows the receiver output this wouldn't 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 don't 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 originally, but tweaked.
  110.     digitalWrite(txPin, LOW);
  111.     delayMicroseconds(1340);  //1225 originally, but tweaked.
  112.   }
  113.   else {
  114.     digitalWrite(txPin, HIGH);
  115.     delayMicroseconds(310);   //275 originally, but tweaked.
  116.     digitalWrite(txPin, LOW);
  117.     delayMicroseconds(310);   //275 originally, 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 receveir 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  https://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 don't 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 Arduino being learned into the socket.
  54.  *
  55.  * Edited code works with a HE305 transmitter, connecting to a HEXXX light fitting. The recipient 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 wouldn't 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.