#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHTesp.h"
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = ""; // Thay bằng mật khẩu WiFi của bạn
// MQTT broker
const char* mqtt_broker = "3184a6f80f8948118b58afa89d73ae55.s1.eu.hivemq.cloud";
const char* mqtt_username = "lienhoa";
const char* mqtt_password = "Hoabmt123";
const int mqtt_port = 8883;
// MQTT topics
const char* subscribe_topic = "esp/sensor";
const char* response_topic_moisture = "esp/response_soil_moisture";
const char* response_topic_temperature = "esp/response_temperature";
const char* response_topic_humidity = "esp/response_humidity";
const char* response_topic_photoresistor = "esp/response_photoresistor";
WiFiClientSecure espClient; // Sử dụng WiFiClientSecure để hỗ trợ TLS
PubSubClient client(espClient);
// ======================================================================================================
LiquidCrystal_I2C lcd(0x27,16,2);
int soil_moisture = 34;
int relay = 21;
int dht = 19;
DHTesp dht_sensor;
int photoresistor = 35;
// ======================================================================================================
// Kết nối WiFi
void wifiConnect() {
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConnected to WiFi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nFailed to connect to WiFi");
}
}
// Gửi phản hồi lên MQTT
void sendMQTTResponse(const char* topic, const char* message) {
if (client.publish(topic, message)) {
Serial.print("Message sent to topic ");
Serial.print(topic);
Serial.print(": ");
Serial.println(message);
} else {
Serial.println("Failed to send message.");
}
}
// Callback xử lý dữ liệu nhận được từ MQTT
void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.println(topic);
Serial.print("Message: ");
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println(message);
// Gửi phản hồi lại MQTT
if (String(topic) == subscribe_topic) {
sendMQTTResponse(topic, ("Received: " + message).c_str());
}
}
// Kết nối đến MQTT Broker
void mqttConnect() {
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP32Client", mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT");
client.subscribe(subscribe_topic); // Đăng ký lắng nghe topic
Serial.print("Subscribed to topic: ");
Serial.println(subscribe_topic);
} else {
Serial.print("Failed to connect. State: ");
Serial.println(client.state());
delay(2000);
}
}
}
// ======================================================================================================
// -- MOISTURE --
int get_percentage_soil_moisture(){
// Đọc giá trị từ cảm biến đất
int16_t i = analogRead(soil_moisture);
int percentage = map(i, 1680, 3620, 100, 0); // Chuyển đổi giá trị cảm biến thành % độ ẩm đất
return percentage;
}
void show_on_lcd(const char* name, int value, const char* unit = "%", int line = 0) {
// Xóa dòng hiện tại
lcd.setCursor(0, line); // Chọn dòng `line` (0: dòng đầu, 1: dòng thứ hai,...)
lcd.print(" "); // Xóa nội dung dòng hiện tại (16 khoảng trống)
// Hiển thị nội dung
lcd.setCursor(0, line); // Đặt lại con trỏ về đầu dòng
lcd.print(name);
lcd.print(": ");
lcd.print(value);
lcd.print(unit);
}
void check_soil_condition(int percentage, bool automatical = true) {
if(automatical) {
if(percentage <= 30) { // Dry
digitalWrite(relay, HIGH); // BUMP WATER
}
else { // OK - WET
digitalWrite(relay, LOW);
}
}
}
void process_soil_moisture(){
int moisture_percentage = get_percentage_soil_moisture();
show_on_lcd("Soil", moisture_percentage);
String msg = String(moisture_percentage) + "%";
sendMQTTResponse(response_topic_moisture, msg.c_str());
check_soil_condition(moisture_percentage);
}
// -- DHT --
void process_dht() {
float temperature = dht_sensor.getTemperature();
float humidity = dht_sensor.getHumidity();
// Kiểm tra lỗi
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Gửi dữ liệu
sendMQTTResponse(response_topic_temperature, String(temperature).c_str());
sendMQTTResponse(response_topic_humidity, String(humidity).c_str());
}
// PHOTORESISTOR
int get_percentage_light_level() {
int light_level = analogRead(photoresistor);
int percentage = map(light_level, 0, 4095, 0, 100);
if (percentage < 0) percentage = 0;
if (percentage > 100) percentage = 100;
// show_on_lcd("Light", percentage, "%", 1); // Hiển thị trên LCD
return percentage;
}
// Xử lý và gửi giá trị ánh sáng qua MQTT
void process_photoresistor() {
int light_percentage = get_percentage_light_level();
// Gửi giá trị qua MQTT
sendMQTTResponse(response_topic_photoresistor, String(light_percentage).c_str());
}
// ======================================================================================================
void setup() {
Serial.begin(115200);
// Kết nối WiFi
Serial.print("Connecting to WiFi...");
wifiConnect();
// Cấu hình TLS cho MQTT
espClient.setInsecure(); // Cho phép kết nối không cần chứng chỉ CA
// Cấu hình MQTT
client.setServer(mqtt_broker, mqtt_port);
client.setCallback(mqttCallback);
// Kết nối MQTT
mqttConnect();
// ------------------------------------------------------------------------
// Khởi tạo LCD
Wire.begin(23, 22);
lcd.init();
lcd.backlight();
// Relay - Bump water
pinMode(relay, OUTPUT);
digitalWrite(relay, LOW);
// DHT22
dht_sensor.setup(dht, DHTesp::DHT22);
// Pir motion sensor
pinMode(photoresistor, INPUT);
}
void loop() {
if (!client.connected()) {
mqttConnect();
}
client.loop(); // Duy trì kết nối MQTT
// Soil moisture
process_soil_moisture();
// DHT
process_dht();
// Photoresistor
process_photoresistor();
delay(1500);
}