/****************************************************
* 📗 DỰ ÁN: TRẠM THỜI TIẾT MINI (WOKWI)
* ⚙️ PHẦN CỨNG: ESP32 + DHT22 + LDR + 2x POT + OLED
* ✨ Chức năng:
* - Đo: Nhiệt độ, Độ ẩm, Ánh sáng, Gió, Mưa
* - Giới hạn: Gió (0–20 m/s), Mưa (0–2000 mm)
* - Hiển thị OLED + Serial (chỉ 1 chữ số thập phân)
****************************************************/
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include "DHT.h" // Cảm biến DHT22 (nhiệt độ - độ ẩm)
// ================== KHAI BÁO CHÂN KẾT NỐI ==================
#define DHTPIN 15 // DATA của DHT22 → GPIO15
#define DHTTYPE DHT22
#define LDR_PIN 34 // AO của LDR → GPIO34
#define WIND_POT_PIN 35 // Biến trở mô phỏng gió → GPIO35
#define RAIN_POT_PIN 32 // Biến trở mô phỏng lượng mưa → GPIO32
// ================== CẤU HÌNH MÀN HÌNH OLED ==================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// ================== CẢM BIẾN DHT ==================
DHT dht(DHTPIN, DHTTYPE);
// ================== CÁC HÀM ĐỌC DỮ LIỆU ==================
// ☀️ Đọc cường độ ánh sáng (%)
float readLightPercent() {
int value = analogRead(LDR_PIN);
return map(value, 0, 4095, 100, 0);
}
// 💨 Đọc tốc độ gió (giới hạn 0–20 m/s)
float readWindSpeed() {
int value = analogRead(WIND_POT_PIN);
float wind = map(value, 0, 4095, 0, 200) / 10.0;
if (wind < 0) wind = 0;
if (wind > 20) wind = 20;
return wind;
}
// 🌧️ Đọc lượng mưa (giới hạn 0–2000 mm)
float readRainAmount() {
int value = analogRead(RAIN_POT_PIN);
float rain = map(value, 0, 4095, 0, 2000);
if (rain < 0) rain = 0;
if (rain > 2000) rain = 2000;
return rain;
}
// ================== THIẾT LẬP BAN ĐẦU ==================
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(LDR_PIN, INPUT);
pinMode(WIND_POT_PIN, INPUT);
pinMode(RAIN_POT_PIN, INPUT);
// OLED setup
Wire.begin(21, 22); // SDA = GPIO21, SCL = GPIO22
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
Serial.println("✅ Weather Station Initialized!");
}
// ================== HÀM CHÍNH ==================
void loop() {
// 1️⃣ Đọc dữ liệu cảm biến
float temp = dht.readTemperature();
float hum = dht.readHumidity();
float light = readLightPercent();
float wind = readWindSpeed();
float rain = readRainAmount();
// 2️⃣ Làm tròn 1 chữ số thập phân
temp = round(temp * 10) / 10.0;
hum = round(hum * 10) / 10.0;
light = round(light * 10) / 10.0;
wind = round(wind * 10) / 10.0;
rain = round(rain * 10) / 10.0;
// 3️⃣ Hiển thị lên OLED
display.clearDisplay();
display.setCursor(0, 0);
display.println("🌤️ Weather Station");
display.print("Temp: "); display.print(temp, 1); display.println(" °C");
display.print("Humi: "); display.print(hum, 1); display.println(" %");
display.print("Light: "); display.print(light, 1); display.println(" %");
display.print("Wind: "); display.print(wind, 1); display.println(" m/s");
display.print("Rain: "); display.print(rain, 1); display.println(" mm");
display.display();
// 4️⃣ In dữ liệu ra Serial Monitor
Serial.print("Temp="); Serial.print(temp, 1); Serial.print("°C, ");
Serial.print("Humi="); Serial.print(hum, 1); Serial.print("%, ");
Serial.print("Light="); Serial.print(light, 1); Serial.print("%, ");
Serial.print("Wind="); Serial.print(wind, 1); Serial.print("m/s, ");
Serial.print("Rain="); Serial.print(rain, 1); Serial.println("mm");
delay(1000); // Cập nhật mỗi giây
}