// Pet Feeder Food storage Lid Sensor
#define LidSensor 25
// Pet Food Storage Level Sensor
#define TRIG_PIN 26 // ESP32 pin GPIO23 connected to Ultrasonic Sensor's TRIG pin
#define ECHO_PIN 27 // ESP32 pin GPIO22 connected to Ultrasonic Sensor's ECHO pin
float duration, distance_cm;
float adjustment = 400.0/23528.0;
long previousMillisL = 0;
int intervalL = 2000;
// Pet Food Bowl Weight Sensor
#include "HX711.h"
float calibrate = 5000.0/2100.0;
const int LOADCELL_DOUT_PIN = 13;
const int LOADCELL_SCK_PIN = 12;
HX711 scale;
float weightset = 40.0;
float bowlset = 180.0;
long previousMillisW = 0;
int intervalW = 500;
// Pet Food Gate
#include <ESP32Servo.h>
#define SERVO_PIN 14
// Gate controller
Servo servoMotor;
int servoAngle = 15; // Initial angle (15 degrees)
// Broker
#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* hostname = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
const char* espClientName = "esp32Client_no1petfeeder";
int PORTNUM = 1883;
void setup_wifi()
{
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED )
{
delay(1000);
Serial.print(".");
}
Serial.println();
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("Given IP by the router to ESP32 is ");
Serial.println(WiFi.localIP());
}
void connectMQTT()
{
while(!client.connected() )
{
Serial.println("Connecting to MQTT ...");
if (client.connect(espClientName) ) //, mqttUser, mqttPassword) )
{
Serial.println("Connected");
MQTTSubscribe();
}
else
{
Serial.print("Failed with state ");
Serial.print(client.state() );
delay(2000);
}
}
}
void callback(String topic, byte* payload, unsigned int length)
{
String messageTemp;
Serial.print("Message received in topic: ");
Serial.print(topic);
Serial.print(" length is: ");
Serial.println(length);
Serial.print("Data received from broker: ");
for (int i = 0; i<length; i++)
{
Serial.print( (char)payload[i] );
messageTemp += (char)payload[i];
}
Serial.println();
if (topic == "NPSG/PetF/DropFood")
{
String DropStatus;
if (messageTemp == "DropFood")
{
servoAngle = 135;
servoMotor.write(servoAngle);
delay(3000);
servoAngle = 15;
servoMotor.write(servoAngle);
DropStatus = "Pet Food drop done (Estimate 10 grams per portion)";
}
client.publish("NPSG/PetF/DropStatus", DropStatus.c_str());
}
if (topic == "NPSG/PetF/WeightSet")
{
if (messageTemp == "One")
{
weightset = 20.0;
}
else if (messageTemp == "Two")
{
weightset = 40.0;
}
else if (messageTemp == "Three")
{
weightset = 60.0;
}
else if (messageTemp == "Four")
{
weightset = 80.0;
}
else if (messageTemp == "Five")
{
weightset = 100.0;
}
}
if (topic == "NPSG/PetF/TimingCheck")
{
if (messageTemp == "OptionA")
{
intervalW = 900000;
Serial.println("Set Check Timing: 15 mins");
}
else if (messageTemp == "OptionB")
{
intervalW = 1800000;
Serial.println("Set Check Timing: 30 mins");
}
else if (messageTemp == "OptionC")
{
intervalW = 3600000;
Serial.println("Set Check Timing: 1 hours");
}
else if (messageTemp == "OptionD")
{
intervalW = 14400000;
Serial.println("Set Check Timing: 4 hours");
}
}
}
void MQTTSubscribe()
{
client.subscribe("NPSG/PetF/DropFood");
client.subscribe("NPSG/PetF/WeightSet");
client.subscribe("NPSG/PetF/TimingCheck");
}
void setup_MQTT()
{
client.setServer(hostname, PORTNUM);
client.setCallback(callback);
}
void setup()
{
Serial.begin(9600);
pinMode(LidSensor, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(23, OUTPUT);
pinMode(19, OUTPUT);
pinMode(18, OUTPUT);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.tare(); // Reset scale
servoMotor.attach(SERVO_PIN);
servoMotor.write(servoAngle); // Set initial position
delay(500);
setup_wifi();
setup_MQTT();
}
void loop()
{
if ( !client.connected() )
{
connectMQTT();
}
client.loop();
// Pet Feeder Food storage Lid Sensor
String LidMsg, LidLED;
if (digitalRead(LidSensor) == HIGH)
{
digitalWrite(19, LOW);
LidMsg = "Storage Lid opening.";
LidLED = "Yellow";
}
else
{
digitalWrite(19, HIGH);
LidMsg = "Storage Lid closed.";
LidLED = "Off";
}
client.publish("NPSG/PetF/LidMsg", LidMsg.c_str());
client.publish("NPSG/PetF/LidLED", LidLED.c_str());
// Pet Food Storage Level Sensor
long currentMillisL = millis();
if ( currentMillisL - previousMillisL >= intervalL)
{
previousMillisL = currentMillisL;
digitalWrite(TRIG_PIN, HIGH); // Generate a 10-microsecond pulse to the TRIG pin
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH); // Measure the duration of the pulse from the ECHO pin
distance_cm = duration * adjustment; // Calculate the distance in centimeters
String FoodLevel;
if (distance_cm <= 5)
{
digitalWrite(18, LOW);
digitalWrite(23, HIGH);
FoodLevel = "Green";
}
else if (distance_cm > 5 && distance_cm < 15)
{
digitalWrite(18, HIGH);
digitalWrite(23, HIGH);
FoodLevel = "Yellow";
}
else if (distance_cm <= 20)
{
digitalWrite(18, HIGH);
digitalWrite(23, LOW);
FoodLevel = "Red";
}
else
{
digitalWrite(18, LOW);
digitalWrite(23, LOW);
FoodLevel = "Open";
}
client.publish("NPSG/PetF/FoodLevel", FoodLevel.c_str());
}
// Pet Food Bowl Weight Sensor
long currentMillisW = millis();
if ( currentMillisW - previousMillisW >= intervalW)
{
previousMillisW = currentMillisW;
float Rawdata = scale.get_units(); // Read food bowl weight value
float weight = Rawdata * calibrate;
float Calcul = weight - bowlset;
String BowlWeight = String(Calcul);
String GateStatus;
if ( Calcul < weightset )
{
servoAngle = 135;
GateStatus = "Droping Pet Food";
}
else
{
servoAngle = 15;
GateStatus = "Pet Food gate clossed";
}
servoMotor.write(servoAngle);
client.publish("NPSG/PetF/BowlWeight", BowlWeight.c_str());
client.publish("NPSG/PetF/GateStatus", GateStatus.c_str());
}
}