/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-hc-sr04-ultrasonic-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
#include <Servo.h>
#include <WiFi.h>
#include <PubSubClient.h>
const int trigPin = 2;
const int echoPin = 4;
const int ldrPin = 36;
const int unlockSwitch = 15;
int adcValue = 0;
const float GAMMA = 0.7;
const float rl10 = 50;
//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define SERVO_PIN 26 // ESP32 pin GPIO26 connected to servo motor
Servo servoMotor;
long duration;
float distanceCm;
float percentage;
int RLED = 23;
int YLED = 19;
int GLED = 18;
int WLED = 5;
//WiFi
//const char* ssid = "Adar's Galaxy N10+";
//const char* password = "Adarwashere";
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* hostname = "broker.hivemq.com";
const char *topicPubSmartbin = "iotgprj/town/smartbin/amount";
const char *topicPubUnlockStatus = "iotgprj/town/smartbin/status";
const char *topicSubUnlock = "iotgprj/town/smartbin/unlock";
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;
// Change the espClientName **************
const char* espClientName = "iotg_project";
//**************
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 unlockBin(String &payload) { // ../smartbin/unlock
if (payload == "Unlocked") {
digitalWrite(15, LOW);
unlock();
delay(5000);
}
else if (payload == "Locked") {
digitalWrite(15, HIGH);
char buf[10] = "Locked";
publishTopic(topicPubUnlockStatus, buf);
}
}
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];
}
if (topic == topicSubUnlock)
unlockBin(messageTemp);
}
void MQTTSubscribe()
{
client.subscribe(topicSubUnlock);
}
bool publishTopic(const char* topic, const char *str) {
Serial.printf("\nPublishing topic \"%s\" + payload \"%s\"", topic, str);
if (client.publish(topic, str)) {
Serial.print(" -- Done ");
return true;
}
else {
Serial.print("\nPublishing encounter error");
return false;
}
}
void setup_MQTT()
{
client.setServer(hostname, PORTNUM);
client.setCallback(callback);
}
void setup() {
Serial.begin(115200); // Starts the serial communication
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
servoMotor.attach(SERVO_PIN); // attaches the servo on ESP32 pin
pinMode(unlockSwitch, INPUT);
setup_wifi();
setup_MQTT();
connectMQTT();
//LEDs
pinMode(23, OUTPUT);
pinMode(19, OUTPUT);
pinMode(18, OUTPUT);
pinMode(5, OUTPUT);
}
void loop() {
client.loop();
LDR();
UltrasonicSensor();
delay(100);
}
void UltrasonicSensor() {
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
digitalWrite(23, HIGH);
digitalWrite(19, HIGH);
digitalWrite(18, HIGH);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculate the distance
distanceCm = duration * SOUND_SPEED/2;
//distance is converted into percentage for easier data analysis
//average bin depth is 100cm
percentage = map(distanceCm, 1, 120, 100, 0);
if (percentage < 0) //percentage is considered zero beyond the 100cm mark
percentage = 0;
// Prints the distance in the Serial Monitor
Serial.print("Amount of Trash Filled: ");
Serial.print(percentage);
Serial.println("%");
if (percentage < 100) {
if (percentage < 50) {
Serial.println("Rubbish Bin is Available.");
servoMotor.write(0);
delay(10); // waits 10ms to reach the position
digitalWrite(18, LOW);
}
else if (percentage >= 50 && percentage < 80) {
Serial.println("Rubbish Bin is Half Full.");
// rotates from 0 degrees to 180 degrees
servoMotor.write(0);
delay(10); // waits 10ms to reach the position
digitalWrite(18, LOW);
}
else if (percentage >= 80 && percentage < 100) {
Serial.println("Rubbish Bin is Almost Full.");
// rotates from 0 degrees to 180 degrees
servoMotor.write(90);
delay(10); // waits 10ms to reach the position
digitalWrite(19, LOW);
}
char buf[10] = "Unlocked";
publishTopic(topicPubUnlockStatus, buf);
}
else if (percentage == 100) {
Serial.println("Rubbish Bin is Full!");
// rotates from 0 degrees to 180 degrees
servoMotor.write(180);
delay(10); // waits 15ms to reach the position
digitalWrite(23, LOW);
if (digitalRead(unlockSwitch) == LOW) {
unlock();
}
else if (digitalRead(unlockSwitch) == HIGH) {
char buf[10] = "Locked";
//buf[0] = topicPubUnlockStatus ? 'Locked' : 'Unlocked';
publishTopic(topicPubUnlockStatus, buf);
}
}
char buf[10];
itoa(percentage, buf, 10); // integer to string in buf
Serial.printf("\nPublishing capacity reading");
publishTopic(topicPubSmartbin, buf);
delay(500);
}
void LDR() {
int adcValue = analogRead(ldrPin);
float voltage = adcValue / 1024.0 * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(rl10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
Serial.println(lux);
if (lux >= 400.00) { //during daytime, the White LED is turned off
Serial.println("Daytime");
digitalWrite(5, HIGH);
}
else { //from dusk to dawn, the White LED is turned on
Serial.println("Nighttime");
digitalWrite(5, LOW);
}
delay(500);
}
void unlock() {
servoMotor.write(0);
delay(10);
char buf[10] = "Unlocked";
publishTopic(topicPubUnlockStatus, buf);
delay(50);
}