#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include "PubSubClient.h"
#include "DHTesp.h"
#include <ESP32Servo.h>
const char * MQTTServer = "broker.emqx.io";
const char * MQTT_Topic = "IoT/display";
//const char * MQTT_Topic1 = "IoT/data";
//const char * MQTT_Topic2 = "IoT/avgTemp";
//const char *MQTT_Topic3 = "IoT/light";
//const char *MQTT_Topic4 = "IoT/ph";
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
#define led1 2
#define led2 4
#define moto 17
#define ledr 13 // đỏ
//#define ledg 12 // lục
#define ledb 14 // xanh
const int button = 0;// Trạng thái trước đó của nút nhấn
unsigned long buttonPressedTime = 0;
const int motorRunTime = 5000; // 5 seconds
bool motorRunning = false;
int buttonState;
int lastButtonState;
unsigned long lastPublishTime = 0;
const unsigned long publishInterval = 10000;
int ledPins[] = {led1, led2, ledr, ledb};
const int potPin = 34;
const int ldrPin = 32;
const int buzzer = 27;
// ======================== Ph Sensor ======================
const int PhPin = 35;
//const int Acidic = 14; // xanh
//const int Neutral = 12; // lục
//const int AnodeLed = 13; // đỏ
int phval = 0;
float PhValue;
int buffer_arr[10], temp;
unsigned long int avgval;
const float MAX = 4095.00;
float calibration_value = 21.34;
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
WiFiClient espClient;
PubSubClient client(espClient);
// Tạo ID ngẫu nhiên tại: https://www.guidgen.com/
const char * MQTT_ID = "c5afa5ae-d3a0-48b7-b850-92015a281909";
int Port = 1883;
const int DHT_PIN = 15;
DHTesp dhtSensor;
// Khai báo để tính nhiệt độ trung bình
const int numReadings = 3;
float temperatures[numReadings];
int readIndex = 0;
float total = 0;
float average = 0;
int numValidReadings = 0;
void WIFIConnect() {
Serial.println("Connecting to SSID: Wokwi-GUEST");
WiFi.begin("Wokwi-GUEST", "");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected");
Serial.print(", IP address: ");
Serial.println(WiFi.localIP());
}
void MQTT_Reconnect() {
while (!client.connected()) {
if (client.connect(MQTT_ID)) {
Serial.print("MQTT Topic: ");
Serial.print(MQTT_Topic);
Serial.println(" connected");
Serial.println("");
Serial.print("MQTT Topic: ");
// Serial.print(MQTT_Topic1);
Serial.println(" connected");
Serial.println("");
Serial.print("MQTT Topic: ");
//Serial.print(MQTT_Topic2);
Serial.println(" connected");
Serial.println("");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.println(topic);
Serial.print("Message: ");
String stMessage;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
stMessage += (char)message[i];
}
Serial.println();
}
void setup() {
Serial.begin(115200);
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
WIFIConnect();
client.setServer(MQTTServer, Port);
client.setCallback(callback);
lcd.init();
lcd.backlight();
// Print something
lcd.setCursor(3, 0);
lcd.print("Welcome!");
Serial.begin(115200);
pinMode(ledPins[0], OUTPUT);
pinMode(ledPins[1], OUTPUT);
pinMode(ledPins[2], OUTPUT);
// pinMode(ledPins[3], OUTPUT);
pinMode(ledPins[3], OUTPUT);
pinMode(moto, OUTPUT);
pinMode(buzzer, OUTPUT);
//pinMode(Acidic, OUTPUT);
// pinMode(Neutral, OUTPUT);
//pinMode(AnodeLed, OUTPUT);
pinMode(PhPin, INPUT);
pinMode(potPin, INPUT);
pinMode(ldrPin, INPUT);
pinMode(button, INPUT);
ledcSetup(1, 5000, 8); // Tham số: kênh (0-15), tần số PWM, độ phân giải bit
//ledcAttachPin(ledPins[2], 1);
//Khởi tạo mảng lưu nhiệt độ trung bình
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
temperatures[thisReading] = NAN;
}
}
void WaterQualityMode() // =============================== WATER QUALITY @ PH SENSOR =============================
{
for (int i = 0; i < 10; i++)
{
buffer_arr[i] = analogRead(PhPin); //Read and store the value of pH in an array
}
//Sorting the array from small to big
for (int i = 0; i < 9; i++)
{
for (int j = i + 1; j < 10; j++)
{
if (buffer_arr[i] > buffer_arr[j])
{
temp = buffer_arr[i];
buffer_arr[i] = buffer_arr[j];
buffer_arr[j] = temp;
}
}
}
avgval = 0;
for (int i = 2; i < 8; i++)
{ //Calculation to get the pH value
avgval += buffer_arr[i];
float volt = (float)avgval * 5.0 / MAX / 6;
float ph_act = -5.70 * volt + calibration_value;
PhValue = ph_act;
}
if (PhValue < 6)
{
digitalWrite(ledPins[2], HIGH); // RGB LED turns RED
digitalWrite(ledPins[3], LOW);
}
else if (PhValue > 7.5)
{
digitalWrite(ledPins[3], HIGH); // RGB LED turns BLUE
digitalWrite(ledPins[2], LOW);
}
else // PhValue nằm trong khoảng từ 6 đến 7
{
digitalWrite(ledPins[3], LOW); // RGB LED turns OFF
digitalWrite(ledPins[2], LOW);
}
// String phMessage = String(PhValue);
//client.publish("IoT/ph", phMessage.c_str());
Serial.println(PhValue);
}
void loop() {
delay(10);
if (!client.connected()) {
MQTT_Reconnect();
}
client.loop();
// Đọc dữ liệu từ cảm biến DHT22
float humidity = dhtSensor.getHumidity();
float temperature = dhtSensor.getTemperature();
// Kiểm tra dữ liệu có hợp lệ không
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
//Thực hiện tính trung bình
// Cập nhật mảng và số lượng đọc hợp lệ
if (!isnan(temperatures[readIndex])) {
// Nếu giá trị cũ là hợp lệ, giảm số lượng đọc hợp lệ
numValidReadings--;
}
temperatures[readIndex] = temperature;
if (!isnan(temperature)) {
// Nếu giá trị mới là hợp lệ, tăng số lượng đọc hợp lệ
numValidReadings++;
}
readIndex = (readIndex + 1) % numReadings;
// Tính trung bình
float total = 0;
for (int i = 0; i < numReadings; i++) {
if (!isnan(temperatures[i])) {
total += temperatures[i];
}
}
float average = numValidReadings > 0 ? total / numValidReadings : NAN;
// Gửi dữ liệu nếu có đủ giá trị hợp lệ
if (!isnan(average)) {
/// String message = String(average);
// client.publish(MQTT_Topic2, message.c_str());
}
//gửi dữ liệu lên mqtt
if (!isnan(humidity) && !isnan(temperature)) {
// Tạo chuỗi tin nhắn
// String message = String(temperature) + "|" + String(humidity);
// Gửi tin nhắn
// client.publish(MQTT_Topic1, message.c_str());
}
if (temperature > 38 && humidity < 40) {
// client.publish(MQTT_Topic,"Báo động");
digitalWrite(ledPins[0],HIGH);
}
else {
//client.publish(MQTT_Topic,"Bình thường");
digitalWrite(ledPins[0],LOW);
}
// Hiển thị dữ liệu lên LCD
lcd.clear(); // Xóa nội dung cũ trên LCD
lcd.setCursor(0, 0); // Đặt con trỏ tại vị trí đầu tiên của LCD
lcd.print("Temp: ");
lcd.print(temperature);
lcd.print(" C");
lcd.setCursor(0, 1); // Chuyển con trỏ xuống dòng tiếp theo
lcd.print("Humidity: ");
lcd.print(humidity);
lcd.print(" %");
Serial.print("Temperature: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.println(humidity);
// Thêm delay để giữ dữ liệu trên màn hình một thời gian
delay(100); // Cập nhật dữ liệu mỗi 2 giây
// Read potentiometer value (simulate soil moisture)
int moistureValue = analogRead(potPin);
// Read LDR value (simulate light level)
int lightValue = analogRead(ldrPin);
unsigned long currentTime = millis();
// Kiểm tra xem có phải là thời gian từ 8 giờ sáng đến 3 giờ chiều không
if (currentTime >= 8 * 3600000 && currentTime <= 15 * 3600000) {
// Trong khoảng thời gian từ 8 giờ sáng đến 3 giờ chiều
// Đọc giá trị ánh sáng và thực hiện xử lý
int lightValue = analogRead(ldrPin);
if (lightValue <= 1000 || lightValue >= 2000) {
digitalWrite(ledPins[1], HIGH); // Turn on the LED
Serial.print("LED ON - ");
} else {
digitalWrite(ledPins[1], LOW); // Turn off the LED
Serial.print("LED OFF - ");
}
// ... (Các xử lý khác trong khoảng thời gian mong muốn)
} else {
// Ngoài khoảng thời gian từ 8 giờ sáng đến 3 giờ chiều
// Tắt LED hoặc thực hiện xử lý khác nếu cần thiết
digitalWrite(ledPins[1], LOW); // Turn off the LED
}
//String lightMessage = String(lightValue);
// client.publish(MQTT_Topic3, lightMessage.c_str());
// Check muc nuoc and control the buzzer
if (moistureValue <= 2023) {
noTone(buzzer); // Turn off buzzer sound
Serial.print("BUZZER OFF - ");
}
else {
tone(buzzer, 1000); // Generate a sound
Serial.print("BUZZER ON - ");
}
// Print values to Serial Monitor on a single line
Serial.print("mực nước: ");
Serial.print(moistureValue);
Serial.print(" - ánh sáng: ");
Serial.println(lightValue);
WaterQualityMode();
// Tạo chuỗi dữ liệu và đưa vào các giá trị
String payload = String(temperature) + "|" + String(humidity) + "|" + String(PhValue) + "|" + String(lightValue) + "|" + String(moistureValue);
// Gửi chuỗi dữ liệu lên MQTT
client.publish(MQTT_Topic, payload.c_str());
buttonState = digitalRead(button);
if (buttonState == HIGH) {
buttonPressedTime = 0; // Reset the timer
} else {
if (buttonPressedTime == 0) {
buttonPressedTime = millis(); // Record the start time
} else {
unsigned long currentTime = millis();
unsigned long buttonPressDuration = currentTime - buttonPressedTime;
// Check if the button has been pressed for 5 seconds
if (buttonPressDuration >= motorRunTime) {
motorRunning = !motorRunning; // Toggle the motor state
buttonPressedTime = 0; // Reset the timer
}
}
}
if (motorRunning) {
digitalWrite(moto, HIGH); // Start the motor
Serial.println("Motor ON");
} else {
digitalWrite(moto, LOW); // Stop the motor
Serial.println("Motor OFF");
}
delay(1000); // Delay for readability
}