#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32TimerInterrupt.h>
// Định nghĩa các tham số màn hình OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Định nghĩa chân cảm biến và thiết bị
const int DHT_PIN = 15;
const int DHT_TYPE = DHT22;
const int photoresistorPin = 33;
const int trigPin = 5;
const int echoPin = 18;
const int Pump = 16;
const int LED = 12;
// Định nghĩa chân nút bấm và relay
const int buttonTempPin = 26;
const int buttonHumidPin = 27;
const int buttonPin3 = 14;
const int buttonPumpPin = 25; // Nút bấm điều khiển Pump
const int buttonModePin = 32; // Chân nút bấm mới
const int nhiet_do = 23;
const int do_am = 19;
const int anh_sang = 17;
float nguonganhsang = 1000;
float nguongnuoc = 50;
float chieucaobe = 100; // Chiều cao bể chứa
volatile bool TempState1 = false;
volatile bool HumidState2 = false;
volatile bool LightState3 = false;
volatile bool PumpState = false; // Trạng thái của bơm
volatile bool ModeState = false; // Biến để lưu trạng thái
DHT dht(DHT_PIN, DHT_TYPE);
// Khai báo thông tin MQTT
#define MQTT_CLIENT_ID "clientidweather"
#define MQTT_BROKER "mqtt-dashboard.com"
#define MQTT_TOPIC "dht22oled"
#define MQTT_TOPICDK "dht22oleddk"
const char* ssid = "Wokwi-GUEST";
const char* password = "";
WiFiClient espClient;
PubSubClient client(espClient);
// Hàm kết nối WiFi
void connectWiFi()
{
Serial.print("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" Connected!");
}
// Hàm kết nối lại MQTT
void reconnectMQTT()
{
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect(MQTT_CLIENT_ID)) {
Serial.println(" Connected!");
client.subscribe(MQTT_TOPICDK);
} else {
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// Hàm gửi dữ liệu lên MQTT
void sendToMQTT(float temperature, float humidity, float distanceCm, float lux) {
String payload = "{\"temperature\":" + String(temperature) +
",\"humidity\":" + String(humidity) +
",\"waterLevel\":" + String(chieucaobe - distanceCm) +
",\"lightIntensity\":" + String(lux) +
",\"nhiet_do\":" + (TempState1 ? "1" : "0") +
",\"do_am\":" + (HumidState2 ? "1" : "0") +
",\"anh_sang\":" + (LightState3 ? "1" : "0") +
",\"MODE\":" + (ModeState ? "AUTO" : "THUCONG") +
",\"pump\":" + (PumpState ? "1" : "0") + "}";
client.publish(MQTT_TOPIC, payload.c_str());
}
// Hàm điều khiển relay dựa trên dữ liệu nhận được
void controlRelay(char* message) {
if (strcmp(message, "TEMP_ON") == 0) {
TempState1 = true;
digitalWrite(nhiet_do, HIGH);
} else if (strcmp(message, "TEMP_OFF") == 0) {
TempState1 = false;
digitalWrite(nhiet_do, LOW);
} else if (strcmp(message, "HUMID_ON") == 0) {
HumidState2 = true;
digitalWrite(do_am, HIGH);
} else if (strcmp(message, "HUMID_OFF") == 0) {
HumidState2 = false;
digitalWrite(do_am, LOW);
} else if (strcmp(message, "LIGH_ON") == 0) {
LightState3 = true;
digitalWrite(anh_sang, HIGH);
} else if (strcmp(message, "LIGH_OFF") == 0) {
LightState3 = false;
digitalWrite(anh_sang, LOW);
} else if (strcmp(message, "PUMP_ON") == 0) {
PumpState = true;
digitalWrite(Pump, HIGH);
} else if (strcmp(message, "PUMP_OFF") == 0) {
PumpState = false;
digitalWrite(Pump, LOW);
} else if (strcmp(message, "mode_auto") == 0) {
ModeState = true;
digitalWrite(LED, HIGH);
} else if (strcmp(message, "mode_thucong") == 0) {
ModeState = false;
digitalWrite(LED, LOW);
}
}
// Hàm xử lý tin nhắn MQTT
void mqttCallback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.println((char*)payload);
controlRelay((char*)payload);
}
// Ngắt ngoài để điều khiển relay
void IRAM_ATTR button1Interrupt() {
TempState1 = !TempState1;
digitalWrite(nhiet_do, TempState1 ? HIGH : LOW);
}
void IRAM_ATTR button2Interrupt() {
HumidState2 = !HumidState2;
digitalWrite(do_am, HumidState2 ? HIGH : LOW);
}
void IRAM_ATTR button3Interrupt() {
LightState3 = !LightState3;
digitalWrite(anh_sang, LightState3 ? HIGH : LOW);
}
// Ngắt ngoài để điều khiển bơm
void IRAM_ATTR buttonPumpInterrupt() {
PumpState = !PumpState;
digitalWrite(Pump, PumpState ? HIGH : LOW);
}
void IRAM_ATTR buttonModeInterrupt() {
ModeState = !ModeState;
digitalWrite(LED, ModeState ? HIGH : LOW);
}
// Khởi tạo các cảm biến và thiết bị
void setup() {
Serial.begin(115200);
pinMode(photoresistorPin, INPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(Pump, OUTPUT);
pinMode(LED, OUTPUT);
pinMode(buttonTempPin, INPUT_PULLUP);
pinMode(buttonHumidPin, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(buttonModePin, INPUT_PULLUP);
pinMode(buttonPumpPin, INPUT_PULLUP);
pinMode(nhiet_do, OUTPUT);
pinMode(do_am, OUTPUT);
pinMode(anh_sang, OUTPUT);
dht.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Không tìm thấy màn hình OLED!"));
while (true);
}
display.clearDisplay();
display.display();
// Kết nối WiFi và MQTT
connectWiFi();
client.setServer(MQTT_BROKER, 1883);
client.setCallback(mqttCallback);
// Thiết lập ngắt ngoài cho nút bấm
attachInterrupt(digitalPinToInterrupt(buttonTempPin), button1Interrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonHumidPin), button2Interrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonPin3), button3Interrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonPumpPin), buttonPumpInterrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonModePin), buttonModeInterrupt, FALLING);
}
// Hàm đọc nhiệt độ và độ ẩm
void readTemperatureAndControlLED(float &temp, float &humid) {
temp = dht.readTemperature();
humid = dht.readHumidity();
if (isnan(temp) || isnan(humid)) {
Serial.println("Không đọc được nhiệt độ và độ ẩm!");
return;
}
Serial.print("Nhiet do: ");
Serial.print(temp);
Serial.println(" °C");
Serial.print("Do am: ");
Serial.print(humid);
Serial.println(" %");
if(ModeState){
digitalWrite(nhiet_do, (temp < 12 || temp > 35) ? HIGH : LOW);
digitalWrite(do_am, (humid < 40 || humid > 70) ? HIGH : LOW);
}
}
// Hàm đọc cường độ ánh sáng và điều khiển LED
void readLightAndControlLED(float &lux) {
int lightIntensity = analogRead(photoresistorPin);
float voltage = lightIntensity / 4096.0 * 3.3;
float resistance = 2000 * voltage / (1 - voltage / 3.3);
lux = pow(33 * 1e3 * pow(10, 0.7) / resistance, (1 / 0.7));
Serial.print("Cuong do anh sang: ");
Serial.print(lux);
Serial.println(" lux");
if(ModeState){
digitalWrite(anh_sang, (lux < nguonganhsang) ? HIGH : LOW);
}
}
// Hàm đọc khoảng cách và điều khiển bơm
void readDistanceAndControlPump(float &distanceCm) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
distanceCm = duration * 0.034 / 2;
Serial.print("Muc nuoc: ");
Serial.print(chieucaobe-distanceCm);
Serial.println(" cm");
if(ModeState){
if (distanceCm > nguongnuoc) {
digitalWrite(Pump, HIGH);
} else if (distanceCm < 20) {
digitalWrite(Pump, LOW);
}
}
}
// Hàm hiển thị dữ liệu lên OLED
void displayData(float temp, float humid, float lux, float distanceCm) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Nhiet do: ");
display.print(temp);
display.println(" C");
display.print("Do am: ");
display.print(humid);
display.println(" %");
display.print("Cuong do: ");
display.print(lux);
display.println(" lux");
display.print("Muc nuoc: ");
display.print(chieucaobe - distanceCm);
display.println(" cm");
display.print("Mode: ");
display.println( ModeState ? "Auto" : "thucong");
display.print("Relay1: ");
display.println(TempState1 ? "ON" : "OFF");
display.print("Relay2: ");
display.println(HumidState2 ? "ON" : "OFF");
display.print("Relay3: ");
display.println(LightState3 ? "ON" : "OFF");
display.print("Pump: ");
display.println( PumpState ? "ON" : "OFF");
display.display();
}
// Vòng lặp chính
void loop() {
float temp, humid, lux, distanceCm;
readTemperatureAndControlLED(temp, humid);
readLightAndControlLED(lux);
readDistanceAndControlPump(distanceCm);
// Gửi dữ liệu lên MQTT
sendToMQTT(temp, humid, distanceCm, lux); // Gửi tất cả dữ liệu cảm biến
displayData(temp, humid, lux, distanceCm); // Hiển thị dữ liệu lên màn hình OLED
if (!client.connected()) {
reconnectMQTT();
}
client.loop(); // Gọi hàm xử lý MQTT
//delay(2000);
}