#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
//define pins and names
#define valve_1 4
#define valve_2 5
#define manual_switch_1 6
#define manual_switch_2 7
#define main_overide 9
#define DHTPIN 8
#define DHTTYPE DHT11
#define moist_sense1 A0
#define moist_sense2 A1
//define variables
String code_version = "1.0";
String message = "";
String message_to_send = "";
String switch_dis = "";
String valve_1_stats = "close";
String valve_2_stats = "close";
float moist_level1 = 0;
float moist_level2 = 0;
float humidity = 0;
float temperature = 0;
int counter = 0;
int moist_limit = 50;
int send_multiple = 0;
bool run_motor1 = false;
bool run_motor2 = false;
bool switch_to_temp = false;
bool switch_to_moist = false;
bool s_overide = false;
bool triggerSMS_1 = false;
bool triggerSMS_2 = false;
bool override_all = false;
bool start_up = true;
String numbers[] = { "+639501415816", "+639501415816" };
//debounce variables
unsigned long previousMillis = 0;
const long interval = 1000;
int buttonState1 = HIGH;
int lastButtonState1 = HIGH;
unsigned long lastDebounceTime1 = 0;
int debounceDelay = 50;
int buttonState2 = HIGH;
int lastButtonState2 = HIGH;
unsigned long lastDebounceTime2 = 0;
int buttonState3 = HIGH;
int lastButtonState3 = HIGH;
unsigned long lastDebounceTime3 = 0;
//create objects
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial gsmSerial(2, 3);
//data to send on sms contain all stats
void get_data(char *result) {
String ov = override_all ? "Active" : "Inactive";
message_to_send = "\ntemp : " + String(temperature) + " C"
+ "\nhum : " + String(humidity) + " %"
+ "\nSensor 1 :" + String(moist_level1 / 10.24) + " %"
+ "\nSensor 2 :" + String(moist_level2 / 10.24) + " %"
+ "\nvalve 1 :" + String(valve_1_stats)
+ "\nvalve 2 :" + String(valve_2_stats)
+ "\nOveride :" + ov;
// Copy the contents of message_to_send to the result char array
message_to_send.toCharArray(result, message_to_send.length() + 1);
}
void setup() {
// put your setup code here, to run once:
dht.begin();
lcd.init(); // Initialize the LCD with 16 columns and 2 rows
lcd.backlight(); // Turn on the backlight
pinMode(valve_1, OUTPUT);
pinMode(valve_2, OUTPUT);
pinMode(manual_switch_1, INPUT_PULLUP);
pinMode(manual_switch_2, INPUT_PULLUP);
pinMode(main_overide, INPUT_PULLUP);
digitalWrite(valve_1, LOW);
digitalWrite(valve_2, LOW);
Serial.println(" ");
Serial.begin(115200);
gsmSerial.begin(115200);
Serial.println("Initializing GSM module...");
delay(1000);
// Set GSM module to text mode for SMS
sendATCommand("AT+CMGF=1");
delay(1000);
}
void loop() {
// Check for incoming SMS
if (gsmSerial.available()) {
String response = readResponse();
Serial.println("Received SMS: " + response);
sendATCommand("AT+CMGD=1,4");
} else {
int reading1 = digitalRead(main_overide);
debounceButton(reading1, lastButtonState1, lastDebounceTime1, buttonState1, override_all);
if (override_all) {
lcd.setCursor(15, 0);
lcd.print("O");
lcd.setCursor(15, 1);
lcd.print("R");
} else {
lcd.setCursor(15, 0);
lcd.print(" ");
lcd.setCursor(15, 1);
lcd.print(" ");
}
//set all to lower case
if (message.length() > 0) {
message.toLowerCase(); // Convert the string to lowercase
// Serial.println("Lowercase: " + message);
switch_dis = String(message);
//message = ""; // Reset the input string
// Serial.println("disp: " + switch_dis);
}
int moist1 = analogRead(moist_sense1);
int moist2 = analogRead(moist_sense2);
moist_level1 = map(moist1, 1023, 0, 0, 1023);
moist_level2 = map(moist2, 1023, 0, 0, 1023);
humidity = dht.readHumidity();
temperature = dht.readTemperature();
moist_check();
switch_dis.trim(); //remove any leading space
if (switch_dis.indexOf("show") != -1) {
// Check if any reads failed and exit early (to try again).
unsigned long currentMillis = millis(); // Get the current time
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the current time
counter++;
switch_dis = counter >= 8 ? "" : switch_dis = switch_dis;
}
if (counter <= 8) {
print(humidity, "Hum : ", "% ", 0);
print(temperature, "Temp : ", "C ", 1);
}
switch_to_temp = true;
if (switch_to_moist) {
lcd.clear();
switch_to_moist = false;
}
} else {
print(moist_level1 / 10.24, "Loc 1 : ", "% ", 0);
print(moist_level2 / 10.24, "Loc 2 : ", "% ", 1);
counter = 0;
switch_to_moist = true;
if (switch_to_temp) {
lcd.clear();
switch_to_temp = false;
}
}
message_to_send.replace("From Sensor 2", "Requested");
message.trim();
if (message.indexOf("request") != -1) {
s_overide = true;
}
if (s_overide) {
char result[200]; // Adjust the size accordingly
get_data(result);
Serial.println(result);
Send(result, s_overide);
}
message = "";
}
}
void print(float data, String location, String unit, int row) {
lcd.setCursor(0, row);
lcd.print(location);
lcd.print(data);
lcd.print(unit);
}
void moist_check() {
if (override_all) {
//manual button 1
int reading2 = digitalRead(manual_switch_1);
debounceButton(reading2, lastButtonState2, lastDebounceTime2, buttonState2, run_motor1);
digitalWrite(valve_1, run_motor1);
//manual button 2
int reading3 = digitalRead(manual_switch_2);
debounceButton(reading3, lastButtonState3, lastDebounceTime3, buttonState3, run_motor2);
digitalWrite(valve_2, run_motor2);
} else {
char result[200]; // Adjust the size accordingly
get_data(result);
if (moist_level1 / 10.24 > moist_limit) {
valve_1_stats = "open";
digitalWrite(valve_1, HIGH);
if (!triggerSMS_1) {
Send(result, triggerSMS_1);
}
} else {
valve_1_stats = "close";
digitalWrite(valve_1, LOW);
if (triggerSMS_1) {
Send(result, triggerSMS_1);
}
}
if (moist_level2 / 10.24 > moist_limit) {
valve_1_stats = "open";
digitalWrite(valve_2, HIGH);
if (!triggerSMS_2) {
Send(result, triggerSMS_2);
}
} else {
valve_1_stats = "close";
digitalWrite(valve_2, LOW);
if (triggerSMS_2) {
Send(result, triggerSMS_2);
}
}
}
}
void debounceButton(int reading, int &lastButtonState, unsigned long &lastDebounceTime, int &buttonState, bool &val) {
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
val = !val;
if (val) {
Serial.println("val is true");
} else {
Serial.println("val is false");
}
}
}
}
lastButtonState = reading;
}
void Send(const char *message, bool &stats) {
static byte count = sizeof(numbers) / sizeof(numbers[0]);
static word startTimer, waitTimer; // waitTimer > 0 causes the timer to run, good up to 65 second intervals
static byte procState;
String phoneNumber = numbers[send_multiple];
if (count - send_multiple == 0) {
stats = !stats;
Serial.println("finished sending");
send_multiple = 0;
start_up = false;
} else {
send_multiple += 1;
if (start_up) {
Serial.println("start up");
return;
}
Serial.println("still sending");
String command = "AT+CMGS=\"" + String(phoneNumber) + "\"";
sendATCommand(command.c_str());
delay(1000);
gsmSerial.print(message);
gsmSerial.write(26); // End the SMS with Ctrl+Z
delay(1000);
}
}
void sendATCommand(const char *command) {
Serial.print("Sending AT command: ");
Serial.println(command);
gsmSerial.println(command);
delay(500); // Wait for the module to respond
readResponse(); // Read and print the response
}
String readResponse() {
String response = "";
while (gsmSerial.available()) {
char c = gsmSerial.read();
response += c;
}
return response;
}