IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series ESP32 & Cảm biến: Bài 15 – Hướng dẫn đọc cảm biến SHT31: đo nhiệt độ/độ ẩm chất lượng cao & theo dõi realtime

Sau khi làm quen với AHT20, chúng ta tiếp tục nâng cấp lên SHT31 – cảm biến nhiệt độ/độ ẩm chất lượng cao, độ chính xác tốt và cực kỳ ổn định, rất phổ biến trong các hệ IoT nghiêm túc và thiết bị thương mại.

Bài này tập trung vào:

  • Làm việc với I2C sensor chất lượng cao
  • Đọc dữ liệu mượt – chính xác – ít nhiễu
  • Gửi dữ liệu realtime lên IoTLabs Cloud MQTT

1. Giới thiệu cảm biến SHT31

SHT31 là cảm biến của Sensirion (Thụy Sĩ), nổi tiếng về độ chính xác và độ ổn định.

Thông số nổi bật:

  • Giao tiếp: I2C
  • Nhiệt độ: -40 → 125°C
  • Độ ẩm: 0 → 100%
  • Độ chính xác: cao hơn AHT20
  • Địa chỉ I2C phổ biến: 0x44 hoặc 0x45

👉 Thường dùng trong:

  • Trạm thời tiết chất lượng cao
  • Smart home cao cấp
  • Thiết bị đo môi trường chạy 24/7

2. So sánh nhanh AHT20 và SHT31

Tiêu chíAHT20SHT31
Giao tiếpI2CI2C
Độ ổn địnhTốtRất cao
Độ chính xácTốtRất tốt
GiáHợp lýCao hơn
Dự ánDIY nghiêm túcGần production

👉 Nếu bạn cần độ tin cậy cao lâu dài, SHT31 là lựa chọn rất đáng tiền.

3. Chuẩn bị phần cứng & nối dây

Thiết bị

  • ESP32-C3 SuperMini
  • Cảm biến SHT31 (module I2C)

Kết nối I2C (chuẩn series)

SHT31ESP32-C3
VCC3.3V
GNDGND
SDAGPIO8
SCLGPIO9

4. Kiểm tra địa chỉ I2C

Trước khi đọc dữ liệu, luôn nên kiểm tra I2C.

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin(8, 9);
}

void loop() {
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found I2C device at 0x");
      Serial.println(addr, HEX);
    }
  }
  delay(5000);
}

👉 Nếu thấy 0x44 hoặc 0x45 → OK.

5. Ví dụ 1: Đọc SHT31 local (Serial)

Thư viện

  • Adafruit SHT31 Library

Code mẫu

#include <Wire.h>
#include <Adafruit_SHT31.h>

Adafruit_SHT31 sht31 = Adafruit_SHT31();

void setup() {
  Serial.begin(115200);
  Wire.begin(8, 9);

  if (!sht31.begin(0x44)) {
    Serial.println("SHT31 not found");
    while (1) delay(10);
  }
  Serial.println("SHT31 ready");
}

void loop() {
  float t = sht31.readTemperature();
  float h = sht31.readHumidity();

  if (!isnan(t) && !isnan(h)) {
    Serial.print("Temp: ");
    Serial.print(t, 1);
    Serial.print(" °C | Humidity: ");
    Serial.print(h, 1);
    Serial.println(" %");
  } else {
    Serial.println("Read error");
  }

  delay(2000);
}

📌 Dữ liệu từ SHT31 thường rất mượt, gần như không gặp NaN.

6. Chuẩn payload gửi IoTLabs Cloud

{
  "ts": 1760000000,
  "metrics": {
    "temperature": 26.4,
    "humidity": 61.8
  }
}

7. Ví dụ 2: Gửi dữ liệu SHT31 realtime qua MQTT

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_SHT31.h>

Adafruit_SHT31 sht31 = Adafruit_SHT31();

// ===== CONFIG =====
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_PASS";

const char* MQTT_HOST = "mqtt.iotlabs.vn";
const int MQTT_PORT = 8883;
const char* MQTT_USER = "YOUR_MQTT_USER";
const char* MQTT_PASS = "YOUR_MQTT_PASS";

const char* MQTT_TOPIC =
  "iotlabs/<orgId>/devices/<deviceId>/telemetry";

WiFiClientSecure net;
PubSubClient mqtt(net);

unsigned long lastSend = 0;

void connectWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
}

void connectMQTT() {
  net.setInsecure();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  while (!mqtt.connected()) {
    mqtt.connect("esp32c3-sht31", MQTT_USER, MQTT_PASS);
    delay(1000);
  }
}

void setup() {
  Serial.begin(115200);
  Wire.begin(8, 9);
  sht31.begin(0x44);

  connectWiFi();
  connectMQTT();
}

void loop() {
  if (!mqtt.connected()) connectMQTT();
  mqtt.loop();

  if (millis() - lastSend > 5000) {
    lastSend = millis();

    float t = sht31.readTemperature();
    float h = sht31.readHumidity();
    if (isnan(t) || isnan(h)) return;

    long ts = millis() / 1000;

    String payload = "{";
    payload += "\"ts\":" + String(ts) + ",";
    payload += "\"metrics\":{";
    payload += "\"temperature\":" + String(t, 1) + ",";
    payload += "\"humidity\":" + String(h, 1);
    payload += "}}";

    mqtt.publish(MQTT_TOPIC, payload.c_str());
    Serial.println(payload);
  }
}

8. Kinh nghiệm thực tế khi dùng SHT31

  • Đặt cảm biến xa ESP32 và nguồn
  • Không cần đọc nhanh (2–5s là lý tưởng)
  • Phù hợp cho thiết bị chạy dài ngày
  • Giá cao hơn nhưng đỡ debug về lâu dài

9. Tổng kết Bài 15

Sau bài này, bạn đã:

  • Làm việc với I2C sensor chất lượng cao
  • Đọc nhiệt độ/độ ẩm chính xác – ổn định
  • Gửi dữ liệu multi-metric realtime
  • Tiến rất gần tới chuẩn production IoT

👉 Bài tiếp theo:

Bài 16 – Hướng dẫn đọc cảm biến BMP280 bằng ESP32: đo áp suất/độ cao ước tính & theo dõi realtime