IoTLabs

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

Series ESP32 & Cảm biến: Bài 36 – Đọc cảm biến PZEM-004T: đo điện năng AC & theo dõi realtime

PZEM-004T là module đo điện năng AC phổ biến trong các dự án IoT giám sát điện: nhà ở, phòng máy, tủ điện, xưởng nhỏ…

Module này đo được điện áp, dòng điện, công suất và điện năng tiêu thụ (kWh), rất phù hợp để đẩy lên IoTLabs Cloud MQTT theo dõi realtime.

1) PZEM-004T đo được gì?

PZEM-004T (v3) cung cấp các thông số:

  • Voltage (V) – điện áp AC
  • Current (A) – dòng điện
  • Power (W) – công suất tức thời
  • Energy (kWh) – điện năng tiêu thụ tích luỹ
  • Frequency (Hz) (tuỳ firmware)
  • Power Factor (tuỳ firmware)

👉 Ưu điểm lớn:

  • Không cần hiệu chuẩn phức tạp
  • Giao tiếp UART (Modbus RTU) ổn định
  • Dữ liệu rất “đáng tin” cho IoT thực tế

2) ⚠️ Lưu ý an toàn (rất quan trọng)

  • PZEM-004T làm việc với điện AC 220V
  • Chỉ đấu dây khi đã ngắt nguồn điện
  • Không chạm tay vào mạch khi đang cấp điện
  • Nên đặt module trong hộp cách điện

ESP32 chỉ giao tiếp UART mức thấp, phần điện nguy hiểm nằm ở PZEM + tải AC, không liên quan trực tiếp ESP32.

3) Chuẩn bị phần cứng

  • ESP32 (DevKit / ESP32-C3/S3)
  • PZEM-004T v3
  • Biến dòng CT đi kèm (100A / 20A tuỳ loại)
  • Dây jumper
  • Nguồn AC 220V (để test)

4) Nối dây ESP32 ↔ PZEM-004T (UART)

PZEM-004T v3 dùng UART TTL.

PZEM-004TESP32
VCC5V
GNDGND
TXGPIO16 (RX2)
RXGPIO17 (TX2)

📌 ESP32 dùng UART2 để tránh xung đột Serial debug.

5) Cài thư viện cần thiết

Trong Arduino IDE → Library Manager:

  • PZEM004Tv30 (by Mandulaj)

Thư viện này xử lý sẵn Modbus, rất tiện.

6) Code ESP32 đọc PZEM-004T & publish MQTT realtime

Ví dụ dưới đây:

  • Đọc đầy đủ thông số điện
  • Gửi telemetry lên IoTLabs Cloud MQTT
  • Chu kỳ 2 giây (phù hợp realtime)
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <PZEM004Tv30.h>

#define PZEM_RX 16
#define PZEM_TX 17
#define PUBLISH_EVERY_MS 2000

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

// MQTT
const char* MQTT_HOST = "broker.iotlabs.vn";
const int   MQTT_PORT = 1883;
const char* MQTT_USER = "YOUR_USER";
const char* MQTT_PASS = "YOUR_PASS";

const char* PROJECT_ID = "demo_project";
const char* DEVICE_ID  = "esp32_pzem004t_01";

WiFiClient espClient;
PubSubClient mqtt(espClient);

PZEM004Tv30 pzem(Serial2, PZEM_RX, PZEM_TX);

unsigned long lastPub = 0;

uint32_t nowSeconds() {
  return millis() / 1000;
}

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

void mqttConnect() {
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  while (!mqtt.connected()) {
    mqtt.connect(DEVICE_ID, MQTT_USER, MQTT_PASS);
    delay(500);
  }
}

void publishTelemetry(float v, float i, float p, float e) {
  String topic = String("iotlabs/") + PROJECT_ID + "/" + DEVICE_ID + "/telemetry";

  StaticJsonDocument<256> doc;
  doc["ts"] = nowSeconds();

  JsonObject metrics = doc.createNestedObject("metrics");
  metrics["voltage"] = v;
  metrics["current"] = i;
  metrics["power"]   = p;
  metrics["energy"]  = e;

  char payload[256];
  serializeJson(doc, payload);

  mqtt.publish(topic.c_str(), payload);
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, PZEM_RX, PZEM_TX);

  wifiConnect();
  mqttConnect();
}

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

  if (millis() - lastPub >= PUBLISH_EVERY_MS) {
    lastPub = millis();

    float voltage = pzem.voltage();
    float current = pzem.current();
    float power   = pzem.power();
    float energy  = pzem.energy();

    if (!isnan(voltage)) {
      Serial.printf("V: %.1fV | I: %.2fA | P: %.1fW | E: %.3fkWh\n",
        voltage, current, power, energy
      );

      publishTelemetry(voltage, current, power, energy);
    }
  }
}

7) Dashboard realtime (IoTLabs Cloud MQTT)

Card hiển thị:

  • Voltage (V)
  • Current (A)
  • Power (W)
  • Energy (kWh – tích luỹ)

Chart:

  • Power theo thời gian (1h / 24h)
  • Energy tăng dần (daily / monthly)

Rule cảnh báo gợi ý:

  • Công suất > ngưỡng X trong 10s → cảnh báo quá tải
  • Điện áp < 200V hoặc > 240V → cảnh báo nguồn không ổn định

8) Use case thực tế

  • Giám sát tủ điện nhà ở
  • Theo dõi thiết bị tiêu thụ lớn (máy lạnh, máy bơm)
  • Đếm điện theo phòng / theo ổ cắm
  • Làm nền cho billing / energy optimization

9) Khi nào nên nâng cấp?

  • Cần đo 3 pha → dùng PZEM-016 / PZEM-017
  • Cần độ chính xác cao hơn → công tơ Modbus công nghiệp
  • Cần lưu offline → kết hợp SD card + ACK MQTT