TKK_E32211375/Kodearduino/terratech.ino

643 lines
22 KiB
C++

#define BLYNK_TEMPLATE_ID "TMPL6G1uKAeN1"
#define BLYNK_TEMPLATE_NAME "testingCopy"
#define BLYNK_AUTH_TOKEN "0QsM_PxN7blv9Zn1Rnroft8uxdJ7zCHR"
#define relay 4
#define soilMoisture 34
#define floot_water 25
#define buzzer 26
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiManager.h>
#include <ArduinoOTA.h>
#include <time.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
// Define constants
#define BLYNK_TEMPLATE_ID_LEN 20
#define BLYNK_TEMPLATE_NAME_LEN 40
#define BLYNK_AUTH_TOKEN_LEN 40
#define MAX_LEN 40
LiquidCrystal_I2C lcd(0X27, 16, 2);
WiFiClient client;
MySQL_Connection conn((Client *)&client);
bool relayState = false;
bool relayTurnedOnToday = false;
bool ManualButtonCondition = false;
bool AutoButtonCondition = false;
bool buzzerEnabled = true;
bool buzzerState = false;
int moistureLevelLo = 0;
int moistureLevelHi = 0;
float lastSoilMoisture = 0.0;
char ssid[64];
char pass[64];
char kebun_id[MAX_LEN];
char blynk_template_id[BLYNK_TEMPLATE_ID_LEN];
char blynk_template_name[BLYNK_TEMPLATE_NAME_LEN];
char blynk_auth_token[BLYNK_AUTH_TOKEN_LEN];
char created_at[50];
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 25200;
const int daylightOffset_sec = 0;
const char* otaPassword = "admin123"; // Kata sandi OTA
const char* otaHostname = "ESP32"; // Hostname OTA
float soilMoistureValue = analogRead(soilMoisture);
float calibratedMoisture = map(soilMoistureValue, 4095, 533, 0, 100);
unsigned long lastBuzzerStartTime = 0;
const unsigned long buzzerDuration = 300000;
const unsigned long buzzerOffDuration = 60000;
unsigned long lastBuzzerOffTime = 0;
unsigned long lastPumpStartTime = 0;
const unsigned long pumpRunDuration = 1 * 60 * 1000;
unsigned long lastHttpPostTime = 0;
unsigned long httpPostInterval = 60 * 1000;
unsigned long pumpManualOnTime = 0;
void setup() {
WiFi.mode(WIFI_STA);
Serial.begin(115200);
EEPROM.begin(512);
pinMode(floot_water, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
digitalWrite(relay, LOW);
pinMode(relay, OUTPUT);
lcd.init();
lcd.backlight();
// Membaca data dari EEPROM
String read_kebun_id = EEPROM.readString(0);
String read_blynk_template_id = EEPROM.readString(20);
String read_blynk_template_name = EEPROM.readString(60);
String read_blynk_auth_token = EEPROM.readString(100);
// Menampilkan data yang dibaca di Serial Monitor
Serial.println("Reading from EEPROM:");
Serial.println("kebun_id: " + read_kebun_id);
Serial.println("blynk_template_id: " + read_blynk_template_id);
Serial.println("blynk_template_name: " + read_blynk_template_name);
Serial.println("blynk_auth_token: " + read_blynk_auth_token);
// Inisialisasi WiFiManager
WiFiManager wifiManager;
bool needConfiguration = false;
// Memeriksa apakah data EEPROM valid
if (read_kebun_id.length() > 0 && read_blynk_template_id.length() > 0 &&
read_blynk_template_name.length() > 0 && read_blynk_auth_token.length() > 0) {
// Data valid, gunakan untuk konfigurasi Blynk
strncpy(kebun_id, read_kebun_id.c_str(), sizeof(kebun_id));
strncpy(blynk_template_id, read_blynk_template_id.c_str(), sizeof(blynk_template_id));
strncpy(blynk_template_name, read_blynk_template_name.c_str(), sizeof(blynk_template_name));
strncpy(blynk_auth_token, read_blynk_auth_token.c_str(), sizeof(blynk_auth_token));
Serial.println("Using saved data from EEPROM:");
Serial.println("kebun_id: " + String(kebun_id));
Serial.println("blynk_template_id: " + String(blynk_template_id));
Serial.println("blynk_template_name: " + String(blynk_template_name));
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
// Coba hubungkan ke WiFi dengan SSID yang disimpan
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting to");
lcd.setCursor(0, 1);
lcd.print("WiFi.........");
delay(5000);
WiFi.begin(ssid, pass);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Failed to connect to WiFi with saved credentials. Opening configuration portal...");
needConfiguration = true;
} else {
Serial.println("Connected to WiFi with saved credentials");
// Periksa apakah SSID telah berubah
if (String(WiFi.SSID()) != String(ssid)) {
Serial.println("SSID has changed, opening configuration portal...");
needConfiguration = true;
}
}
} else {
// Data tidak valid atau kosong, buka portal konfigurasi
Serial.println("No saved data in EEPROM or data invalid. Opening configuration portal...");
needConfiguration = true;
}
if (needConfiguration) {
WiFiManagerParameter custom_kebun_id("kebun_id", "Kebun ID", kebun_id, MAX_LEN);
WiFiManagerParameter custom_blynk_template_id("blynk_template_id", "Blynk Template ID", blynk_template_id, BLYNK_TEMPLATE_ID_LEN);
WiFiManagerParameter custom_blynk_template_name("blynk_template_name", "Blynk Template Name", blynk_template_name, BLYNK_TEMPLATE_NAME_LEN);
WiFiManagerParameter custom_blynk_auth_token("blynk_auth_token", "Blynk Auth Token", blynk_auth_token, BLYNK_AUTH_TOKEN_LEN);
wifiManager.addParameter(&custom_kebun_id);
wifiManager.addParameter(&custom_blynk_template_id);
wifiManager.addParameter(&custom_blynk_template_name);
wifiManager.addParameter(&custom_blynk_auth_token);
if (!wifiManager.autoConnect("TerraTech", "password")) {
Serial.println("Failed to connect to WiFi and hit timeout");
ESP.restart();
delay(1000);
}
// Simpan parameter kustom ke variabel
strncpy(ssid, WiFi.SSID().c_str(), sizeof(ssid));
strncpy(pass, WiFi.psk().c_str(), sizeof(pass));
strncpy(kebun_id, custom_kebun_id.getValue(), sizeof(kebun_id));
strncpy(blynk_template_id, custom_blynk_template_id.getValue(), sizeof(blynk_template_id));
strncpy(blynk_template_name, custom_blynk_template_name.getValue(), sizeof(blynk_template_name));
strncpy(blynk_auth_token, custom_blynk_auth_token.getValue(), sizeof(blynk_auth_token));
// Simpan parameter kustom ke EEPROM
EEPROM.writeString(0, kebun_id);
EEPROM.writeString(20, blynk_template_id);
EEPROM.writeString(60, blynk_template_name);
EEPROM.writeString(100, blynk_auth_token);
EEPROM.commit();
// Tampilkan data yang ditulis ke EEPROM di Serial Monitor
Serial.println("Saved new data to EEPROM:");
Serial.println("kebun_id: " + String(kebun_id));
Serial.println("blynk_template_id: " + String(blynk_template_id));
Serial.println("blynk_template_name: " + String(blynk_template_name));
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
}
// Initialize Blynk with obtained credentials
Blynk.begin(blynk_auth_token, ssid, pass);
ArduinoOTA.setPassword(otaPassword);
ArduinoOTA.setHostname(otaHostname);
ArduinoOTA.begin();
// Menampilkan data yang digunakan ke Serial Monitor
Serial.println("Final data used:");
Serial.println("kebun_id: " + String(kebun_id));
Serial.println("blynk_template_id: " + String(blynk_template_id));
Serial.println("blynk_template_name: " + String(blynk_template_name));
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
buzzTwice();
uploadWireless();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SSID: ");
lcd.print(WiFi.SSID());
lcd.setCursor(0, 1);
lcd.print("IP: ");
lcd.print(WiFi.localIP());
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Penyiram");
lcd.setCursor(0, 1);
lcd.print(" Otomatis");
delay(5000);
lcd.clear();
for (int i = 0; i < 5; i++) {
sendSoilMoistureData();
delay(500);
}
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// Ensure time is properly set up
// Wait for time to be set
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
} else {
Serial.println("Time obtained successfully");
Serial.print("Current time: ");
Serial.printf("%02d-%02d-%04d %02d:%02d:%02d\n",
timeinfo.tm_mday,
timeinfo.tm_mon + 1,
timeinfo.tm_year + 1900,
timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec);
lcd.setCursor(0, 0);
lcd.printf("%02d-%02d-%04d %02d:%02d:%02d",
timeinfo.tm_mday,
timeinfo.tm_mon + 1,
timeinfo.tm_year + 1900,
timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec);
}
}
void loop() {
ArduinoOTA.handle();
Blynk.run();
getDateTime();
checkWiFiConnection();
unsigned long currentMillis = millis();
// Kirim data ke server web setiap 1 menit
if (currentMillis - lastHttpPostTime >= httpPostInterval) {
int kebun_id_int = atoi(kebun_id);
sendHttpPost(calibratedMoisture, buzzerState, relayState, kebun_id_int, created_at);
lastHttpPostTime = currentMillis;
}
// Kirim data ke Blynk setiap 2 detik
static unsigned long lastBlynkUpdateTime = 0;
const unsigned long blynkUpdateInterval = 2000; // Waktu interval dalam milidetik (2 detik)
if (currentMillis - lastBlynkUpdateTime >= blynkUpdateInterval) {
sendSoilMoistureData(); // Memanggil fungsi untuk mengirim data ke Blynk
sendRelayStatusToBlynk();
sendBuzzerStatusToBlynk();
lastBlynkUpdateTime = currentMillis;
}
// Diperbarui nilai kelembaban tanah
soilMoistureValue = analogRead(soilMoisture);
calibratedMoisture = map(soilMoistureValue, 4095, 533, 0, 100);
calibratedMoisture = constrain(calibratedMoisture, 0, 100);
bool isDry = (calibratedMoisture < moistureLevelLo);
bool isPumpOn = relayState;
displayLCD(isDry, calibratedMoisture, isPumpOn);
// Cek jadwal pompa dan kontrol pompa berdasarkan jadwal
checkPumpSchedule();
handleFlootWater();
// Kontrol relay berdasarkan kelembaban tanah
controlRelayBasedOnSoilMoisture();
delay(1000); // Delay singkat untuk menjaga agar loop tidak terlalu cepat
}
void checkWiFiConnection() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi connection lost.");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi connection lost.");
lcd.setCursor(0, 1);
lcd.print("Reconnecting....");
// Start WiFi Manager again for reconnection attempt
WiFiManager wifiManager;
// Custom parameters to configure in WiFi Manager
WiFiManagerParameter custom_kebun_id("kebun_id", "Kebun ID", kebun_id, MAX_LEN);
WiFiManagerParameter custom_blynk_template_id("blynk_template_id", "Blynk Template ID", blynk_template_id, BLYNK_TEMPLATE_ID_LEN);
WiFiManagerParameter custom_blynk_template_name("blynk_template_name", "Blynk Template Name", blynk_template_name, BLYNK_TEMPLATE_NAME_LEN);
WiFiManagerParameter custom_blynk_auth_token("blynk_auth_token", "Blynk Auth Token", blynk_auth_token, BLYNK_AUTH_TOKEN_LEN);
wifiManager.addParameter(&custom_kebun_id);
wifiManager.addParameter(&custom_blynk_template_id);
wifiManager.addParameter(&custom_blynk_template_name);
wifiManager.addParameter(&custom_blynk_auth_token);
if (!wifiManager.autoConnect("TerraTech", "password")) {
Serial.println("Failed to connect and hit timeout");
// Handle failure (e.g., restart)
ESP.restart();
}
// Check if connected after trying to connect
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi reconnected");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connected to");
lcd.setCursor(0, 1);
lcd.print(WiFi.SSID());
// Update credentials
strncpy(ssid, WiFi.SSID().c_str(), sizeof(ssid));
strncpy(pass, WiFi.psk().c_str(), sizeof(pass));
strncpy(kebun_id, custom_kebun_id.getValue(), sizeof(kebun_id));
strncpy(blynk_template_id, custom_blynk_template_id.getValue(), sizeof(blynk_template_id));
strncpy(blynk_template_name, custom_blynk_template_name.getValue(), sizeof(blynk_template_name));
strncpy(blynk_auth_token, custom_blynk_auth_token.getValue(), sizeof(blynk_auth_token));
EEPROM.writeString(0, kebun_id);
EEPROM.writeString(20, blynk_template_id);
EEPROM.writeString(60, blynk_template_name);
EEPROM.writeString(100, blynk_auth_token);
EEPROM.commit();
Serial.println("Saved new data to EEPROM:");
Serial.println("kebun_id: " + String(kebun_id));
Serial.println("blynk_template_id: " + String(blynk_template_id));
Serial.println("blynk_template_name: " + String(blynk_template_name));
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
// Reinitialize Blynk with new credentials
Blynk.begin(blynk_auth_token, ssid, pass);
} else {
Serial.println("\nFailed to reconnect WiFi. Restarting...");
ESP.restart();
}
}
}
void handleFlootWater() {
unsigned long currentMillis = millis();
if (buzzerEnabled) { // Only handle buzzer if it's enabled
if (digitalRead(floot_water) == HIGH && (currentMillis - lastBuzzerOffTime >= buzzerOffDuration)) { // Floot water up
if (!buzzerState) {
digitalWrite(buzzer, HIGH);
buzzerState = true;
lastBuzzerStartTime = millis();
}
} else { // Floot water down
if (buzzerState) {
digitalWrite(buzzer, LOW);
buzzerState = false;
lastBuzzerOffTime = millis();
Blynk.virtualWrite(V10, "Hidupkan Mode Otomatis atau Manual");
}
}
// Turn off the buzzer after the specified duration if floot water stays high
if (buzzerState && (currentMillis - lastBuzzerStartTime >= buzzerDuration)) {
digitalWrite(buzzer, LOW);
buzzerState = false;
lastBuzzerOffTime = millis(); // Record the time when the buzzer was turned off
}
} else {
digitalWrite(buzzer, LOW);
buzzerState = false;
}
}
void sendHttpPost(float calibratedMoisture, bool buzzerState, bool relayState, int kebun_id, const char* created_at) {
HTTPClient http;
Serial.println("Starting HTTP POST...");
http.begin("https://kantorku.cloud/terratech/upload/upload.php");
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> jsonDoc;
jsonDoc["soil_moisture"] = calibratedMoisture;
jsonDoc["buzzer_state"] = buzzerState;
jsonDoc["relay_state"] = relayState;
jsonDoc["kebun_id"] = kebun_id;
jsonDoc["created_at"] = created_at;
String jsonString;
serializeJson(jsonDoc, jsonString);
// Send POST request with JSON payload
int httpResponseCode = http.POST(jsonString);
if (httpResponseCode > 0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String response = http.getString();
Serial.println(response);
Serial.println("---------------------------------");
} else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
Serial.println("---------------------------------");
}
http.end();
}
void uploadWireless() {
ArduinoOTA.setHostname(otaHostname); // Hostname OTA
ArduinoOTA.setPassword(otaPassword); // Kata sandi OTA
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void displayLCD(bool isDry, float moistureValue, bool isPumpOn) {
lcd.clear();
char moistureStr[6]; // Menyimpan string untuk kelembaban tanah
// Format nilai kelembaban ke dalam format dua digit dengan angka nol di depan jika diperlukan
sprintf(moistureStr, "%05.2f", moistureValue);
if (isDry) {
lcd.setCursor(0, 0);
lcd.print("T Kering: ");
lcd.print(moistureStr);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Pompa : ");
lcd.print(isPumpOn ? "Hidup" : "Mati");
} else {
lcd.setCursor(0, 0);
lcd.print("T Basah: ");
lcd.print(moistureStr);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Pompa : ");
lcd.print(isPumpOn ? "Hidup" : "Mati");
}
}
void sendRelayStatusToBlynk() {
// Mengirim status relay ke pin virtual 14 di Blynk
Blynk.virtualWrite(V14, relayState ? "Hidup" : "Mati");
}
void sendBuzzerStatusToBlynk() {
// Mengirim status buzzer ke pin virtual 15 di Blynk
Blynk.virtualWrite(V15, buzzerState ? "Habis" : "Penuh");
}
void getDateTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
snprintf(created_at, sizeof(created_at), "0000-00-00 00:00:00");
} else {
snprintf(created_at, sizeof(created_at), "%04d-%02d-%02d %02d:%02d:%02d",
timeinfo.tm_year + 1900,
timeinfo.tm_mon + 1,
timeinfo.tm_mday,
timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec);
}
}
void controlRelayBasedOnSoilMoisture() {
static unsigned long lastTurnOnTime = 0;
static unsigned long lastTurnOffTime = 0;
unsigned long currentTime = millis();
if (digitalRead(floot_water) == HIGH) { // Check if floot water is HIGH
// If flood water is low, turn off the relay
digitalWrite(relay, LOW); // Matikan pompa
relayState = false;
Serial.println("Pompa dimatikan karena floot water rendah");
Blynk.virtualWrite(V10, "Air Habis Penyiraman Nonaktif");
handleFlootWater();
return; // Exit the function
}
if (AutoButtonCondition) {
// Mode otomatis aktif
if (calibratedMoisture < moistureLevelLo && !relayState) {
digitalWrite(relay, HIGH); // Nyalakan pompa
relayState = true;
lastTurnOnTime = currentTime;
Serial.println("Pompa dinyalakan otomatis karena kelembaban rendah");
} else if (calibratedMoisture >= moistureLevelHi && relayState) {
digitalWrite(relay, LOW); // Matikan pompa
relayState = false;
lastTurnOffTime = currentTime;
Serial.println("Pompa dimatikan otomatis karena kelembaban cukup tinggi");
}
} else if (ManualButtonCondition) {
// Mode manual aktif
digitalWrite(relay, HIGH); // Nyalakan pompa
relayState = true;
pumpManualOnTime = currentTime; // Set the manual on time
Serial.println("Pompa dinyalakan secara manual");
} else {
// Matikan pompa jika tidak dalam mode otomatis atau manual
digitalWrite(relay, LOW); // Matikan pompa
relayState = false;
Serial.println("Pompa dimatikan karena tidak dalam mode otomatis atau manual");
}
}
void sendSoilMoistureData() {
if (calibratedMoisture != lastSoilMoisture) {
lastSoilMoisture = calibratedMoisture;
Blynk.virtualWrite(V11, calibratedMoisture);
Serial.print("Soil Moisture: ");
Serial.println(soilMoistureValue);
Serial.print("kalibrasi: ");
Serial.println(calibratedMoisture);
Serial.println("Relay: " + (String)(relayState ? "Hidup" : "Mati"));
Serial.println("Moisture Lo: " + (String)moistureLevelLo);
Serial.println("Moisture Hi: " + (String)moistureLevelHi);
Serial.println("buzzer: " + (String)(buzzerState ? "Hidup" : "Mati"));
Serial.println("Level Air: " + (String)floot_water);
Serial.println("Soil Moisture data sent to Blynk");
Serial.println("---------------------------------");
}
}
void buzzTwice() {
for (int i = 0; i < 2; i++) {
digitalWrite(buzzer, HIGH);
delay(100); // Buzz duration
digitalWrite(buzzer, LOW);
delay(100); // Pause between buzzes
}
}
void checkPumpSchedule() {
unsigned long currentMillis = millis();
struct tm timeinfo;
// Check if the current time is 9 AM
if (getLocalTime(&timeinfo)) {
if (timeinfo.tm_hour == 9 && timeinfo.tm_min == 0 && !relayTurnedOnToday) {
digitalWrite(relay, HIGH); // Turn on the pump
relayState = true;
lastPumpStartTime = currentMillis;
relayTurnedOnToday = true;
Serial.println("Pompa dinyalakan pada pukul 9 pagi");
}
}
// Turn off the pump after the run duration
if (relayTurnedOnToday && (currentMillis - lastPumpStartTime >= pumpRunDuration)) {
digitalWrite(relay, LOW); // Turn off the pump
relayState = false;
relayTurnedOnToday = false; // Reset for the next day
Serial.println("Pompa dimatikan setelah 1 menit");
}
}
BLYNK_WRITE(V8) {
moistureLevelLo = param.asInt();
Serial.print("Set low moisture level: ");
Serial.println(moistureLevelLo);
}
BLYNK_WRITE(V9) {
moistureLevelHi = param.asInt();
Serial.print("Set high moisture level: ");
Serial.println(moistureLevelHi);
}
BLYNK_WRITE(V6) {
AutoButtonCondition = param.asInt();
if (AutoButtonCondition == 1) {
Serial.println("Automatic mode activated");
Blynk.virtualWrite(V10, "Penyiraman Otomatis Hidup");
} else {
Serial.println("Automatic mode deactivated");
Blynk.virtualWrite(V10, "Penyiraman Mati");
}
}
BLYNK_WRITE(V7) {
relayState = param.asInt() == 1;
if (relayState == 1) {
digitalWrite(relay, HIGH);
ManualButtonCondition = true;
Blynk.virtualWrite(V8, created_at);
Blynk.virtualWrite(V10, "Penyiraman Manual Hidup");
} else {
digitalWrite(relay, LOW);
ManualButtonCondition = false;
Blynk.virtualWrite(V10, "Penyiraman Mati");
}
}
BLYNK_WRITE(V13) { // New Blynk virtual pin for buzzer control
buzzerEnabled = param.asInt() == 1;
if (buzzerEnabled) {
Serial.println("Buzzer enabled");;
} else {
Serial.println("Buzzer disabled");
digitalWrite(buzzer, LOW);
buzzerState = false;
}
}