#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define button_pin 2
#define led_pin 3
#define MoistureSensorPin 0
#define SDA 1
#define SCL 10
#define EnA 4
#define In1 18
#define In2 19
LiquidCrystal_I2C lcd(0x27, 16, 2);
volatile bool led_state = true;
bool initial = false;
const int freq = 2000;
const int resolution = 8;
int mois_value = 0;
int mois_percentage = 0;
double max_mois_value = 4095.0;
double min_mois_value = 2400.0;
volatile unsigned long last_interrupt_time = 0;
volatile unsigned long last_time = 0;
const unsigned long Timer = 5000;
const unsigned long debounce_time = 400;
volatile unsigned long high_moisture_time = 0;
const unsigned long sleep_duration = 20000;
// Interrupt Function + Debouncing
void Mode() {
unsigned long current_time = millis();
if (current_time - last_interrupt_time > debounce_time) {
led_state = !led_state;
}
last_interrupt_time = current_time;
last_time = millis();
initial = false;
}
void setup() {
Serial.begin(115200);
// GPIO
pinMode(button_pin, INPUT_PULLUP);
pinMode(led_pin, OUTPUT);
pinMode(In1, OUTPUT);
pinMode(In2, OUTPUT);
// Interrupt
attachInterrupt(digitalPinToInterrupt(button_pin), Mode, FALLING);
// Interface I2C
Wire.begin(SDA, SCL);
lcd.init();
lcd.backlight();
lcd.clear();
ledcAttach(EnA, freq, resolution);
}
void loop() {
digitalWrite(led_pin, led_state);
// Manual Mode
if (led_state == false) {
high_moisture_time = 0;
lcd.setCursor(0, 0);
lcd.print("Chuyen sang Mode: ");
lcd.setCursor(0,1);
lcd.print("Thu Cong");
digitalWrite(In1, LOW);
digitalWrite(In2, LOW);
ledcWrite(EnA, 0);
}
// Automatic Mode
if (led_state == true) {
unsigned long now_time = millis();
if (initial == false){
int mois_value_init = analogRead(MoistureSensorPin);
Serial.println("Mois_value_init: " + String(mois_value_init));
int mois_percentage_init = 100*((max_mois_value - mois_value_init) / (max_mois_value - min_mois_value));
mois_value = mois_value_init;
mois_percentage = mois_percentage_init;
lcd.clear();
initial = true;
}
// Timer
if (now_time - last_time >= Timer){
last_time = now_time;
// Analog to Digital
lcd.clear();
int mois_value_update = analogRead(MoistureSensorPin);
Serial.println("Mois_value_update: " + String(mois_value_update));
int mois_percentage_update = 100*((max_mois_value - mois_value_update) / (max_mois_value - min_mois_value));
mois_value = mois_value_update;
mois_percentage = mois_percentage_update;
// Sleep
if (mois_percentage > 70) {
high_moisture_time += Timer;
} else {
high_moisture_time = 0;
}
if (high_moisture_time >= sleep_duration) {
lcd.clear();
lcd.print("Going to Sleep...");
delay(1500);
lcd.clear();
lcd.noBacklight();
digitalWrite(led_pin, LOW);
Serial.println("Restart to awake");
delay(2000);
esp_deep_sleep_start();
}
}
// PWM
String moisture;
if(mois_percentage < 60){
moisture = "DRY";
digitalWrite(In1, HIGH);
digitalWrite(In2, LOW);
ledcWrite(EnA, 80);
}
else if(mois_percentage < 70 ){
moisture = "OKE";
digitalWrite(In1, HIGH);
digitalWrite(In2, LOW);
ledcWrite(EnA, 40);
}
else {
moisture = "WET";
digitalWrite(In1, LOW);
digitalWrite(In2, LOW);
ledcWrite(EnA, 0);
}
lcd.setCursor(0, 0);
lcd.print("Soil: " + String(mois_percentage) + "%");
lcd.setCursor(0,1);
lcd.print(moisture);
}
}