#include <DHT.h>
#include <ESP32Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <PubSubClient.h>
// Định nghĩa các tham số màn hình OLED
#define SCREEN_WIDTH 128 // Chiều rộng màn hình OLED
#define SCREEN_HEIGHT 64 // Chiều cao màn hình OLED
#define OLED_RESET -1 // Chân reset OLED (không sử dụng)
// Khởi tạo màn hình OLED
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 LED1 = 13;
const int LED2 = 25;
const int LED3 = 32;
const int photoresistorPin = 33;
const int trigPin = 5;
const int echoPin = 18;
const int pir = 19;
const int Buzzer = 12;
#define Pump 4
// Định nghĩa chân nút bấm và relay
const int buttonPin1 = 14;
const int buttonPin2 = 27;
const int buttonPin3 = 17;
const int relay1 = 2;
const int relay2 = 16;
const int relay3 = 23;
// Khởi tạo đối tượng Servo và DHT
Servo myServo; // Tạo đối tượng Servo
DHT dht(DHT_PIN, DHT_TYPE);
float nguonganhsang = 1000;
float nguongnuoc = 50;
float chieucaobe = 100; // Chiều cao bể chứa
// Biến lưu trạng thái của các relay
volatile bool relayState1 = false;
volatile bool relayState2 = false;
volatile bool relayState3 = false;
// Thời gian debounce
const unsigned long debounceDelay = 50; // Thời gian debounce (50 ms)
// Biến để theo dõi thời gian nhấn nút
unsigned long lastButtonPress1 = 0;
unsigned long lastButtonPress2 = 0;
unsigned long lastButtonPress3 = 0;
// Khai báo thông tin MQTT
#define MQTT_CLIENT_ID "clientidweather"
#define MQTT_BROKER "mqtt-dashboard.com"
#define MQTT_TOPIC "dht22oled" // Topic duy nhất
#define MQTT_TOPICDK "dht22oleddk"
// Thông tin mạng WiFi
const char* ssid = "Wokwi-GUEST"; // Thay bằng SSID của bạn
const char* password = ""; // Thay bằng mật khẩu WiFi của bạn
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!");
// Đăng ký topic điều khiển LED
client.subscribe(MQTT_TOPICDK); // Chỉ cần subscribe 1 topic
} 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, bool motionDetected) {
String payload = "{\"temperature\":" + String(temperature) +
",\"humidity\":" + String(humidity) +
",\"waterLevel\":" + String(chieucaobe - distanceCm) +
",\"lightIntensity\":" + String(lux) +
",\"motionDetected\":" + (motionDetected ? "1" : "0") +
",\"relay1\":" + (relayState1 ? "1" : "0") +
",\"relay2\":" + (relayState2 ? "1" : "0") +
",\"relay3\":" + (relayState3 ? "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, "RELAY1_ON") == 0) {
relayState1 = true;
digitalWrite(relay1, HIGH);
} else if (strcmp(message, "RELAY1_OFF") == 0) {
relayState1 = false;
digitalWrite(relay1, LOW);
} else if (strcmp(message, "RELAY2_ON") == 0) {
relayState2 = true;
digitalWrite(relay2, HIGH);
} else if (strcmp(message, "RELAY2_OFF") == 0) {
relayState2 = false;
digitalWrite(relay2, LOW);
} else if (strcmp(message, "RELAY3_ON") == 0) {
relayState3 = true;
digitalWrite(relay3, HIGH);
} else if (strcmp(message, "RELAY3_OFF") == 0) {
relayState3 = false;
digitalWrite(relay3, LOW);
}
}
// Hàm xử lý tin nhắn MQTT
void mqttCallback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0'; // Kết thúc chuỗi
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.println((char*)payload);
// Gọi hàm điều khiển relay tương ứng
controlRelay((char*)payload);
}
// Hàm khởi tạo các cảm biến và thiết bị
void setup() {
Serial.begin(115200); // Khởi tạo Serial Monitor
// Cấu hình các chân vào/ra
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(photoresistorPin, INPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(pir, INPUT);
pinMode(Buzzer, OUTPUT);
pinMode(Pump, OUTPUT);
// Cấu hình chân nút bấm và relay
pinMode(buttonPin1, INPUT_PULLUP); // Chế độ kéo lên
pinMode(buttonPin2, INPUT_PULLUP); // Chế độ kéo lên
pinMode(buttonPin3, INPUT_PULLUP); // Chế độ kéo lên
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
dht.begin(); // Khởi động cảm biến DHT22
myServo.attach(26); // Kết nối Servo với chân 26 (có thể thay đổi tùy vào cấu hình)
myServo.write(0);
// Khởi tạo màn hình OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Địa chỉ I2C mặc định 0x3C
Serial.println(F("Không tìm thấy màn hình OLED!"));
while (true); // Dừng chương trình nếu OLED không khởi tạo thành công
}
display.clearDisplay();
display.display();
// Kết nối WiFi
connectWiFi();
// Kết nối MQTT
client.setServer(MQTT_BROKER, 1883);
client.setCallback(mqttCallback);
}
// Hàm gộp đọ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(" %");
digitalWrite(LED3, (temp < 12 || temp > 35 || humid < 40 || humid > 70) ? HIGH : LOW);
}
// Hàm gộp đọc cường độ ánh sáng và điều khiển LED1, Servo
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");
digitalWrite(LED1, (lux < nguonganhsang) ? HIGH : LOW);
myServo.write(lux < nguonganhsang ? 180 : 0); // Mở hoặc đóng cửa sổ
}
// Hàm gộp đọc khoảng cách và điều khiển Pump, LED2
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; // Tính khoảng cách (cm)
Serial.print("Muc nuoc: ");
Serial.print(chieucaobe-distanceCm);
Serial.println(" cm");
if (distanceCm > nguongnuoc) {
digitalWrite(Pump, HIGH);
digitalWrite(LED2, HIGH);
} else if (distanceCm < 20) {
digitalWrite(Pump, LOW);
digitalWrite(LED2, LOW);
}
}
// Hàm gộp đọc chuyển động và điều khiển Buzzer
void readPIRAndControlBuzzer(bool &motionDetected) {
motionDetected = digitalRead(pir);
if (motionDetected) {
Serial.println("Phat hien chuyen dong!");
digitalWrite(Buzzer, HIGH);
} else {
digitalWrite(Buzzer, 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("Relay1: ");
display.println(relayState1 ? "ON" : "OFF");
display.print("Relay2: ");
display.println(relayState2 ? "ON" : "OFF");
display.print("Relay3: ");
display.println(relayState3 ? "ON" : "OFF");
display.display();
}
// Hàm loop chính
void loop() {
float temp, humid, lux, distanceCm;
bool motionDetected;
readTemperatureAndControlLED(temp, humid);
readLightAndControlLED(lux);
readDistanceAndControlPump(distanceCm);
readPIRAndControlBuzzer(motionDetected);
// Gửi dữ liệu lên MQTT
sendToMQTT(temp, humid, distanceCm, lux, motionDetected); // 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
// Kiểm tra trạng thái nút bấm
if (digitalRead(buttonPin1) == LOW) {
unsigned long currentMillis = millis();
if (currentMillis - lastButtonPress1 > debounceDelay) {
relayState1 = !relayState1;
digitalWrite(relay1, relayState1 ? HIGH : LOW);
lastButtonPress1 = currentMillis;
}
}
if (digitalRead(buttonPin2) == LOW) {
unsigned long currentMillis = millis();
if (currentMillis - lastButtonPress2 > debounceDelay) {
relayState2 = !relayState2;
digitalWrite(relay2, relayState2 ? HIGH : LOW);
lastButtonPress2 = currentMillis;
}
}
if (digitalRead(buttonPin3) == LOW) {
unsigned long currentMillis = millis();
if (currentMillis - lastButtonPress3 > debounceDelay) {
relayState3 = !relayState3;
digitalWrite(relay3, relayState3 ? HIGH : LOW);
lastButtonPress3 = currentMillis;
}
}
if (!client.connected()) {
reconnectMQTT();
}
client.loop(); // Gọi hàm xử lý MQTT
delay(100); // Thời gian trễ giữa các lần đọc
}