nikhil
Created October 31, 2016

IoT-based Dog Watcher

This project will be a tutorial for how to build a variety of long range wireless sensors and how to integrate these sensors

132
IoT-based Dog Watcher

Things used in this project

Story

Read more

Schematics

IOT DOG WATCHER

Code

IOT DOG WATCHER

C/C++
/*
RFM69 Pinout:
MOSI = 11
MISO = 12 <<<<
SCK = 13
SS = 8
*/

/*
Ethernet Pinout:
MOSI = 11
MISO = 12
SCK = 13
SS = 10
DI00 to Pin 2 (interrupt)
*/

//general --------------------------------
#define SERIAL_BAUD   115200
#if 0
#define DEBUG1(expression)  Serial.print(expression)
#define DEBUG2(expression, arg)  Serial.print(expression, arg)
#define DEBUGLN1(expression)  Serial.println(expression)
#else
#define DEBUG1(expression)
#define DEBUG2(expression, arg)
#define DEBUGLN1(expression)
#endif
//RFM69  ----------------------------------
#include <RFM69.h>
#include <SPI.h>
#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
//#define FREQUENCY   RF69_433MHZ
//#define FREQUENCY   RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "MysampleEncryptKey" //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 RFM69_SS  8
RFM69 radio(RFM69_SS);
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

#include <Ethernet.h>
bool conn_ok;
bool mydebug = true;

//Ethernet
byte mac[]    = {
  0x90, 0xA2, 0xDA, 0x0D, 0x11, 0x11
};
byte server[] = {192, 168, 0, 134 }; //Linux server address

IPAddress ip(192, 168, 0, 4); //address of gateway device
EthernetClient ethClient;
#define DHCP_RETRY 500

// Mosquitto---------------
#include <PubSubClient.h>
PubSubClient client(server, 1883, callback, ethClient);
#define MQTT_CLIENT_ID "arduinoClient"
#define MQTT_RETRY 500
int sendMQTT = 0;
unsigned long MQTT_reconnect = 0;


void MQTTSendInt(PubSubClient* _client, int node, int sensor, int var, int val);
void MQTTSendULong(PubSubClient* _client, int node, int sensor, int var, unsigned long val);
void MQTTSendFloat(PubSubClient* _client, int node, int sensor, int var, float val);

//use LED for indicating MQTT connection status.
int led = 13;

typedef struct {
  int                   nodeID;
  int   sensorID;
  unsigned long         var1_usl;
  float                 var2_float;
  float   var3_float;
}
Payload;
Payload theData;

volatile struct
{
  int                   nodeID;
  int   sensorID;
  unsigned long         var1_usl;
  float                 var2_float;
  float   var3_float;  //
  int                   var4_int;
}
SensorNode;

void setup()
{
  Serial.begin(SERIAL_BAUD);
  Serial.println("Rebooting Ethernet_RFM_Gateways_Combinedv1.1");

  //Ethernet -------------------------
  //Ethernet.begin(mac, ip);

  //  //wait for IP address
  while (Ethernet.begin(mac) != 1) {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(DHCP_RETRY);
  }

  Serial.println("ethernet OK");
  // print your local IP address:
  Serial.println("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Connecting to MQTT via ethernet: ");
  // Mosquitto ------------------------------
  while (client.connect(MQTT_CLIENT_ID) != 1) {
    DEBUGLN1("Error connecting to MQTT");
    delay(MQTT_RETRY);
  }
  Serial.println("Connected... ");

  //RFM69 ---------------------------
  Serial.println("Initializing radio");
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
  Serial.println("setHighPower ok ");
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  Serial.println("Radio initialized");
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY == RF69_433MHZ ? 433 : FREQUENCY == RF69_868MHZ ? 868 : 915);
  Serial.println(buff);

  Serial.println("setup complete");
}  // end of setup

byte ackCount = 0;
long watchdogInterval = 2000;
long watchdog = 0;

void loop() {

  // calling client.loop too often block the system at some point quite early (~up to 5 loop)
  // Here is a temporized call to it on a regular interval
  // This need to be as fast as the fastest sensor received
  //  if (millis() > watchdog) {
  //        Serial.print("loop ");
  //        Serial.println(millis());
  //    watchdog += watchdogInterval;
  //    //client.loop needs to run every iteration.  Previous version did not.  Big opps.
  //    client.loop();
  //  }
  //Serial.println("Other loop");
  if (radio.receiveDone()) {
    if (mydebug)  Serial.print('[');
    if (mydebug)  Serial.print(radio.SENDERID, DEC);
    if (mydebug)  Serial.print("] ");
    if (promiscuousMode) {
      if (mydebug)     Serial.print("to [");
      if (mydebug)    Serial.print(radio.TARGETID, DEC);
      if (mydebug)    Serial.print("] ");
    }
    if (mydebug)  Serial.println();

    if (mydebug) Serial.println("before checking payload");

    if (radio.DATALEN != sizeof(Payload))
      Serial.println(F("Invalid payload received, not matching Payload struct!"));
    else {
      theData = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
      if (mydebug)  Serial.println("payload is valid");

      //save it for i2c:
      SensorNode.nodeID = theData.nodeID;
      SensorNode.sensorID = theData.sensorID;
      SensorNode.var1_usl = theData.var1_usl;
      SensorNode.var2_float = theData.var2_float;
      SensorNode.var3_float = theData.var3_float;
      SensorNode.var4_int = radio.RSSI;
      sendMQTT = 1;
    }

    if (radio.ACK_REQUESTED)
    {
      if (mydebug)  Serial.println("ACK Requested");
      byte theNodeID = radio.SENDERID;
      radio.sendACK();

      // When a node requests an ACK, respond to the ACK
      // and also send a packet requesting an ACK (every 3rd one only)
      // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY
      if (ackCount++ % 3 == 0)
      {
        //Serial.print(" Pinging node ");
        //Serial.print(theNodeID);
        //Serial.print(" - ACK...");
        //delay(3); //need this when sending right after reception .. ?
        //if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
        //  Serial.print("ok!");
        //else Serial.print("nothing");
      }
    }//end if radio.ACK_REQESTED
  } //end if radio.receive


  if (sendMQTT == 1)
  {

    if (mydebug) Serial.println("starting MQTT send");
    conn_ok = client.connected();
    if (conn_ok == 1)
    {
      digitalWrite(led, HIGH);
      if (mydebug)  Serial.println("MQTT connected OK from MQTT Send");
    }
    else
    {
      digitalWrite(led, LOW);
      if (mydebug)   Serial.println("MQTT NOT connected OK from MQTT Send");
    }

    //no connection, reconnect
    if (conn_ok == 0)
    {
      client.disconnect();
      delay(5000);
      while (client.connect("arduinoClient") != 1)
      {
        digitalWrite(led, LOW);
        Serial.println("Error connecting to MQTT");
        delay(4000);
        digitalWrite(led, HIGH);
      }
      digitalWrite(led, HIGH);
      Serial.println("reconnected to MQTT");
      MQTT_reconnect = millis();
    }

    int varnum;
    char buff_topic[6];
    char buff_message[12];

    Serial.println("******************************");

    //send var1_usl
    varnum = 1;
    buff_topic[6];
    buff_message[12];
    //sprintf creates buff_topic by combining SensorNode.nodeID, SensorNode.sensorID, varnum
    sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
    dtostrf (SensorNode.var1_usl, 10, 1, buff_message);
    client.publish(buff_topic, buff_message);
    Serial.println("Publishing");

    decodeBuffTopic(buff_topic);
    Serial.print("buff_topic: ");
    Serial.print(buff_topic);
    Serial.print(" varnum 1: ");
    Serial.println(buff_message);

    //%02d means format the integer with 2 digits, left padding with zeros
    //send var2_float
    varnum = 2;
    buff_topic[6];
    buff_message[7];
    sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
    dtostrf (SensorNode.var2_float, 2, 1, buff_message);
    client.publish(buff_topic, buff_message);

    decodeBuffTopic(buff_topic);
    Serial.print("buff_topic: ");
    Serial.print(buff_topic);
    Serial.print(" varnum 2: ");
    Serial.println(buff_message);
    delay(200);

    //send var3_float
    varnum = 3;
    sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
    dtostrf (SensorNode.var3_float, 2, 2, buff_message);
    client.publish(buff_topic, buff_message);
    decodeBuffTopic(buff_topic);
    Serial.print("buff_topic: ");
    Serial.print(buff_topic);
    Serial.print(" varnum 3: ");
    Serial.println(buff_message);
    delay(200);

    //send var4_int, RSSI
    varnum = 4;
    sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
    sprintf(buff_message, "%04d%", SensorNode.var4_int);
    client.publish(buff_topic, buff_message);
    decodeBuffTopic(buff_topic);
    Serial.print("buff_topic: ");
    Serial.print(buff_topic);
    Serial.print(" varnum 4: ");
    Serial.println(buff_message);
    Serial.println("******************************");
    sendMQTT = 0;
   // Serial.println("finished MQTT send");
  }//end if sendMQTT

}//end loop

void MQTTSendInt(PubSubClient* _client, int node, int sensor, int var, int val) {
  char buff_topic[6];
  char buff_message[7];

  sprintf(buff_topic, "%02d%01d%01d", node, sensor, var);
  sprintf(buff_message, "%04d%", val);
  _client->publish(buff_topic, buff_message);
}

void MQTTSendULong(PubSubClient* _client, int node, int sensor, int var, unsigned long val) {
  char buff_topic[6];
  char buff_message[12];

  sprintf(buff_topic, "%02d%01d%01d", node, sensor, var);
  sprintf(buff_message, "%u", val);
  _client->publish(buff_topic, buff_message);
}

void MQTTSendFloat(PubSubClient* _client, int node, int sensor, int var, float val) {
  char buff_topic[6];
  char buff_message[12];

  sprintf(buff_topic, "%02d%01d%01d", node, sensor, var);
  dtostrf (val, 2, 1, buff_message);
  _client->publish(buff_topic, buff_message);
}

// Handing of Mosquitto messages
void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
  Serial.println(F("Mosquitto Callback"));
}

void decodeBuffTopic (char mybufftopic[6])
{
  //print the OpenHAB Items value
  int myInt;
  myInt = atoi(mybufftopic);

  if (myInt == 4032)
  {
    Serial.print("Garage Distance: ");
  }
  else if (myInt == 4122)
  {
    Serial.print("Mailbox count: ");
  }
  else if (myInt == 4124)
  {
    Serial.print("Mailbox RSSI: ");
  }
  else if (myInt == 4123)
  {
    Serial.print("Mailbox battery: ");
  }
  else if (myInt == 4022)
  {
    Serial.print("Garage light: ");
  }
  else if (myInt == 4042)
  {
    Serial.print("Garage temp: ");
  }
  else if (myInt == 4043)
  {
    Serial.print("Garage humidity: ");
  }
  else if (myInt == 3042)
  {
    Serial.print("Dryer: ");
  }
  else if (myInt == 3052)
  {
    Serial.print("Washer: ");
  }
  else if (myInt == 3032)
  {
    Serial.print("Water leak: ");
  }
  else if (myInt == 3062)
  {
    Serial.print("Laundry light: ");
  }
  else
    Serial.print("unknown: ");
}

Credits

nikhil

nikhil

10 projects • 17 followers
I am a engineering student

Comments