Author Topic: Home automation project with a lot of gateway/receiver nodes  (Read 5406 times)

gurari

  • NewMember
  • *
  • Posts: 48
  • Country: bg
Home automation project with a lot of gateway/receiver nodes
« on: January 11, 2015, 01:48:02 PM »
Hello guys!
Some time ago I've started building a wireless temperature monitoring system for my home with the idea to lately expand this system.
For building my system I'm using Arduino nano clones with RFM69 transceivers and DHT22 sensors.
So with the temperature monitoring and logging all is working OK. All the temperature nodes are sending with sendWithRetry (every 30 seconds) the temp and humidity data to the gateway unit (Arduino UNO clone with RFM69 too). The gateway is sending the received data through serial connection to a Raspberry Pi.  Then using Node-Red I'm uploading the data to emoncms and also to the openHAB (through MQTT). Everything is working perfectly and soon I'll be recording temperatures all over my place.
So now I want to go further with my project. Now I want to add the ability of my nodes to control things - lets say to control my air conditioners and this the tricky part for me. I'm not sure if this is possible with the architecture I've build so I'll be happy if someone could tell me that? Because now if I sendWithRetry some data from the Gateway to one of the temp nodes to turn a LED ON or OFF the LED is not always doing what I want. Sometimes node accepts the command but is not returning ACK, other times is not doing anything or the command is done with a delay. If I remove the lines from temp node for sending temp data the LED control is working very well and very fast.
So my question is: Am I doing it in the wright way? Are the Temp nodes and one Gateway enough for my project or I have to add some other units in the game?

Sorry if the stuff I wrote is not very clear but I'm not native English speaker

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #1 on: January 12, 2015, 09:22:52 AM »
For any node to receive data reliably it has to be listening and not doing something else. It sounds like your node is doing other things and the RX slice is only active part of the time, so it may miss some packets. If your sensors keep the MCU busy for long periods of time (even tens of ms is long). If you keep the radio in RX mode and go do something else, as long as interrupts are not disabled during that time, your packets should still be received.

gurari

  • NewMember
  • *
  • Posts: 48
  • Country: bg
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #2 on: January 12, 2015, 03:20:52 PM »
Thank you Felix for the fast reply and for the all information you have shared with us about your projects.
If I understood you right if I write my code correctly I'll be able to make my sender node to receive data with high readability rate.
So can you take a look at my code if you have some time and tell me where I can modify the code in order to achieve my goals?
Code: [Select]
/*

//RFM69  --------------------------------------------------------------------------------------------------
#include <RFM69.h>
#include <SPI.h>
#define NODEID        22    //unique for each node on same network
#define NETWORKID     110  //the same on all nodes that talk to each other
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_868MHZ
//#define FREQUENCY   RF69_915MHZ
#define ENCRYPTKEY    "encryptkurec1111" //exactly the same 16 characters/bytes on all nodes!
//#define IS_RFM69HW  //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ACK_TIME      30 // max # of ms to wait for an ack
#define LED           6  // On which PIN the LED isconnected
#define SERIAL_BAUD   115200  //must be 9600 for GPS, use whatever if no GPS

//deviceID's
// 2 = Temperature/Humidity

typedef struct {
  int           nodeID; //node ID (1xx, 2xx, 3xx);  1xx = BEDRoom, 2xx = LivingRoom, 3xx = Kitchen ...
  int deviceID; //sensor ID (2, 3, 4, 5)
  float var1_usl;         //uptime in ms - not in all cases
  float         var2_float;            //sensor data?
  float var3_float; //battery condition?
} Payload;
Payload theData;

bool promiscuousMode = false;

typedef struct {
  int                   nodeID;
  int command;
  //unsigned long       var1_usl;
  //float               var2_float;
  //float var3_float;
  //int                 var4_int;
} klima_Send;
klima_Send theDataIR;

char buff[20];
byte sendSize=0;
//boolean requestACK = false;
RFM69 radio;

//end RFM69 ------------------------------------------

//device DHT22 Temperature/Humidity
#include <DHT.h>
#define DHTPIN 4        // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

//time:
const unsigned long dev2_period = 30000; //send data every X seconds
unsigned long dev2_period_time;                 //seconds since last period

void setup()
{
  Serial.begin(SERIAL_BAUD);  //Begin serial communcation
 
  //RFM69-------------------------------------------
 
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
    radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  theData.nodeID = 22;  //this node id should be the same for all devices in this node
 
  pinMode(LED, OUTPUT);
 
  //device DHT
  dht.begin();
 
  //time:

// dev2 is temperature_F/humidity
dev2_period_time = millis(); //seconds since last period
 
}

void loop()
{

  if (radio.receiveDone())
  {
      theDataIR = *(klima_Send*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
     
      Serial.print(theDataIR.nodeID);
      Serial.print(":");
      Serial.print(theDataIR.command);
      Serial.print(":");
      Serial.println(radio.RSSI);
     
      int state;
      if(theDataIR.command == 1)
        state = HIGH;
      else if(theDataIR.command == 0)
        state = LOW;
     
      digitalWrite(LED, state);
    //}
    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
      Serial.println();
    }
  } //end if radio.receive 
  radio.receiveDone(); 
 
  delay(2000);

  //DHT22 --------------------------------
 
  //always report after X seconds
  unsigned long timepassed = millis() - dev2_period_time;
 
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  //send every x seconds
 
  if ((timepassed > dev2_period) || (timepassed < 0))
  {
  if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
  } else {
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" *C\t");
  }
  //send data
  theData.deviceID = 2;
  theData.var1_usl = timepassed;
  theData.var2_float = t;
  theData.var3_float = h;
  radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData));

          dev2_period_time = millis();
         
          //digitalWrite(LED, HIGH); delay(200); digitalWrite(LED, LOW);
  }
 
}//end loop

If it is not possible I can always add separate nodes for controlling things (receiving commands) but it sounds to me like wasting the "talent" of the arduino using only  some of it's power ;)

p.s. Sorry for not so tidy code but I'm still developing the skills to write good structured code  ::)

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #3 on: January 12, 2015, 05:20:16 PM »
Thank you Felix for the fast reply and for the all information you have shared with us about your projects.
If I understood you right if I write my code correctly I'll be able to make my sender node to receive data with high readability rate.
So can you take a look at my code if you have some time and tell me where I can modify the code in order to achieve my goals?
Code: [Select]
/*

//RFM69  --------------------------------------------------------------------------------------------------
#include <RFM69.h>
#include <SPI.h>
#define NODEID        22    //unique for each node on same network
#define NETWORKID     110  //the same on all nodes that talk to each other
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_868MHZ
//#define FREQUENCY   RF69_915MHZ
#define ENCRYPTKEY    "encryptkurec1111" //exactly the same 16 characters/bytes on all nodes!
//#define IS_RFM69HW  //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ACK_TIME      30 // max # of ms to wait for an ack
#define LED           6  // On which PIN the LED isconnected
#define SERIAL_BAUD   115200  //must be 9600 for GPS, use whatever if no GPS

//deviceID's
// 2 = Temperature/Humidity

typedef struct {
  int           nodeID; //node ID (1xx, 2xx, 3xx);  1xx = BEDRoom, 2xx = LivingRoom, 3xx = Kitchen ...
  int deviceID; //sensor ID (2, 3, 4, 5)
  float var1_usl;         //uptime in ms - not in all cases
  float         var2_float;            //sensor data?
  float var3_float; //battery condition?
} Payload;
Payload theData;

bool promiscuousMode = false;

typedef struct {
  int                   nodeID;
  int command;
  //unsigned long       var1_usl;
  //float               var2_float;
  //float var3_float;
  //int                 var4_int;
} klima_Send;
klima_Send theDataIR;

char buff[20];
byte sendSize=0;
//boolean requestACK = false;
RFM69 radio;

//end RFM69 ------------------------------------------

//device DHT22 Temperature/Humidity
#include <DHT.h>
#define DHTPIN 4        // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

//time:
const unsigned long dev2_period = 30000; //send data every X seconds
unsigned long dev2_period_time;                 //seconds since last period

void setup()
{
  Serial.begin(SERIAL_BAUD);  //Begin serial communcation
 
  //RFM69-------------------------------------------
 
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
    radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  theData.nodeID = 22;  //this node id should be the same for all devices in this node
 
  pinMode(LED, OUTPUT);
 
  //device DHT
  dht.begin();
 
  //time:

// dev2 is temperature_F/humidity
dev2_period_time = millis(); //seconds since last period
 
}

void loop()
{

  if (radio.receiveDone())
  {
      theDataIR = *(klima_Send*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
     
      Serial.print(theDataIR.nodeID);
      Serial.print(":");
      Serial.print(theDataIR.command);
      Serial.print(":");
      Serial.println(radio.RSSI);
     
      int state;
      if(theDataIR.command == 1)
        state = HIGH;
      else if(theDataIR.command == 0)
        state = LOW;
     
      digitalWrite(LED, state);
    //}
    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
      Serial.println();
    }
  } //end if radio.receive 
  radio.receiveDone(); 
 
  delay(2000);

  //DHT22 --------------------------------
 
  //always report after X seconds
  unsigned long timepassed = millis() - dev2_period_time;
 
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  //send every x seconds
 
  if ((timepassed > dev2_period) || (timepassed < 0))
  {
  if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
  } else {
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" *C\t");
  }
  //send data
  theData.deviceID = 2;
  theData.var1_usl = timepassed;
  theData.var2_float = t;
  theData.var3_float = h;
  radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData));

          dev2_period_time = millis();
         
          //digitalWrite(LED, HIGH); delay(200); digitalWrite(LED, LOW);
  }
 
}//end loop

If it is not possible I can always add separate nodes for controlling things (receiving commands) but it sounds to me like wasting the "talent" of the arduino using only  some of it's power ;)

p.s. Sorry for not so tidy code but I'm still developing the skills to write good structured code  ::)
Without doing a thorough analysis of your code, I see that you are calling receiveDone() twice and, in the second call, you are not checking to see if you have any data.  If you DID have any data sent to you at this time, it will be lost before you ever check again...

Tom

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #4 on: January 12, 2015, 06:22:12 PM »
Dear gurari,
Rather than me analysing everyone's code - which is time consuming and I would love to do in a perfect universe, but I am very busy and time is so very limited - I posted a bunch of examples that demonstrate the usage of the Moteinos/transceivers in different listening/sleeping modes. For instance a sleepy mote that only sends data is the MotionMote. A highly reliable example of Moteino that sends some data, but mostly listens for data, is the GarageMote or the SwitchMote. You can look at these examples and use them as basis for your own sketches. I hope that does not sound very defensive, I hope not. I am very grateful for the handful of other users in the forum that are actual contributors who share their experience and advice, TomWS being one of the most distinguished.

gurari

  • NewMember
  • *
  • Posts: 48
  • Country: bg
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #5 on: January 13, 2015, 12:48:45 AM »
Thank you guys for the support! All you are doing is appreciated highly and I'm very grateful that you are trying to help all the people writing in that forum.
I'll keep digging in the examples you've written and try to achieve the goals I've set.

Have a great day and I'm hoping to write soon with some good results :)

gurari

  • NewMember
  • *
  • Posts: 48
  • Country: bg
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #6 on: January 14, 2015, 12:13:46 AM »
Ciao!
Good news for me ;) Yesterday I was able to rewrite my code and now the nodes are sending and receiving data like they should. Thank you guys again for the the help and the useful information you've provided to me!
Now I'm starting to write the code for generation the ir commands for my air conditioners. As soon as I have success and some photos to share I'll write again. Also if some questions appear I'll bother you again.

Have a great day

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #7 on: January 17, 2015, 08:43:35 AM »
Ciao!
Good news for me ;) Yesterday I was able to rewrite my code and now the nodes are sending and receiving data like they should. Thank you guys again for the the help and the useful information you've provided to me!
Now I'm starting to write the code for generation the ir commands for my air conditioners. As soon as I have success and some photos to share I'll write again. Also if some questions appear I'll bother you again.

Have a great day
I just noticed that you said you are using IR to control Air Conditioners.  Which brand air conditioner is it?  I've been thinking about setting up programmable controllers for all the zones in my workshop but haven't spent the time to 'hack' the IR codes.  If you have something that works, maybe it would be useful to others (like me, for instance  ;)

Tom

Kylix

  • Jr. Member
  • **
  • Posts: 67
  • Country: ro
    • Omologazioni veicoli
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #8 on: January 17, 2015, 04:50:19 PM »
You can find here everything you need (I'm not the owner of that blog and also, I didn't write the code):

https://github.com/shirriff/Arduino-IRremote
http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html

Felix

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #9 on: January 18, 2015, 09:18:06 AM »
You can find here everything you need (I'm not the owner of that blog and also, I didn't write the code):

https://github.com/shirriff/Arduino-IRremote
http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html

Felix
Grazie!  I'll try it when I get a chance.  It doesn't look like it specifically supports my LG heatpump, but the protocol might already be there in another form and it does appear to be easily configured once I scope the LG remotes to determine WHAT needs to be supported. Regardless, the library should be useful.

Tom

Kylix

  • Jr. Member
  • **
  • Posts: 67
  • Country: ro
    • Omologazioni veicoli
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #10 on: January 18, 2015, 09:55:22 AM »
Hello Tom!

In case your LG is not supported out of the box, there is a RAW protocol you can use (if I'm not wrong, that library also supports Sony and Philips protocols).

A few months ago I've used an Arduino to control a Sony TV, with the help of instructions found on the same blog:

http://www.righto.com/2009/11/controlling-your-stereo-over-web-with.html

Felix
« Last Edit: January 18, 2015, 09:58:12 AM by fpaliuc »

gurari

  • NewMember
  • *
  • Posts: 48
  • Country: bg
Re: Home automation project with a lot of gateway/receiver nodes
« Reply #11 on: January 27, 2015, 12:31:52 AM »
Ciao!
Good news for me ;) Yesterday I was able to rewrite my code and now the nodes are sending and receiving data like they should. Thank you guys again for the the help and the useful information you've provided to me!
Now I'm starting to write the code for generation the ir commands for my air conditioners. As soon as I have success and some photos to share I'll write again. Also if some questions appear I'll bother you again.

Have a great day
I just noticed that you said you are using IR to control Air Conditioners.  Which brand air conditioner is it?  I've been thinking about setting up programmable controllers for all the zones in my workshop but haven't spent the time to 'hack' the IR codes.  If you have something that works, maybe it would be useful to others (like me, for instance  ;)

Tom

Ciao Tom!
Sorry for the late reply but I was on a ski holiday and just get back to home.
I'll be controlling DAIKIN Air Conditioners but still haven't write the complete code.
Some useful information can be found here: http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/
For the moment I'm only sending ON and OFF commands but soon I'll write the code to fully control the AC's. Also in the bright future maybe I'll put one arduino in all the AC's to listen for commands send to the AC in order to have feedback what is the real state of the AC.