Dự án đo nhiệt độ, độ ẩm và áp suất khí quyển, định kỳ gửi lên MQTT broker (ví dụ Mosquitto trong Home Assistant). Giữa các lần đo ESP32 ngủ sâu để tiết kiệm pin.
Linh kiện
- Board ESP32 DevKit (30 hoặc 38 chân đều được)
- Module cảm biến BME280 (I2C). Lưu ý: chip BMP280 không có độ ẩm, hãy kiểm tra kỹ khi mua.
- Dây cắm, breadboard; pin Li-ion 18650 + mạch sạc nếu chạy pin
Sơ đồ nối dây
| BME280 | ESP32 |
|---|---|
| VIN / VCC | 3V3 |
| GND | GND |
| SDA | GPIO21 |
| SCL | GPIO22 |
Địa chỉ I2C thường là 0x76 (hoặc 0x77 tùy module). Nếu cảm biến không được nhận, hãy chạy thử sketch I2C scanner.
Thư viện cần cài (Arduino IDE)
Adafruit BME280 Library(kèm Adafruit Unified Sensor)PubSubClientcủa Nick O'Leary
Mã nguồn
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
const char* WIFI_SSID = "ten_wifi";
const char* WIFI_PASS = "mat_khau";
const char* MQTT_HOST = "192.168.1.10";
const uint16_t MQTT_PORT = 1883;
const char* TOPIC = "esp32diy/tram1";
const uint64_t SLEEP_US = 5ULL * 60ULL * 1000000ULL; // 5 phút
Adafruit_BME280 bme;
WiFiClient net;
PubSubClient mqtt(net);
void goSleep() {
WiFi.disconnect(true);
esp_sleep_enable_timer_wakeup(SLEEP_US);
esp_deep_sleep_start();
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
if (!bme.begin(0x76)) {
Serial.println("Khong thay BME280!");
goSleep();
}
// Chế độ "forced": đo 1 lần rồi tự về sleep, ít tốn điện
bme.setSampling(Adafruit_BME280::MODE_FORCED);
bme.takeForcedMeasurement();
float t = bme.readTemperature();
float h = bme.readHumidity();
float p = bme.readPressure() / 100.0F;
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
uint32_t t0 = millis();
while (WiFi.status() != WL_CONNECTED && millis() - t0 < 15000) delay(100);
if (WiFi.status() != WL_CONNECTED) goSleep();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
if (mqtt.connect("esp32diy-tram1")) { // thêm user/pass nếu broker yêu cầu
char buf[32];
snprintf(buf, sizeof buf, "%.2f", t); mqtt.publish("esp32diy/tram1/nhiet_do", buf, true);
snprintf(buf, sizeof buf, "%.2f", h); mqtt.publish("esp32diy/tram1/do_am", buf, true);
snprintf(buf, sizeof buf, "%.1f", p); mqtt.publish("esp32diy/tram1/ap_suat", buf, true);
mqtt.loop();
delay(100); // cho gói tin kịp gửi đi
}
goSleep();
}
void loop() {} // không bao giờ chạy tới đây
Khai báo trong Home Assistant
Thêm vào configuration.yaml (cần đã cài tích hợp MQTT):
mqtt:
sensor:
- name: "Nhiệt độ ngoài trời"
state_topic: "esp32diy/tram1/nhiet_do"
unit_of_measurement: "°C"
device_class: temperature
- name: "Độ ẩm ngoài trời"
state_topic: "esp32diy/tram1/do_am"
unit_of_measurement: "%"
device_class: humidity
- name: "Áp suất"
state_topic: "esp32diy/tram1/ap_suat"
unit_of_measurement: "hPa"
device_class: atmospheric_pressure
Mẹo: publish với cờ
retain = true để Home Assistant luôn có giá trị gần nhất khi khởi động lại, không phải đợi 5 phút.Cải tiến tiếp theo
- Đọc điện áp pin qua ADC (cầu chia 2 điện trở) và gửi cùng dữ liệu. Xem bài Deep sleep và GPIO cần tránh.
- Dùng IP tĩnh hoặc lưu kênh WiFi/BSSID vào RTC memory để kết nối nhanh hơn, giảm thời gian thức.
- Chuyển sang ESPHome nếu muốn bỏ hẳn phần code C++.