#include <ESP32Servo.h>
#include "thingProperties.h"
#include <string>
#include <Wire.h>
#include <HTTPClient.h>
#include <base64.h>
#include <WiFi.h>
#include <RTClib.h> // Include the RTClib library for RTC functionality
RTC_DS1307 rtc; // Create an RTC object
const char* accountSid = "AC926d9d44487fa3a2ccf01bf624aeb109";
const char* authToken = "234435e8b818e19a02b17f35d3a4bea4";
const char* fromNumber = "+12088377466";
const char* toNumber = "+919369599113";
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Time tracking for SMS alerts
const unsigned long smsInterval = 3600000; // 1 hour in milliseconds
unsigned long lastSmsTime = -smsInterval;
// Servo and LDR setup
const int ldrPin1 = 32, ldrPin2 = 35, ldrPin3 = 33, ldrPin4 = 34;
const int servoPin1 = 21, servoPin2 = 18, servoPin3 = 14, servoPin4 = 12;
float moistureThreshold;
int threshold;
const float GAMMA = 0.7, RL10 = 50;
Servo myservo1, myservo2, myservo3, myservo4;
// Soil moisture sensor setup
int minValue = 1680, maxValue = 3620;
unsigned long lastUpdateTime = 0; // Store the time of the last threshold check
unsigned long maxWaitTime = 30000; // Max wait time (e.g., 30 seconds)
unsigned long restartDelayTime = 10000; // Delay before restarting (e.g., 10 seconds)
bool isStopped = false; // To check if the servos are stopped
unsigned long stopTime = 0; // When the system was stopped
unsigned long currentTime;
int pos = 0;
void setup() {
// Start serial communication
Serial.begin(115200);
Wire.begin(23, 19); // SDA on GPIO 23, SCL on GPIO 19
// Wi-Fi connection
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
// Initialize Arduino IoT Cloud properties
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
// Servo setup
myservo1.attach(servoPin1, 500, 2400);
myservo2.attach(servoPin2, 500, 2400);
myservo3.attach(servoPin3, 500, 2400);
myservo4.attach(servoPin4, 500, 2400);
// Initialize the RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// Check if the RTC has lost power and if so, set the time
if (!rtc.isrunning()) {
Serial.println("RTC is NOT running, setting the time!");
// Set the RTC to the current time, you can customize this
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set time to the time this code was compiled
}
Serial.println("Plant automation system initialized.");
Serial.println("Setup ready...");
}
void loop() {
// Update Arduino IoT Cloud connection
ArduinoCloud.update();
// Wait until the IoT Cloud is connected before proceeding
if (ArduinoCloud.connected()) {
// Ensure tulsi (cloud variable) is available before processing
if (tulsi.length() > 0) {
DateTime now = rtc.now(); // Get the current time from the RTC
// Extract hours and minutes
int currentHour = now.hour();
int currentMinute = now.minute();
currentTime = millis();
if (isStopped) {
// Check if the restart delay time has passed
if (currentTime - stopTime > restartDelayTime) {
isStopped = false; // Restart the system
lastUpdateTime = currentTime; // Reset the last update time
Serial.println("Restarting the system after delay...");
}
else {
delay(100); // Wait before checking again
return; // Exit the loop to avoid executing further code until restart
}
}
Serial.print("Current time: ");
Serial.print(currentHour);
Serial.print(":");
Serial.println(currentMinute);
if (currentHour >= 6 && currentHour < 18) {
// If time is between 6:00 AM and 6:00 PM, start the plant system
Serial.println("Starting plant operations...");
processPlantSelection();
controlServosAndLDR();
checkSoilMoisture();
}
else {
// Otherwise, stop the plant system
Serial.println("Stopping plant operations...");
// Add code to stop the plant (like turning off motors, sensors, etc.)
delay(60000); // Wait for 1 minute before checking again
}
} else {
Serial.println("Waiting for tulsi variable to sync...");
}
// Call other functions to control servos and check soil moisture
}
}
void processPlantSelection() {
String selectedPlant = tulsi; // Use the synced cloud variable 'tulsi'
int commaIndex = selectedPlant.indexOf(',');
// Check if the comma is found in the string
if (commaIndex != -1) {
String firstPart = selectedPlant.substring(0, commaIndex);
String secondPart = selectedPlant.substring(commaIndex + 1);
moistureThreshold = firstPart.toFloat();
threshold = secondPart.toInt();
Serial.print("Moisture Threshold: ");
Serial.println(moistureThreshold);
Serial.print("Sunlight Threshold: ");
Serial.println(threshold);
} else {
Serial.println("Error: Invalid plant selection format");
}
}
void controlServosAndLDR() {
int ldrValue[4];
ldrValue[0] = readLDR(ldrPin1);
ldrValue[1] = readLDR(ldrPin2);
ldrValue[2] = readLDR(ldrPin3);
ldrValue[3] = readLDR(ldrPin4);
Serial.println(ldrValue[0]);
Serial.println(ldrValue[1]);
Serial.println(ldrValue[2]);
Serial.println(ldrValue[3]);
int avgLDR = (ldrValue[0] + ldrValue[1] + ldrValue[2] + ldrValue[3]) / 4;
sunlight_Intensity = avgLDR;
Serial.print("Avg sunlight: ");
Serial.println(avgLDR);
if (avgLDR > threshold) {
Serial.println("Current Sunlight greater than threshold needed");
delay(10000);
lastUpdateTime = millis();
Serial.println("Restarting the system after delay...");
} else {
if (currentTime - lastUpdateTime > maxWaitTime) {
// Stop the servos (set them to a rest position)
for (int i = 0; i < 4; i++) {
myservo1.write(pos);
myservo2.write(pos);
myservo3.write(pos);
myservo4.write(pos);
}
Serial.println("Threshold not reached, stopping the servos.");
isStopped = true; // Set the system as stopped
stopTime = millis(); // Mark the stop time to track restart delay
}
else decideMovement(ldrValue);
}
delay(500);
}
int readLDR(int pin) {
float analogValue = (analogRead(pin)) / 4;
float voltage = analogValue / 1024 * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
return pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
}
void decideMovement(int ldrValue[]) {
if ( ldrValue[0] == ldrValue[1] && ldrValue[1] == ldrValue[2] && ldrValue[2] == ldrValue[3]) {
Serial.println("All LDR values same, moving forward");
moveFront();
} else if (ldrValue[0]>ldrValue[3] && ldrValue[0] == ldrValue[1] && ldrValue[1] == ldrValue[2]) {
Serial.println("Moving right");
moveRight();
} else if (ldrValue[1]>ldrValue[0] && ldrValue[1] == ldrValue[2] && ldrValue[2] == ldrValue[3]) {
Serial.println("Moving back");
moveBack();
} else {
int maxDiff = INT_MIN, LDRIndex = -1;
for (int i = 0; i < 4; i++) {
if (ldrValue[i] - threshold > maxDiff) {
maxDiff = ldrValue[i] - threshold;
LDRIndex = i;
}
}
if (LDRIndex == 0) moveFront();
else if (LDRIndex == 1) moveRight();
else if (LDRIndex == 2) moveBack();
else if (LDRIndex == 3) moveLeft();
}
}
void checkSoilMoisture() {
int16_t rawValue = analogRead(36);
float moisturePercentage = ((float)(rawValue - minValue) / (maxValue - minValue)) * 100.0;
moisture_Level = moisturePercentage;
Serial.print("Soil Moisture: ");
Serial.print(moisturePercentage);
Serial.println("%");
if (moisturePercentage < moistureThreshold) {
Serial.println("Please Give Water...");
if (millis() - lastSmsTime >= smsInterval) {
sendSMS("Alert! Soil moisture low. Please water the plant.");
lastSmsTime = millis();
}
} else {
Serial.println("I am Chill ...");
}
delay(50); // Delay for readability
}
void sendSMS(String message) {
HTTPClient http;
String apiUrl = "https://api.twilio.com/2010-04-01/Accounts/" + String(accountSid) + "/Messages.json";
http.begin(apiUrl.c_str());
String credentials = String(accountSid) + ":" + String(authToken);
String encodedCredentials = base64::encode(credentials);
String authorizationHeader = "Basic " + encodedCredentials;
http.addHeader("Authorization", authorizationHeader.c_str());
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String postData = "To=" + String(toNumber) + "&From=" + String(fromNumber) + "&Body=" + message;
int httpResponseCode = http.POST(postData.c_str());
if (httpResponseCode > 0) {
Serial.print("HTTP POST response: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
} else {
Serial.print("Error sending SMS: ");
Serial.println(httpResponseCode);
}
http.end();
}
// Movement functions (as in the first code)
void moveLeft() {
Serial.println("Turning left, left motors slow down...");
int fastSpeedDelay = 10; // Normal speed for right motors (faster side)
int myservo1Pos = 0;
int myservo4Pos = 0;
for (int pos = 0; pos <= 180; pos++) {
// Move the left side slower (servo1 and servo3)
if (pos % 2 == 0) { // Slow down left-side wheels by updating every 2 iterations
myservo1.write(myservo1Pos);
myservo4.write(myservo4Pos);
myservo1Pos++;
myservo4Pos++;
}
// Move the right side wheels at normal speed (servo2 and servo4)
myservo2.write(pos); // Right front
myservo3.write(pos); // Right back
// Delay to control speed of right-side wheels
delay(fastSpeedDelay); // Delay for right-side motors (faster)
}
// Reset positions and move back from 180 to 0 for reverse movement
myservo1Pos = 180;
myservo4Pos = 180;
for (int pos = 180; pos >= 0; pos--) {
// Move the left side slower (servo1 and servo3)
if (pos % 2 == 0) {
myservo1.write(myservo1Pos);
myservo4.write(myservo4Pos);
myservo1Pos--;
myservo4Pos--;
}
// Move the right side wheels at normal speed (servo2 and servo4)
myservo2.write(pos); // Right front
myservo3.write(pos); // Right back
// Delay to control speed of right-side wheels
delay(fastSpeedDelay); // Delay for right-side motors (faster)
}
}
void moveRight() {
Serial.println("Turning right, right motors slow down...");
int fastSpeedDelay = 10; // Normal speed for left motors (faster side)
int slowSpeedDelay = 20; // Slow speed for right motors
int myservo2Pos = 0; // Position tracker for servo2 (front right)
int myservo3Pos = 0; // Position tracker for servo4 (back left)
for (int pos = 0; pos <= 180; pos++) {
// Move the left side at normal speed (servo1 and servo4)
myservo1.write(pos); // Front left
myservo4.write(pos); // Back left
// Move the right side slower (servo2 and servo3)
if (pos % 2 == 0) { // Slow down right-side wheels by updating every 2 iterations
myservo2.write(myservo2Pos);
myservo3.write(myservo3Pos);
myservo2Pos++;
myservo3Pos++;
}
// Delay to control speed of right-side wheels
delay(fastSpeedDelay); // Delay for left-side motors (faster)
}
// Reset positions and move back from 180 to 0 for reverse movement
myservo2Pos = 180;
myservo3Pos = 180;
for (int pos = 180; pos >= 0; pos--) {
// Move the left side at normal speed (servo1 and servo4)
myservo1.write(pos); // Front left
myservo4.write(pos); // Back left
// Move the right side slower (servo2 and servo3)
if (pos % 2 == 0) {
myservo2.write(myservo2Pos);
myservo3.write(myservo3Pos);
myservo2Pos--;
myservo3Pos--;
}
// Delay to control speed of right-side wheels
delay(fastSpeedDelay); // Delay for left-side motors (faster)
}
}
void moveFront() {
Serial.println("Moving forward...");
int fastSpeedDelay = 10; // Normal speed for all motors
for (int pos = 0; pos <= 180; pos++) {
// Move all servos forward at the same speed
myservo1.write(pos); // Front left
myservo2.write(pos); // Front right
myservo3.write(pos); // Back right
myservo4.write(pos); // Back left
// Delay to control speed
delay(fastSpeedDelay);
}
// Reset positions and move back from 180 to 0 for reverse movement
for (int pos = 180; pos >= 0; pos--) {
myservo1.write(pos); // Front left
myservo2.write(pos); // Front right
myservo3.write(pos); // Back right
myservo4.write(pos); // Back left
// Delay to control speed
delay(fastSpeedDelay);
}
}
void moveBack() {
Serial.println("Moving backward...");
int fastSpeedDelay = 10; // Normal speed for all motors
for (int pos = 0; pos <= 180; pos++) {
// Move all servos backward at the same speed
myservo1.write(180 - pos); // Front left
myservo2.write(180 - pos); // Front right
myservo3.write(180 - pos); // Back right
myservo4.write(180 - pos); // Back left
// Delay to control speed
delay(fastSpeedDelay);
}
// Reset positions and move back from 180 to 0 for reverse movement
for (int pos = 180; pos >= 0; pos--) {
myservo1.write(180 - pos); // Front left
myservo2.write(180 - pos); // Front right
myservo3.write(180 - pos); // Back right
myservo4.write(180 - pos); // Back left
// Delay to control speed
delay(fastSpeedDelay);
}
}
void onTulsiChange() {
Serial.println("Tulsi variable changed!");
Serial.print("New value: ");
Serial.println(tulsi);
}