#include <Wire.h>
#include <WiFi.h> //This library enables the ESP32 to connect to a WiFi network.
#include <PubSubClient.h> //It allows the ESP32 to communicate with an MQTT broker.
#include <LiquidCrystal_I2C.h>
#include <HX711.h>
#include <ESP32Servo.h> //This library is used for controlling servo motors with the ESP32.
// Define your custom SDA and SCL pins here
#define SDA_PIN 4 // Example pin for SDA
#define SCL_PIN 5 // Example pin for SCL
#define SERVO_PIN 2 // Pin connected to the servo motor.
// Calibration factor for 50 kg load cell
const float calibration_factor1 = 1.0; // Adjust this value as needed
const float calibration_factor2 = 1.0; // Adjust this value as needed
// Define the range of the output values
const float output_min = 0.0;
const float output_max = 50.0;
// Servo motor
Servo servo;
LiquidCrystal_I2C lcd(0x27, 16, 2); // Address 0x27 for a 16x2 LCD
HX711 scale1;
HX711 scale2;
// MQTT Credentials
const char* ssid = "Wokwi-GUEST"; // Setting your AP SSID
const char* password = ""; // Setting your AP PSK
const char* mqttServer = "broker.hivemq.com";
// const char* mqttUserName = "bqzbdodo";
// const char* mqttPwd = "5oU2W_QN2WD8";
const char* espClientName = "esp32Client_Mohanraj"; // Client ID username+0001
// Parameters for using non-blocking delay
unsigned long previousMillis = 0;
const long interval = 1000;
String msgStr = ""; // MQTT message buffer
float temp, hum;
// Setting up WiFi and MQTT client
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
while (!client.connected()) {
if (client.connect( espClientName)) {
Serial.println("MQTT connected");
client.subscribe("Mohanraj/room/lights");
client.subscribe("Mohanraj/room/servo"); // Subscribe to servo topic
client.subscribe("Mohanraj/room/lights/neopixel"); // Subscribe to neopixel topic
Serial.println("Topic Subscribed");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000); // wait 5sec and retry
}
}
}
/* Subscribe callback
The callback function handles incoming MQTT messages and triggers corresponding actions based on the topic and
payload. It controls the servo motor(Door Open Close) based on the received messages*/
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message: ");
String data = "";
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
data += (char)payload[i];
}
Serial.println();
Serial.print("Message size: ");
Serial.println(length);
Serial.println();
Serial.println("-----------------------");
Serial.println(data);
if (String(topic) == "Mohanraj/room/servo") {
String command = String((char*)payload).substring(0, length);
Serial.print("Received command for servo: ");
Serial.println(command);
if (command == "open") {
Serial.println("Moving servo to 180 degrees");
servo.write(180); // Move the servo to 180 degrees (open position)
} else if (command == "close") {
Serial.println("Moving servo to 0 degrees");
servo.write(0); // Move the servo to 0 degrees (close position)
} else {
Serial.println("Invalid command for servo");
}
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqttServer, 1883); // Setting MQTT server
client.setCallback(callback); // Define function which will be called when a message is received.
Serial.println("Serial monitor initialized.");
Wire.begin(SDA_PIN, SCL_PIN); // Initialize I2C communication with custom pins
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on the backlight
scale1.begin(21, 22); // Example pins for HX711
scale2.begin(23, 19); // Example pins for HX711
Serial.println("HX711 scales initialized.");
// Set the calibration factor for each load cell
scale1.set_scale(calibration_factor1);
scale2.set_scale(calibration_factor2);
scale1.tare();
scale2.tare();
Serial.println("HX711 calibration and tare complete.");
// Setup servo
servo.attach(SERVO_PIN);
servo.write(0);
}
void loop() {
if (!client.connected()) { // If client is not connected
reconnect(); // Try to reconnect
}
client.loop();
// Get weight from first load cell
float weight1 = scale1.get_units(10); // Use a higher number of samples for better stability
// Get weight from second load cell
float weight2 = scale2.get_units(10); // Use a higher number of samples for better stability
// Scale the weight readings to a range from 0 to 50 kg
float scaled_weight1 = map(weight1, 0, calibration_factor1 * 50, output_min, output_max);
float scaled_weight2 = map(weight2, 0, calibration_factor2 * 50, output_min, output_max);
Serial.print("Weight 1: ");
Serial.print(scaled_weight1);
Serial.println(" kg");
Serial.print("Weight 2: ");
Serial.print(scaled_weight2);
Serial.println(" kg");
// Clear the LCD display
lcd.clear();
if (scaled_weight1 > 18 && scaled_weight2 > 18) {
lcd.print("Slat Full");
Serial.println("Slat Full");
client.publish("Mohanraj/room/Trash", "Slat Full");
} else if (scaled_weight1 > 18 || scaled_weight2 > 18) {
lcd.print("One Slat Available");
Serial.println("One Slat Available");
client.publish("Mohanraj/room/Trash", "One Slat Available");
} else {
lcd.print("Two Slat Available");
Serial.println("Two Slat Available");
client.publish("Mohanraj/room/Trash", "Two Slat Available");
}
delay(1000); // Update every second
}