/*
Forth level Autonomous solar panel cleaning robot
Edited for Node-RED MQTT Integration
Date: 9-Feb-2025
*/
#include <Wire.h>
#include "RTClib.h"
#include <WiFi.h>
#include <PubSubClient.h>
#define RIGHT_SWITCH 14
#define LEFT_SWITCH 12
#define RAIN_SENSOR 13
#define FORWARD_MOTOR 5
#define REVERSE_MOTOR 18
#define FORWARD_BRUSH 19
#define REVERSE_BRUSH 26
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";
RTC_DS1307 rtc;
WiFiClient espClient;
PubSubClient client(espClient);
bool manualControl = false;
bool forwardCommand = false;
bool reverseCommand = false;
void setup_wifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
}
void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
String message = String((char*)payload);
if (String(topic) == "/robot/control") {
if (message == "FORWARD") {
manualControl = true;
forwardCommand = true;
reverseCommand = false;
} else if (message == "REVERSE") {
manualControl = true;
reverseCommand = true;
forwardCommand = false;
} else if (message == "STOP") {
manualControl = false;
stopMotors();
}
}
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ESP32Client")) {
client.subscribe("/robot/control");
} else {
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
rtc.begin();
pinMode(RIGHT_SWITCH, INPUT_PULLUP);
pinMode(LEFT_SWITCH, INPUT_PULLUP);
pinMode(RAIN_SENSOR, INPUT);
pinMode(FORWARD_MOTOR, OUTPUT);
pinMode(REVERSE_MOTOR, OUTPUT);
pinMode(FORWARD_BRUSH, OUTPUT);
pinMode(REVERSE_BRUSH, OUTPUT);
stopMotors();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
bool isRightPressed = digitalRead(RIGHT_SWITCH) == LOW;
bool isLeftPressed = digitalRead(LEFT_SWITCH) == LOW;
bool isRaining = digitalRead(RAIN_SENSOR) == LOW;
String sensorData = "{\"right_switch\": " + String(isRightPressed) + ", \"left_switch\": " + String(isLeftPressed) + ", \"rain\": " + String(isRaining) + "}";
client.publish("/robot/status", sensorData.c_str());
if (manualControl) {
if (forwardCommand) startForward();
else if (reverseCommand) startReverse();
} else {
DateTime time = rtc.now();
if (time.hour() == 13 && time.minute() < 59 && !isRaining) {
startForward();
while (!isLeftPressed) {
isLeftPressed = digitalRead(LEFT_SWITCH) == LOW;
if (digitalRead(RAIN_SENSOR) == LOW) break;
delay(100);
}
stopMotors();
startReverse();
while (!isRightPressed) {
isRightPressed = digitalRead(RIGHT_SWITCH) == LOW;
delay(100);
}
stopMotors();
} else {
stopMotors();
}
}
delay(1000);
}
void stopMotors() {
digitalWrite(FORWARD_MOTOR, LOW);
digitalWrite(REVERSE_MOTOR, LOW);
digitalWrite(FORWARD_BRUSH, LOW);
digitalWrite(REVERSE_BRUSH, LOW);
}
void startForward() {
digitalWrite(FORWARD_MOTOR, HIGH);
digitalWrite(FORWARD_BRUSH, HIGH);
}
void startReverse() {
digitalWrite(REVERSE_MOTOR, HIGH);
digitalWrite(REVERSE_BRUSH, HIGH);
}