Giám sát nhiệt độ và độ ẩm bằng ESP32 với MQTT

Giám sát nhiệt độ và độ ẩm bằng ESP32 với MQTT

Chỉ với một ESP32, vài cảm biến và MQTT, bạn đã có thể xây dựng một thiết bị giám sát hữu ích cho ngôi nhà, nhà kính hoặc hệ thống IoT nhỏ. Trong dự án này, ESP32 đọc nhiệt độ, độ ẩm không khí và độ ẩm đất, sau đó gửi các phép đo đến MQTT broker thông qua Wi-Fi.

Kiến trúc này có thể mở rộng thêm dashboard, cảnh báo, lưu trữ dữ liệu hoặc tưới cây tự động.

Chúng ta sẽ xây dựng gì?

Thiết bị sẽ:

  • Kết nối vào mạng Wi-Fi
  • Đọc nhiệt độ và độ ẩm không khí từ cảm biến DHT22
  • Đọc độ ẩm đất từ cảm biến điện dung analog
  • Gửi các phép đo dưới dạng JSON qua MQTT
  • Tự động kết nối lại khi Wi-Fi hoặc MQTT tạm thời bị mất

Dữ liệu sẽ được gửi đến topic:

1home/garden/esp32-01/telemetry

Ví dụ payload:

1{
2  "temperature": 27.4,
3  "humidity": 68.2,
4  "soil_moisture": 54
5}

Phần cứng

Bạn cần:

  • Bo mạch ESP32
  • Cảm biến nhiệt độ và độ ẩm DHT22 hoặc AM2302
  • Cảm biến độ ẩm đất điện dung có ngõ ra analog
  • Điện trở 10 kOhm nếu module DHT22 chưa có điện trở kéo lên
  • Dây nối và breadboard

Kết nối tham khảo

Linh kiệnESP32
DHT22 VCC3.3V
DHT22 GNDGND
DHT22 DATAGPIO 4
Cảm biến đất VCC3.3V
Cảm biến đất GNDGND
Cảm biến đất AOGPIO 34

GPIO 34 chỉ dùng làm input, phù hợp cho cảm biến analog trên nhiều bo ESP32. Hãy kiểm tra sơ đồ chân của đúng bo mạch bạn đang sử dụng trước khi đấu nối.

Kiến trúc MQTT

MQTT sử dụng mô hình publish/subscribe:

  1. ESP32 đóng vai trò MQTT publisher.
  2. Broker nhận dữ liệu telemetry.
  3. Dashboard, dịch vụ tự động hóa hoặc thiết bị khác subscribe vào topic.

Nhờ vậy firmware của cảm biến không phụ thuộc vào ứng dụng sử dụng dữ liệu. ESP32 không cần biết dữ liệu được hiển thị bằng Node-RED, Home Assistant hay backend tự xây dựng.

Khi phát triển ở local, bạn có thể dùng Mosquitto làm broker:

1mosquitto_sub -h localhost -t 'home/garden/esp32-01/telemetry' -v

Thư viện Arduino

Cài các thư viện sau từ Library Manager của Arduino IDE:

  • DHT sensor library
  • Adafruit Unified Sensor
  • PubSubClient
  • ArduinoJson

Thư viện Wi-Fi cho ESP32 đã có sẵn trong ESP32 Arduino core.

Mã nguồn ví dụ cho ESP32

Sketch sau đọc cảm biến mỗi 30 giây và gửi một JSON payload:

 1#include <ArduinoJson.h>
 2#include <DHT.h>
 3#include <PubSubClient.h>
 4#include <WiFi.h>
 5
 6const char *WIFI_SSID = "your-wifi-ssid";
 7const char *WIFI_PASSWORD = "your-wifi-password";
 8const char *MQTT_HOST = "192.168.1.100";
 9const int MQTT_PORT = 1883;
10const char *MQTT_TOPIC = "home/garden/esp32-01/telemetry";
11
12constexpr uint8_t DHT_PIN = 4;
13constexpr uint8_t DHT_TYPE = DHT22;
14constexpr uint8_t SOIL_MOISTURE_PIN = 34;
15constexpr unsigned long PUBLISH_INTERVAL_MS = 30000;
16
17DHT dht(DHT_PIN, DHT_TYPE);
18WiFiClient wifiClient;
19PubSubClient mqttClient(wifiClient);
20unsigned long lastPublish = 0;
21
22void connectWiFi() {
23  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
24  while (WiFi.status() != WL_CONNECTED) {
25    delay(500);
26  }
27}
28
29void connectMQTT() {
30  while (!mqttClient.connected()) {
31    String clientId = "esp32-" + String((uint32_t)ESP.getEfuseMac(), HEX);
32    if (!mqttClient.connect(clientId.c_str())) {
33      delay(2000);
34    }
35  }
36}
37
38void publishTelemetry() {
39  const float temperature = dht.readTemperature();
40  const float humidity = dht.readHumidity();
41  const int soilRaw = analogRead(SOIL_MOISTURE_PIN);
42
43  if (isnan(temperature) || isnan(humidity)) {
44    return;
45  }
46
47  // Hãy hiệu chuẩn các giới hạn này theo cảm biến và ứng dụng thực tế.
48  const int soilMoisture = constrain(map(soilRaw, 3000, 1200, 0, 100), 0, 100);
49
50  StaticJsonDocument<192> document;
51  document["temperature"] = round(temperature * 10) / 10.0;
52  document["humidity"] = round(humidity * 10) / 10.0;
53  document["soil_moisture"] = soilMoisture;
54
55  char payload[192];
56  serializeJson(document, payload, sizeof(payload));
57  mqttClient.publish(MQTT_TOPIC, payload);
58}
59
60void setup() {
61  Serial.begin(115200);
62  dht.begin();
63  connectWiFi();
64  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
65}
66
67void loop() {
68  if (WiFi.status() != WL_CONNECTED) {
69    connectWiFi();
70  }
71
72  if (!mqttClient.connected()) {
73    connectMQTT();
74  }
75  mqttClient.loop();
76
77  if (millis() - lastPublish >= PUBLISH_INTERVAL_MS) {
78    lastPublish = millis();
79    publishTelemetry();
80  }
81}

Sketch này sử dụng ArduinoJson, vì vậy bạn cũng cần cài thư viện đó. Hãy thay thông tin Wi-Fi và địa chỉ broker trước khi upload chương trình.

Hiệu chuẩn cảm biến độ ẩm đất

Cảm biến đất analog không có sẵn một giá trị phần trăm dùng chung cho mọi trường hợp. Giá trị raw phụ thuộc vào cảm biến, loại đất, điện áp cấp và độ sâu cắm đầu dò.

Hãy ghi lại hai giá trị:

  1. Giá trị khi cảm biến nằm trong đất khô.
  2. Giá trị khi cảm biến nằm trong đất ướt.

Sau đó thay 30001200 trong hàm map() bằng giá trị đo được từ cảm biến của bạn. Hàm constrain() giữ phần trăm được gửi trong khoảng từ 0 đến 100.

Kiểm tra dữ liệu

Subscribe vào MQTT topic để xem message:

1mosquitto_sub -h 192.168.1.100 \
2  -t 'home/garden/esp32-01/telemetry' \
3  -v

Bạn sẽ nhận được một JSON message mới sau mỗi 30 giây. Nếu không thấy message, hãy kiểm tra Serial Monitor của ESP32, địa chỉ Wi-Fi, địa chỉ broker và firewall.

Một số cải tiến về độ tin cậy

Ví dụ này được viết ngắn gọn, nhưng thiết bị thực tế nên cân nhắc thêm:

  • Username và password cho MQTT
  • Mã hóa TLS khi dữ liệu đi qua mạng không tin cậy
  • Last-will và retained message
  • Gửi thông báo khi đọc cảm biến lỗi
  • Logic reconnect không block
  • Deep sleep nếu thiết bị dùng pin
  • MQTT client ID riêng cho từng thiết bị

Không nên đưa một MQTT broker không có xác thực trực tiếp lên internet công cộng.

Kết luận

Dự án này minh họa một mô hình IoT hữu ích: ESP32 phụ trách đọc cảm biến, MQTT phụ trách truyền dữ liệu, còn một dịch vụ khác phụ trách hiển thị hoặc tự động hóa.

Thiết kế đủ đơn giản cho dự án đầu tiên nhưng vẫn có thể mở rộng. Bạn có thể thêm cảm biến, gửi dữ liệu đến các topic riêng, subscribe lệnh điều khiển hoặc bật máy bơm khi độ ẩm đất giảm dưới một ngưỡng.

Ba việc quan trọng nhất là hiệu chuẩn cảm biến, xử lý reconnect và bảo mật kết nối MQTT trước khi triển khai trong môi trường thực tế.

Translations: