Will ThrailkillJoshua Waits
Published © CC BY-NC

AquaNiner Pet Hydration Monitor

Using two Photons, IFTTT and ThingSpeak, get notifications for when your furry friend needs water and monitor how much they're drinking.

IntermediateFull instructions provided5 hours2,126
AquaNiner Pet Hydration Monitor

Things used in this project

Hardware components

Photon
Particle Photon
×2
NON-Contact Digital Water / Liquid Level Sensor
×1
Ultrasonic Module HC-SR04 Distance Measuring Transducer Sensor
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

ThingSpeak API
ThingSpeak API
IFTTT Email
Particle Build Web IDE
Particle Build Web IDE

Hand tools and fabrication machines

Wood Borer Bits
Power Drill
Epoxy Glue
Caulk
Tape

Story

Read more

Schematics

Photon 2 Wiring Schematic

This is the wiring schematic for the second photon which connects to the HC-SR04 Ultrasonic Distance Sensor

Photon 1 Wiring Schematic

Wiring diagram for photon connected to non-contact water level sensor.

Code

Photon 1 Code (Non-Contact Liquid Sensor)

C/C++
This code monitors the non-contact liquid sensor and triggers IFTTT to alert the user if the water level is low or if there is some sort of sensor error.
int liquid_level = 0;
const int sleep = 60;

//Define variable to be used in the code. One variable is measured, so one variable interger input required 
/*This sketch shows the wiring of the photon for the non contact liquid level sensor.
 
                                       +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *       Sensor Power Input-| [*] VIN           3V3 [ ] |
 *                          | [ ] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [*] |-Sensor Ground
 *                          | [ ] WKP            D7 [ ] |       
 *                          | [ ] DAC +-------+  D6 [ ] |       
 *                          | [ ] A5  |   *   |  D5 [*] |-Sensor Digital Output       
 *                          | [ ] A4  |Photon |  D4 [ ] |     
 *                          | [ ] A3  |       |  D3 [ ] |       
 *                          | [ ] A2  +-------+  D2 [ ] |       
 *                          | [ ] A1             D1 [ ] |       
 *                          | [ ] A0             D0 [ ] |
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */

//  begin particle webhook code snippit to add to particle webhook interface on console

int liquid_level = 0;
const int sleep = 60;

//Define variable to be used in the code. One variable is measured, so one variable interger input required 

void setup() {
    /*setup inputs and outputs for the device. Sensor input is the only input.
    In this code, an output to blink the built in LED was added to ensure the 
    sensor was reading out and could communicate with the other photon.
    */
pinMode(liquid_level, INPUT);
pinMode(D7, OUTPUT);

//Added subscribe function to be used at a later date

}

void loop() {
    
    /*Loop used to communicate with the particle Photon and the sensor. If water is detected, the LED light lights up
    If no liguid detected nothing happens. Will be modified further to communicate this with another photon.
    
    */
liquid_level = digitalRead(D5);
if (liquid_level == 1){
    Particle.publish("ish2ook","allclear",60);
}
if (liquid_level == 0){

Particle.publish("ish2ook","waterLOW",60);

}

delay(15000);/*Time between measurements change here. At this moment
a measurement is taken ever fifteen seconds. Can change to monitor every
minute, every hour or every half hour.
*/
Particle.subscribe("watercheck", decide);


}


//Liquid check function will go here, will communicate with Will's device to verify no liquid is at this level


void decide(const char *event, const char *data){
  if (strcmp(data,"GIVE_FLUFFY_SOME H2O")==0) { //Needs to compare recieved interger for decision to be made


Serial.println("trouble");
Particle.publish("iftttTrigger","lowlevel",60);//Publishes to IFTTT to email water needs to be refilled
digitalWrite(D7,HIGH);
delay(2000);
digitalWrite(D7, LOW);
}
else if (strcmp(data,"SENSORERROR")==0) {

Serial.println("okay");
Particle.publish("iftttTrigger","sensor_error",60);//Nothing Happens
digitalWrite(D7,HIGH);
delay(2000);
digitalWrite(D7, LOW);
}
else if (strcmp(data,"SENSORERROR2")==0) {

Serial.println("okay");
Particle.publish("iftttTrigger","sensor_error",60);//Nothing Happens
digitalWrite(D7,HIGH);
delay(2000);
digitalWrite(D7, LOW);
}
else {
Serial.println("randomeventreceived");

}  

}

Photon 2 Code (for ultrasonic distance sensor)

C/C++
This tracks the water level using the ultrasonic sensor. It also compares the non-contact sensor reading with the level readings and tells Photon 1 if both agree or if there are sensor errors. Additionally it publishes a string to a Thingspeak webhook which tracks the water level over time.
/*This sketch shows the wiring of the photon for the non contact liquid level sensor.
 
                                       +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+         |
 *          VCC (on sensor)-| [*] VIN           3V3 [ ] |
 *          GND (on sensor)-| [*] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [ ] |
 *                          | [ ] WKP            D7 [ ] |       
 *                          | [ ] DAC +-------+  D6 [ ] |       
 *                          | [ ] A5  |   *   |  D5 [ ] |       
 *                          | [ ] A4  |Photon |  D4 [ ] |     
 *                          | [ ] A3  |       |  D3 [ ] |       
 *                          | [ ] A2  +-------+  D2 [ ] |       
 *                          | [ ] A1             D1 [*] |-Trig (on sensor)                
 *                          | [ ] A0             D0 [*] |-Echo (on sensor)         
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */

// intitializes the pins used in the program

const int triggerPin = D1;
const int echoPin = D0;
int light = D7;
int willswaterlevel;

// initialized the data that's coming in, long indicates a
// larger decimal number, int indicates an integer value
unsigned long duration;
int mydistance;


void setup() {

//establishes input and output for the digital pins

  pinMode(triggerPin, OUTPUT);

  pinMode(echoPin, INPUT);
  
  pinMode(light,OUTPUT);
  
// subscribes this particle to the other particle's code and sends the strings coming from that event
// to the program "H20_checker"

Particle.subscribe("ish2ook", H2O_checker);
  

}

void loop() {

//first to make sure that the trigger pin is off, we'll make it 
//low for 2 microseconds:

digitalWrite(triggerPin, LOW);
delayMicroseconds(2);

//next we'll send the signal for 10 microseconds and then turn 
//it off (this is the ultrasonic wave)

digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);

//this gets the time (duration)which the HIGH pulse 
//was recieved and then
//converts it to distance, using
//the formula in this video:
//https://www.youtube.com/watch?v=ZejQOX69K5M&authuser=0
//note: duration is in microseconds

duration = pulseIn(echoPin, HIGH);

// once duration is aquired, it is converted into both a string and an integer using the following formula

willswaterlevel = duration*.035/2;

String mydistance = String(duration*.035/2);



//this just publishes the distance to Thingspeak

Particle.publish("mydistance", mydistance, PRIVATE);

delay(3000);


}

// this function, H20_checker,  takes the strings sent from the other photon's event and compares them to the distance data gathered from this particle

void H2O_checker(const char *event, const char *data)

{
/* Particle.subscribe handlers are void functions, which means they don't return anything.
They take two variables-- the name of your event, and any data that goes along with your event.

Since the input here is a char, we can't do

data=="waterLOW"
or
data=="waterLOW"

chars just don't play that way. Instead we're going to strcmp(), which compares two chars.
If they are the same, strcmp will return 0.
*/

// this is the situation where both sensors indicate water is needed

if (strcmp(data,"waterLOW")==0 && willswaterlevel > 30 ) {

Particle.publish("watercheck", "GIVE_FLUFFY_SOME H2O", 20);
digitalWrite(light, HIGH);
delay(5000);
digitalWrite(light, LOW);
}

// this is the situation where the other photon indicates the water needs to be filled, but this photon does not

else if (strcmp(data,"waterLOW")==0 && willswaterlevel < 30 ) {

Particle.publish("watercheck", "SENSORERROR", 20);
digitalWrite(light, HIGH);
delay(5000);
digitalWrite(light, LOW);

// this is the situation where both photons indicate an acceptable water level

}

else if (strcmp(data,"allclear")==0 && willswaterlevel < 30 ) {

Particle.publish("watercheck", "allclearwill", 20);
digitalWrite(light, HIGH);
delay(1000);
digitalWrite(light, LOW);

}

// this is the situation where the other particle indicates water is needed but this one does not

else {
    
Particle.publish("watercheck", "SENSORERROR2", 20);
// if the data is something else, don't do anything.
// Really the data shouldn't be anything but those two listed above.
digitalWrite(light, HIGH);
delay(5000);
digitalWrite(light, LOW);
}
}

Credits

Will Thrailkill

Will Thrailkill

1 project • 4 followers
Joshua Waits

Joshua Waits

1 project • 3 followers

Comments