#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// LCD I2C 20x4
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Pin định nghĩa
#define BUZZER_PIN 23
#define LDR_PIN 34
#define LED1 25
#define LED2 26
#define LED3 27
// Tham số tính lux từ LDR
const float GAMMA = 0.7;
const float RL10 = 33;
// Thông tin mạng
const char *ssid = "Wokwi-GUEST";
const char *password = "";
const char *mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char *MQTT_ID = "c7ec4eb6-e077-4a6d-8f82-39fde3f2f840";
// Topic MQTT
const char *topic_led = "topic_led";
const char *topic_lcd = "topic_lcd";
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
// ===== Hàm cập nhật LCD trạng thái WiFi & MQTT =====
void updateLCDStatus(const char* wifiStatus, const char* mqttStatus) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi: ");
lcd.print(wifiStatus);
lcd.setCursor(0, 1);
lcd.print("MQTT: ");
lcd.print(mqttStatus);
}
// ===== Kết nối WiFi =====
void setup_wifi() {
delay(10);
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected. IP: ");
Serial.println(WiFi.localIP());
updateLCDStatus("Connected", "Waiting...");
}
// ===== Kết nối lại MQTT =====
void reconnect() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect(MQTT_ID)) {
Serial.println(" connected.");
updateLCDStatus("Connected", "Connected");
client.subscribe(topic_led);
client.subscribe(topic_lcd);
} else {
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" try again...");
updateLCDStatus("Connected", "Retry...");
delay(1000);
}
}
}
// ===== Xử lý tin nhắn MQTT =====
void callback(char *topic, byte *payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
message.trim();
Serial.printf("Topic: %s | Message: %s\n", topic, message.c_str());
if (strcmp(topic, topic_led) == 0) {
if (message == "1") {
digitalWrite(LED1, HIGH); digitalWrite(LED2, LOW); digitalWrite(LED3, LOW);
} else if (message == "2") {
digitalWrite(LED1, LOW); digitalWrite(LED2, HIGH); digitalWrite(LED3, LOW);
} else if (message == "3") {
digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); digitalWrite(LED3, HIGH);
} else if (message == "0") {
digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); digitalWrite(LED3, LOW);
}
}
if (strcmp(topic, topic_lcd) == 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Message:");
lcd.setCursor(0, 1);
lcd.print(message);
}
}
// ===== Thiết lập =====
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
lcd.init();
lcd.backlight();
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
// ===== Vòng lặp =====
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
// Đọc giá trị ánh sáng từ LDR
int analogValue = analogRead(LDR_PIN);
float voltage = analogValue / 4096.0 * 3.3;
float resistance = 2000 * voltage / (1 - voltage / 3.3);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
// Hiển thị giá trị ánh sáng và trạng thái trên LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lux: ");
lcd.print(lux);
lcd.setCursor(0, 1);
if (lux < 10) {
lcd.print("Very dark");
} else if (lux >= 10 && lux < 50) {
lcd.print("Low light");
} else if (lux >= 50 && lux < 500) {
lcd.print("Dim light");
} else if (lux >= 500 && lux < 1000) {
lcd.print("Ambient light");
} else if (lux >= 1000 && lux < 10000) {
lcd.print("Strong light");
} else {
lcd.print("Very bright");
}
if (lux > 1000 ) {
lcd.noBacklight();
} else {
lcd.backlight();
}
// Bật còi nếu ánh sáng rất sáng (>10.000 lux)
if (lux > 10000) {
digitalWrite(BUZZER_PIN, HIGH);
} else {
digitalWrite(BUZZER_PIN, LOW);
}
// Gửi giá trị ánh sáng lên MQTT
String luxStr = String(lux, 2);
client.publish("anhsang", luxStr.c_str());
// In ra Serial Monitor
Serial.print("Lux: ");
Serial.println(lux);
}
}