Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
nikhil
Published © MIT

Smart 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.

AdvancedProtip2,378
Smart Dog Watcher

Things used in this project

Story

Read more

Code

SMART DOG TRACKER

Arduino
ARDUINO PROGRAMMING LANGUAGE
/*
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