Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Stefan Vasic
Published © GPL3+

Pet Care IoT

Take care of your pet from anywhere in world in a real-time with Arduino, Android and and ASP. NET Core.

AdvancedFull instructions provided2,428
Pet Care IoT

Things used in this project

Hardware components

NodeMCU ESP8266 Breakout Board
NodeMCU ESP8266 Breakout Board
You can use Arduino with ESP-01 instead of this.
×1
Arduino UNO
Arduino UNO
×1
Relay Module (Generic)
×1
Dual H-Bridge motor drivers L298
SparkFun Dual H-Bridge motor drivers L298
×1
DC motor (generic)
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
5V 2.5A Switching Power Supply
Digilent 5V 2.5A Switching Power Supply
×2
Jumper wires (generic)
Jumper wires (generic)
×1
12V power suply
For L298N
×1
Arduino Nano R3
Arduino Nano R3
(Optional - Instead of Arduino Uno)
×1
ESP8266 ESP-01
Espressif ESP8266 ESP-01
(Optional - Instead of NodeMCU)
×1

Software apps and online services

Arduino IDE
Arduino IDE
Visual Studio 2017
Microsoft Visual Studio 2017
For web server and Android development.
SmarterAsp.net
ASP.NET hosting.

Story

Read more

Schematics

Circuit

Code

Arduino sketch

Arduino
#include <Servo.h>
#include <SoftwareSerial.h>
#include "common.h"
#include <Wire.h>
#include <ArduinoJson.h>

bool pumpState = false;
bool servoState = false;

bool waitingForResponse = false;
int sensor;
int requestType;

Servo servo;

void setup(){  
  Serial.begin(115200);

  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(LIGHT_PIN, OUTPUT);

  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(LIGHT_PIN, LOW);

  servo.attach(SERVO_PIN);
  servo.write(4);

  Wire.begin(I2CAddressESPWifi);
  Wire.onReceive(espWifiReceiveEvent);
  Wire.onRequest(espWifiRequestEvent);

  delay(1000);
  Serial.println("Started");
}

void espWifiReceiveEvent(int count){
  byte value;
  value = Wire.read();    
  process(value);
}
void  process(int messageType){

  if(messageType == (int)LIGHT_ON)
  {
    digitalWrite(LIGHT_PIN, HIGH);
    waitingForResponse = true;
  }
  else if(messageType == (int)LIGHT_OFF)
  {
    digitalWrite(LIGHT_PIN, LOW);
    waitingForResponse = true;
  }     
  else if(messageType == (int)FEEDER_START)
  {
    servoState = true;
  }
  else if(messageType == (int)PUMP_START)
  {
    pumpState = true;
  }
  else if(messageType == (int)GET_VALUES)
  {
    requestType = (int)GET_VALUES;       
  }
}
void espWifiRequestEvent(){
  if(waitingForResponse)
  {
    Wire.write(DONE);
    waitingForResponse = false;
  }
  else if(requestType == (int)GET_VALUES)
  {
    
    Wire.write(sensor);              // send the lower 8 bits
    Wire.write((sensor >> 8));   // send the upper 8 bits
  }
  else
  {
    -1;
  }    
}
void startPump(){
  int sensorLevel = analogRead(A3); 

  analogWrite(enA, 255);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);

  while(sensorLevel >= WATER_LEVEL_HIGH)
  {
    sensorLevel=analogRead(A3);
    delay(200);
  }

  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);

  pumpState = false;
  waitingForResponse = true;
}
void startServo(){

  servo.write(180);
  delay(700);
  servo.write(4);
  servoState = false;
  waitingForResponse = true;
}
void loop()
{ if(pumpState == true)
  {
    startPump();
  }
  if(servoState == true)
  {
    startServo();
  }

  sensor = analogRead(A3);
  delay(10);

  if(sensor>WATER_LEVEL_LOW)
  {
     startPump();
  }
}

NodeMCU sketch

Arduino
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiClient.h>
#include <Wire.h>
#include <ESP8266HTTPClient.h>
#include <WebSocketsClient_Generic.h>
#include <Hash.h>
#include <ArduinoJson.h>
#include "common.h"

ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
IPAddress serverIP(192, 168, 0, 132);

bool alreadyConnected = false;
String token = "token:";

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length){
  switch (type){
  case WStype_DISCONNECTED:
    if (alreadyConnected)
    {
      Serial.println("Disconnected from websocket!");
      alreadyConnected = false;
    }   
    break;
  case WStype_CONNECTED:
    {
      alreadyConnected = true;  
      Serial.print("Connected to websocket. ");
    }
    break;
  case WStype_TEXT:
    processPayload((char *) payload);
    break;
  default:
    break;
  }
}

void setup(){
  Serial.begin(115200);
  Serial.setDebugOutput(false);
  Wire.begin(D1, D2);

  Serial.println("Booting");
  for (uint8_t t = 4; t > 0; t--)
  {
    Serial.print(".");
    delay(1000);
  }

  WiFiMulti.addAP(ssid, pass);
  Serial.println("Connecting to network");
  while (WiFiMulti.run() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(100);
  }

  login();
  
  // Add jwt token after login 
  webSocket.setExtraHeaders(token.c_str());
  webSocket.begin(serverIP, 61955, "/");

  webSocket.onEvent(webSocketEvent);
  webSocket.setReconnectInterval(15000);
  webSocket.enableHeartbeat(60000, 10000, 2);
}
unsigned long messageTimestamp = 0;

void loop(){
  webSocket.loop();
  
  uint64_t now = millis();
  if (now - messageTimestamp > 2000) 
  {
    messageTimestamp = now;
    getWaterLevel();  
  }
}

void processPayload(char * payload){
  StaticJsonDocument<300> doc;
  String jsonObject = String(payload);
  
  auto error = deserializeJson(doc, jsonObject);
  if (error) {
    Serial.println("Error parsing object.");
    return;
  }
  
  int messageType = doc["Type"];

  writeToArduino(messageType);      
  readFromArduino(doc);  
}

void getWaterLevel(){
  writeToArduino((int)GET_VALUES);
  Wire.requestFrom(8, 16); 

  int level;
  if(Wire.available()>0){
    level = (Wire.read() | Wire.read() << 8);    
  }   
  Serial.print("Water level: ");
  Serial.println(level);
  
}

void readFromArduino(StaticJsonDocument<300> doc){
  int c;
  Wire.requestFrom(8, 4); 
  if(Wire.available()>0){
    c = Wire.read();
  }       
  if(c == DONE)
  {
    String myOutput ="";
    doc["Type"] = DONE;
    serializeJson(doc, myOutput);
    sendConfirmationMessage(myOutput);
  }
  
}

void sendConfirmationMessage(String output){
  String sendTo = String("{\"From\":\"Arduino\", \"Data\" :") + output + ", \"To\":\"\"}";
  webSocket.sendTXT(sendTo);
}

void writeToArduino(int code){
  Wire.beginTransmission(I2CAddressESPWifi);
  Wire.write(code);
  Wire.endTransmission();
  if(code == FEEDER_START)
  {
    delay(1000);
  }

  if(code == PUMP_START)
  {
    delay(5000);
  }
}

void login(){
  StaticJsonDocument<600> doc;
  HTTPClient http;
  http.begin(serverLoginGlobal);
  
  http.addHeader("Content-Type", "application/json");
  http.POST("{\"username\" : \"arduino-esp\", \"password\" : \"password\"}");
  delay(5000);  
  
  String payload = http.getString();

  auto error = deserializeJson(doc, payload);
  if (error) {
    return;
  }
  String tokenValue =  doc["token"];
  if(t.length()>1)
  {
     Serial.println("Login successful");
  }
  token += tokenValue;

  http.end();
}

common.h

C Header File
//Mesage codes
#define FEEDER_START      1
#define PUMP_START        2
#define LIGHT_ON          3
#define LIGHT_OFF         4
#define GET_VALUES        5
#define DONE              8

#define WATER_LEVEL_LOW 750  // Over than 750 is near empty, must start pump,
#define WATER_LEVEL_HIGH 350 // Under 320 is near full, must stop pumo.

#define SERVO_PIN 3
#define LIGHT_PIN 12
#define I2CAddressESPWifi 8
#define enA  9
#define in1  8
#define in2  7

const char* ssid     = "WIFI name";
const char* pass = "wifipass";

String serverLoginGlobal = "deployed_server_url/api/authenticate/login";
String websocketGlobal = "deployed_websocket_url";
String serverLoginLocal = "http://localhost/api/authenticate/login";

String websocketLocal = "local_ip";

int portLocal = 61955;
int portGlobal = 80;

PetCareIoT project

Contains Android, Web and Arduino projects

Credits

Stefan Vasic
5 projects • 17 followers
Full Stack Developer. Big mobile development and Arduino enthusiast.
Contact

Comments

Please log in or sign up to comment.