IoTLabs

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

Series ESP32 & Cảm biến: Bài 18 – Đọc cảm biến DS3231 (RTC): giữ thời gian chính xác & theo dõi realtime

Ở các bài trước, chúng ta đã gửi dữ liệu realtime lên IoTLabs Cloud.
Tuy nhiên, một câu hỏi rất quan trọng trong hệ IoT thực tế là:

Nếu mất mạng, reboot, hoặc chạy offline thì thời gian lấy ở đâu?

Câu trả lời chính là RTC – Real Time Clock, và DS3231 là lựa chọn ổn định – chính xác – phổ biến nhất cho ESP32.

1. Vì sao IoT cần RTC?

Trong hệ IoT thực tế, RTC giúp bạn:

  • Ghi timestamp chính xác khi:
    • Mất WiFi
    • MQTT chưa kết nối
    • Thiết bị reboot
  • Lưu log offline (SD / Flash)
  • Đồng bộ dữ liệu khi online trở lại
  • Giảm phụ thuộc vào NTP / Internet

👉 RTC là mảnh ghép bắt buộc khi IoT bước sang “production-ready”.

2. Giới thiệu cảm biến DS3231

DS3231 là RTC chất lượng cao, thường dùng trong:

  • Data logger
  • Thiết bị chạy lâu ngày
  • IoT offline / intermittent network

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

  • Giao tiếp: I2C
  • Độ chính xác cao (bù nhiệt)
  • Có pin CR2032 → giữ giờ khi mất điện
  • Địa chỉ I2C: 0x68

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

Thiết bị

  • ESP32-C3 SuperMini
  • Module DS3231 (RTC + pin)

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

DS3231ESP32-C3
VCC3.3 V
GNDGND
SDAGPIO8
SCLGPIO9

📌 DS3231 dùng chung bus I2C với các sensor khác (BME280, SHT31…).

4. Kiểm tra địa chỉ 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);
}

👉 Thấy 0x68 → DS3231 hoạt động.

5. Ví dụ 1: Đọc thời gian từ DS3231 (local)

Thư viện

  • RTClib (Adafruit)

Code mẫu

#include <Wire.h>
#include <RTClib.h>

RTC_DS3231 rtc;

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

  if (!rtc.begin()) {
    Serial.println("DS3231 not found");
    while (1) delay(10);
  }

  // Set time 1 lần (comment lại sau khi set)
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  DateTime now = rtc.now();

  Serial.print(now.year()); Serial.print("-");
  Serial.print(now.month()); Serial.print("-");
  Serial.print(now.day()); Serial.print(" ");
  Serial.print(now.hour()); Serial.print(":");
  Serial.print(now.minute()); Serial.print(":");
  Serial.println(now.second());

  delay(1000);
}

📌 Chỉ cần set thời gian 1 lần, sau đó RTC tự chạy bằng pin.

6. Chuẩn timestamp dùng trong IoTLabs Cloud

IoTLabs Cloud dùng Unix timestamp (seconds):

{
  "ts": 1760000000,
  "metrics": {
    "temperature": 26.8
  }
}

👉 ts lấy trực tiếp từ DS3231, không phụ thuộc millis() hay NTP.

7. Ví dụ 2: Gửi timestamp RTC lên IoTLabs Cloud MQTT

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

RTC_DS3231 rtc;

// ===== 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-ds3231", MQTT_USER, MQTT_PASS);
    delay(1000);
  }
}

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

  connectWiFi();
  connectMQTT();
}

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

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

    DateTime now = rtc.now();
    long ts = now.unixtime();

    String payload = "{";
    payload += "\"ts\":" + String(ts) + ",";
    payload += "\"metrics\":{";
    payload += "\"rtc\":1";
    payload += "}}";

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

8. RTC + IoT = tư duy hệ thống

Khi kết hợp DS3231 với các sensor khác, bạn có thể:

  • Ghi log offline → sync khi online
  • Gửi dữ liệu đúng timestamp
  • Debug dễ hơn (biết chính xác lúc xảy ra sự kiện)
  • Xây hệ store-and-forward chuẩn bài

👉 Đây là bước chuyển từ DIY → hệ IoT đúng nghĩa.

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

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

  • Làm chủ RTC DS3231
  • Tạo timestamp độc lập Internet
  • Hoàn thiện tư duy I2C + multi-sensor + time
  • Sẵn sàng bước sang Level 3 – hệ thống IoT thực tế

👉 Tiếp theo: Tổng kết Level 2 – I2C & tư duy hệ thống IoT