บทความ: สร้างระบบวัดพลังงานไฟฟ้าที่แม่นยำด้วย ESP32 True Power Monitor

เรียนรู้วิธีสร้างระบบวัดพลังงานไฟฟ้าที่คำนวณกำลังไฟฟ้าจริง (True Power) ด้วยการวัดทั้งแรงดันและกระแสพร้อมกัน พร้อมคำนวณ Power Factor และ Reactive Power แบบ Real-time

📅 22 มีนาคม 2026⏱️ 15 นาที🎯 ระดับกลาง🔌 ESP32, Energy Monitoring, Power Factor

📖 คำนำ

การวัดพลังงานไฟฟ้าที่แม่นยำเป็นสิ่งสำคัญสำหรับระบบ Smart Home และ IoT Monitoring ส่วนใหญ่ของระบบวัดพลังงานแบบง่าย จะวัดเพียงกระแสไฟฟ้าเท่านั้น ซึ่งให้ค่าประมาณที่ไม่แม่นยำ บทความนี้จะพาคุณไปสร้างระบบวัดพลังงานไฟฟ้าที่คำนวณ กำลังไฟฟ้าจริง (True Power) ด้วยการวัดทั้งแรงดันและกระแสไฟฟ้าพร้อมกัน

⚠️ คำเตือนความปลอดภัย

โปรเจกต์นี้ต้องการการต่อเข้ากับไฟฟ้ากระแสสลับ (AC) 220V/110V ซึ่งอันตรายถึงชีวิต หากคุณไม่มีประสบการณ์กับระบบไฟฟ้ากระแสสลับ ควรศึกษาและขอคำแนะนำจากช่างผู้เชี่ยวชาญก่อนดำเนินการ

ทำไมต้องวัด True Power?

  • Apparent Power (VA) = Voltage × Current (คำนวณง่ายแต่ไม่แม่นยำ)
  • True Power (Watts) = Voltage × Current × Power Factor (ค่าที่ใช้จริง)
  • อุปกรณ์บางชนิดมี Power Factor ต่ำ (เช่น มอเตอร์ พัดลม ท่อนำแสง LED) ทำให้ค่าที่วัดต่างจากจริงมาก
  • การวัด True Power ช่วยประหยัดค่าไฟและวางแผนการใช้พลังงานได้ดีขึ้น

📋 ข้อกำหนดเบื้องต้น

ความรู้พื้นฐานที่ต้องมี

  • พื้นฐานการเขียนโปรแกรม C/C++ สำหรับ Arduino
  • ความเข้าใจเรื่องไฟฟ้ากระแสสลับ (AC) ขั้นพื้นฐาน
  • ประสบการณ์ใช้งาน ESP32 มาก่อนจะดีมาก
  • ความรู้เรื่อง IoT และการส่งข้อมูลผ่าน MQTT/HTTP

ซอฟต์แวร์และเครื่องมือที่ต้องใช้

  • Arduino IDE หรือ PlatformIO
  • บัญชี CynoIoT (สมัครฟรีที่ cynoiot.com)
  • Library: EmonLib สำหรับการวัดพลังงาน
  • Library: WiFi, HTTPClient สำหรับ ESP32

📐 ทฤษฎีพลังงานไฟฟ้า

ประเภทของพลังงานไฟฟ้าในระบบ AC

สมการพื้นฐาน:

  • Apparent Power (S) = V × I (หน่วย: VA)
  • True Power (P) = V × I × cos(θ) (หน่วย: Watts)
  • Reactive Power (Q) = V × I × sin(θ) (หน่วย: VAR)
  • Power Factor (PF) = cos(θ) = P / S

โดย θ คือมุมเฟสระหว่างแรงดันและกระแส

ตัวอย่างเช่น:

พัดลมที่มี Power Factor = 0.7

  • แรงดัน: 220V
  • กระแส: 1A
  • Apparent Power: 220 × 1 = 220 VA
  • True Power: 220 × 1 × 0.7 = 154 Watts
  • ความแตกต่าง: 66 VA (29%)

🔧 อุปกรณ์ฮาร์ดแวร์

อุปกรณ์ที่ต้องใช้

อุปกรณ์จำนวนราคาโดยประมาณ
ESP32 Development Board1฿100-200
AC Voltage Sensor (ZMPT101B หรือ เทปขดลวดคูณ)1฿50-100
AC Current Sensor (SCT-013-000 100A)1฿150-300
Burden Resistor 33 Ω (ถ้า SCT-013 ไม่มีตัวต้านทาน)1฿5-10
Resistors 10k Ω, 220k Ω (สำหรับ Voltage Divider)4฿10
Capacitor 10µF (สำหรับกรองสัญญาณ)2฿5
Breadboard หรือ PCB1฿30-50
สาย Jumper และ สายไฟ AC1 ชุด฿50

งบประมาณรวม: ประมาณ ฿400-700

🔌 การต่อสาย

ขั้นตอนการต่อสาย

📌 ขั้นตอนที่ 1: ต่อ Current Sensor (SCT-013)

  1. สายไฟ AC ที่ต้องการวัดผ่านห่วงของ SCT-013 (เฉพาะสาย Phase/เฟส ไม่ใช่ Neutral)
  2. SCT-013 จะสร้างกระแสไฟฟ้าสัมพันธ์กับกระแสหลัก (เช่น 100A → 50mA)
  3. ต่อขา SCT-013 เข้ากับ Burden Resistor และ ESP32 GPIO34 (ADC1_CH6)

📌 ขั้นตอนที่ 2: ต่อ Voltage Sensor (ZMPT101B)

  1. ต่อ ZMPT101B ข้ามระหว่าง Phase และ Neutral (เป็น Voltage Divider)
  2. สัญญาณ output จะเป็น AC ที่ลดระดับลงเหลือ ±5V
  3. ต่อเข้า ESP32 GPIO35 (ADC1_CH7) ผ่าน Voltage Divider เพื่อลดให้อยู่ในช่วง 0-3.3V

⚠️ ข้อควรระวัง

  • • ตรวจสอบให้แน่ใจว่าไม่มีไฟฟ้าไหลผ่านขาที่จะต่อสาย
  • • ZMPT101B มีฉนวนกันไฟฟ้า (Opto-isolation) แต่ควรระมัดระวัง
  • • ใช้สายไฟที่มาตรฐานและขนาดพอเหมาะกับกระแสที่วัด
  • • ทดสอบกับโหลดขนาดเล็กก่อน เช่น หลอดไฟ 60W

แผนภาพการต่อสาย

SCT-013-000 (Current Sensor)
┌─────────────────┐
│   AC Phase      │
│   ┌───────┐     │
│   │       │     │
│   └───────┘     │
│      │          │
└──────┼──────────┘
       │
    [SCT-013]
    CT  │  │  CT
    ───┤  ├──
       │  │
       ├──┴───┐
       │       │
    [Burden 33Ω]
       │       │
       └───┬───┘
           │
      [To ESP32 GPIO34]
          (ADC1_CH6)


ZMPT101B (Voltage Sensor)
┌─────────────────┐
│   AC Phase ─────┼─────┐
│                 │     │
│              [ZMPT101B]
│                 │     │
│   AC Neutral ───┼─────┘
└─────────────────┘
                 │
            [Voltage Divider]
                 │
            [To ESP32 GPIO35]
                 (ADC1_CH7)
                                

💻 ซอฟต์แวร์และโค้ด

การติดตั้ง Library

เปิด Arduino IDE และติดตั้ง Library ผ่าน Library Manager:

  • ค้นหา "EmonLib" และติดตั้ง (โดย OpenEnergyMonitor)
  • Library อื่นที่ใช้งาน ESP32 จะถูกติดตั้งอัตโนมัติ

โค้ดสำหรับ ESP32 True Power Monitor

/*
 * ESP32 True Power Energy Monitor
 * วัดทั้งแรงดันและกระแสไฟฟ้าพร้อมกันเพื่อคำนวณ True Power
 * รองรับ CynoIoT Platform
 * 
 * Hardware:
 * - ESP32 Development Board
 * - SCT-013-000 Current Sensor (100A:50mA)
 * - ZMPT101B Voltage Sensor
 * - Burden Resistor 33Ω
 * 
 * Wiring:
 * - Current Sensor → GPIO34 (ADC1_CH6)
 * - Voltage Sensor → GPIO35 (ADC1_CH7)
 * 
 * อัปเดตล่าสุด: 22 มีนาคม 2026
 */

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "EmonLib.h"

// ============================
// ตั้งค่า WiFi
// ============================
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// ============================
// ตั้งค่า CynoIoT
// ============================
const char* CYNOIOT_API_KEY = "YOUR_CYNOIOT_API_KEY";
const char* CYNOIOT_DEVICE_ID = "YOUR_DEVICE_ID";
const char* CYNOIOT_ENDPOINT = "https://api.cynoiot.com/v1/telemetry";

// ============================
// ตั้งค่า Sensor
// ============================
const int CURRENT_SENSOR_PIN = 34;  // ADC1_CH6
const int VOLTAGE_SENSOR_PIN = 35;  // ADC1_CH7

// ค่า Calibration (แก้ไขตามอุปกรณ์ของคุณ)
const double CURRENT_CALIBRATION = 111.1;  // สำหรับ SCT-013-000 (100A:50mA + 33Ω burden)
const double VOLTAGE_CALIBRATION = 230.0;   // สำหรับ ZMPT101B (ปรับค่าได้)

// ค่า AC Voltage ที่ใช้จริง (ประเทศไทย 220-240V)
const double MAINS_VOLTAGE = 230.0;

// ============================
// ตั้งค่า Sampling
// ============================
const int SAMPLES = 1480;        // จำนวน samples ต่อการวัด
const int TIMEOUT = 2000;        // Timeout สำหรับ WiFi (ms)
const unsigned long SEND_INTERVAL = 5000;  // ส่งข้อมูลทุก 5 วินาที

// ============================
// สร้าง Object
// ============================
EnergyMonitor emon1;

// ============================
// ตัวแปร Global
// ============================
unsigned long lastSendTime = 0;
double currentRms = 0;
double voltageRms = 0;
double realPower = 0;
double apparentPower = 0;
double powerFactor = 0;
double reactivePower = 0;

void setup() {
  // เริ่ม Serial Monitor สำหรับ Debug
  Serial.begin(115200);
  delay(1000);
  Serial.println("\n\n=== ESP32 True Power Energy Monitor ===");
  Serial.println("เริ่มต้นระบบ...\n");

  // ตั้งค่า ADC ของ ESP32
  analogReadResolution(12);  // 12-bit resolution (0-4095)
  analogSetAttenuation(ADC_11db);  // เพิ่ม range เป็น 0-3.3V

  // ตั้งค่า Current Sensor
  emon1.current(CURRENT_SENSOR_PIN, CURRENT_CALIBRATION);

  // ตั้งค่า Voltage Sensor
  emon1.voltage(VOLTAGE_SENSOR_PIN, VOLTAGE_CALIBRATION, 1.7);  // phase_shift = 1.7

  Serial.println("✓ Sensor ถูกตั้งค่าแล้ว");

  // เริ่มเชื่อมต่อ WiFi
  connectWiFi();

  Serial.println("\n✓ พร้อมใช้งานแล้ว!\n");
}

void loop() {
  // ตรวจสอบสถานะ WiFi
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠ WiFi หลุดการเชื่อมต่อ กำลังเชื่อมต่อใหม่...");
    connectWiFi();
  }

  // วัดค่าพลังงาน
  measurePower();

  // แสดงผลใน Serial Monitor
  displayPowerData();

  // ส่งข้อมูลไป CynoIoT ทุก 5 วินาที
  if (millis() - lastSendTime >= SEND_INTERVAL) {
    sendToCynoIoT();
    lastSendTime = millis();
  }

  // รอ 1 วินาที
  delay(1000);
}

// ============================
// ฟังก์ชันเชื่อมต่อ WiFi
// ============================
void connectWiFi() {
  Serial.print("กำลังเชื่อมต่อ WiFi: ");
  Serial.println(WIFI_SSID);

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  unsigned long startAttemptTime = millis();

  while (WiFi.status() != WL_CONNECTED && 
         millis() - startAttemptTime < TIMEOUT) {
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n✓ WiFi เชื่อมต่อสำเร็จ!");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\n✗ WiFi เชื่อมต่อล้มเหลว!");
    Serial.println("จะลองเชื่อมต่อใหม่ใน loop...");
  }
}

// ============================
// ฟังก์ชันวัดพลังงาน
// ============================
void measurePower() {
  // คำนวณค่าทั้งหมดในครั้งเดียว
  emon1.calcVI(SAMPLES, 2000);  // 1480 samples, 2000ms timeout

  // รับค่าที่คำนวณได้
  currentRms = emon1.Irms;      // กระแส (Amps)
  voltageRms = emon1.Vrms;      // แรงดัน (Volts)
  realPower = emon1.realPower;  // กำลังไฟฟ้าจริง (Watts)
  apparentPower = emon1.apparentPower;  // กำลังไฟฟ้าปรากฏ (VA)
  powerFactor = emon1.powerFactor;      // Power Factor
  reactivePower = emon1.reactivePower;  // กำลังไฟฟ้าเชิงตอบสนอง (VAR)
}

// ============================
// ฟังก์ชันแสดงผล
// ============================
void displayPowerData() {
  Serial.println("─────────────────────────────");
  Serial.println("📊 ข้อมูลพลังงานไฟฟ้า:");
  Serial.println("─────────────────────────────");
  Serial.printf("แรงดัน: %.2f V\n", voltageRms);
  Serial.printf("กระแส: %.3f A\n", currentRms);
  Serial.printf("กำลังไฟฟ้าจริง: %.2f W\n", realPower);
  Serial.printf("กำลังไฟฟ้าปรากฏ: %.2f VA\n", apparentPower);
  Serial.printf("Power Factor: %.2f\n", powerFactor);
  Serial.printf("กำลังไฟฟ้าเชิงตอบสนอง: %.2f VAR\n", reactivePower);
  
  // คำนวณ Energy สะสม (kWh) จากค่าเฉลี่ย
  // หมายเหตุ: ในการใช้งานจริงควรเก็บค่าใน EEPROM หรือ Flash
  static double totalEnergy = 0;
  totalEnergy += (realPower / 1000.0) * (SEND_INTERVAL / 3600000.0);  // kWh
  Serial.printf("Energy สะสม: %.6f kWh\n", totalEnergy);
  Serial.println("─────────────────────────────\n");
}

// ============================
// ฟังก์ชันส่งข้อมูลไป CynoIoT
// ============================
void sendToCynoIoT() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠ ข้ามการส่งข้อมูล เนื่องจาก WiFi ไม่ได้เชื่อมต่อ");
    return;
  }

  Serial.println("📤 กำลังส่งข้อมูลไป CynoIoT...");

  // สร้าง JSON payload
  StaticJsonDocument<256> doc;
  doc["device_id"] = CYNOIOT_DEVICE_ID;
  doc["timestamp"] = millis();
  
  JsonObject data = doc.createNestedObject("data");
  data["voltage"] = round(voltageRms * 10) / 10.0;      // ทศนิยม 1 ตำแหน่ง
  data["current"] = round(currentRms * 100) / 100.0;    // ทศนิยม 2 ตำแหน่ง
  data["real_power"] = round(realPower * 10) / 10.0;    // ทศนิยม 1 ตำแหน่ง
  data["apparent_power"] = round(apparentPower * 10) / 10.0;
  data["power_factor"] = round(powerFactor * 100) / 100.0;
  data["reactive_power"] = round(reactivePower * 10) / 10.0;

  String jsonString;
  serializeJson(doc, jsonString);

  // ส่ง HTTP POST
  HTTPClient http;
  http.begin(CYNOIOT_ENDPOINT);
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Authorization", "Bearer " + String(CYNOIOT_API_KEY));

  int httpResponseCode = http.POST(jsonString);

  if (httpResponseCode > 0) {
    Serial.printf("✓ ส่งข้อมูลสำเร็จ! Response: %d\n", httpResponseCode);
    String response = http.getString();
    Serial.println("Response: " + response);
  } else {
    Serial.printf("✗ ส่งข้อมูลล้มเหลว! Error: %s\n", 
                  http.errorToString(httpResponseCode).c_str());
  }

  http.end();
}
                                

การแก้ไขค่า Calibration

🔧 ขั้นตอน Calibration

  1. 1. Current Calibration: เปิด Serial Monitor และเปรียบเทียบค่ากระแสกับมัลติมิเตอร์ แก้ไข CURRENT_CALIBRATION
  2. 2. Voltage Calibration: เปรียบเทียบค่าแรงดันกับมัลติมิเตอร์ แก้ไข VOLTAGE_CALIBRATION
  3. 3. Phase Calibration: เปรียบเทียบค่า Power Factor ที่ควรจะเป็น (โหลดตัวต้านทาน PF ≈ 1.0) แก้ไข phase_shift

🌐 เชื่อมต่อกับ CynoIoT Platform

ขั้นตอนการลงทะเบียนอุปกรณ์

  1. ไปที่ cynoiot.com และลงทะเบียนบัญชี (ฟรี)
  2. สร้าง Device ใหม่ ใน Dashboard
  3. คัดลอก API Key และ Device ID
  4. แก้ไขโค้ดในส่วน:
    const char* CYNOIOT_API_KEY = "YOUR_CYNOIOT_API_KEY";
    const char* CYNOIOT_DEVICE_ID = "YOUR_DEVICE_ID";
  5. อัปโหลดโค้ดและดูผลใน Dashboard

ข้อมูลที่ส่งไป CynoIoT

ระบบจะส่งข้อมูลทุก ๆ 5 วินาที:

  • Voltage: แรงดันไฟฟ้า (V)
  • Current: กระแสไฟฟ้า (A)
  • Real Power: กำลังไฟฟ้าจริง (W)
  • Apparent Power: กำลังไฟฟ้าปรากฏ (VA)
  • Power Factor: ตัวประกอบกำลังไฟฟ้า (0.0-1.0)
  • Reactive Power: กำลังไฟฟ้าเชิงตอบสนอง (VAR)

การสร้าง Dashboard

ใน CynoIoT Dashboard คุณสามารถสร้างกราฟและแสดงผล:

  • กราฟ Real-time แสดงการใช้พลังงาน
  • กราฟย้อนหลังเพื่อวิเคราะห์การใช้งาน
  • แจ้งเตือนเมื่อใช้พลังงานเกินกำหนด
  • คำนวณค่าไฟฟ้าโดยประมาณ

🧪 การทดสอบ

การทดสอบเบื้องต้น

  1. อัปโหลดโค้ดไปยัง ESP32
  2. เปิด Serial Monitor (115200 baud)
  3. ตรวจสอบว่า WiFi เชื่อมต่อสำเร็จ
  4. เสียบ SCT-013 ไปที่สายไฟของอุปกรณ์ทดสอบ (เช่น หลอดไฟ 60W)
  5. ดูค่าที่แสดงใน Serial Monitor
  6. เปรียบเทียบกับมัลติมิเตอร์ (ถ้ามี)
  7. ตรวจสอบ CynoIoT Dashboard ว่าได้รับข้อมูลหรือไม่

✓ ตัวอย่างผลลัพธ์ที่คาดหวัง

📊 ข้อมูลพลังงานไฟฟ้า:
─────────────────────────────
แรงดัน: 228.50 V
กระแส: 0.265 A
กำลังไฟฟ้าจริง: 58.42 W
กำลังไฟฟ้าปรากฏ: 60.55 VA
Power Factor: 0.96
กำลังไฟฟ้าเชิงตอบสนอง: 16.84 VAR
Energy สะสม: 0.000081 kWh
─────────────────────────────

🔧 การแก้ปัญหา

ปัญหาที่พบบ่อย

ปัญหา: ค่ากระแสอ่านได้ 0 A

สาเหตุ:

  • Burden Resistor ขาดหายหรือมีค่าไม่ถูกต้อง
  • สาย SCT-013 ต่อไม่ติด
  • Pin GPIO ผิด

วิธีแก้:

  • ตรวจสอบวงจรและ Burden Resistor
  • ลองเปลี่ยน Pin GPIO
  • ทดสอบกับมัลติมิเตอร์

ปัญหา: ค่า Power Factor ผิดปกติ (น้อยกว่า 0 หรือมากกว่า 1)

สาเหตุ:

  • Phase Shift ไม่ถูกต้อง
  • ตำแหน่ง Sensor ไม่เหมาะสม
  • สัญญาณรบกวน

วิธีแก้:

  • ปรับค่า phase_shift ใน emon1.voltage()
  • ทดสอบกับโหลดตัวต้านทาน (PF ≈ 1.0)
  • เพิ่ม Capacitor เพื่อกรองสัญญาณ

ปัญหา: ไม่สามารถเชื่อมต่อ WiFi ได้

สาเหตุ:

  • SSID หรือ Password ผิด
  • สัญญาณ WiFi อ่อน
  • ESP32 อยู่ในโหมดที่ไม่ถูกต้อง

วิธีแก้:

  • ตรวจสอบ SSID และ Password
  • ย้าย ESP32 ใกล้ Router ชั่วคราว
  • ตรวจสอบว่า ESP32 อยู่ในโหมด STA

ปัญหา: ส่งข้อมูลไป CynoIoT ไม่ได้

สาเหตุ:

  • API Key หรือ Device ID ผิด
  • อินเทอร์เน็ตไม่ได้เชื่อมต่อ
  • Endpoint URL ผิด

วิธีแก้:

  • ตรวจสอบ API Key และ Device ID ใหม่
  • ทดสอบอินเทอร์เน็ตด้วยการ ping
  • ตรวจสอบ Endpoint URL

🎯 สรุป

ในบทความนี้ เราได้เรียนรู้วิธีสร้างระบบวัดพลังงานไฟฟ้าที่คำนวณกำลังไฟฟ้าจริง (True Power) ด้วยการวัดทั้งแรงดันและกระแสไฟฟ้าพร้อมกัน ระบบนี้สามารถใช้งานได้จริงและแม่นยำกว่าการวัดเพียงกระแสเพียงอย่างเดียว

สิ่งที่เราได้เรียนรู้:

  • ทฤษฎีเรื่อง True Power, Apparent Power, และ Power Factor
  • การใช้งาน Current Sensor (SCT-013) และ Voltage Sensor (ZMPT101B)
  • การเขียนโค้ดสำหรับ ESP32 เพื่อวัดและคำนวณค่าต่าง ๆ
  • การเชื่อมต่อกับ CynoIoT Platform เพื่อแสดงผลและวิเคราะห์ข้อมูล

แนวคิดการพัฒนาต่อ:

  • เพิ่มหน่วยความจำ EEPROM หรือ Flash เพื่อเก็บข้อมูล Energy สะสม
  • สร้างระบบแจ้งเตือนเมื่อใช้พลังงานเกินกำหนด
  • เพิ่มจอ LCD/OLED เพื่อแสดงผลแบบ Real-time
  • วัดพลังงานหลายช่องทาง (Multi-channel)
  • คำนวณค่าไฟฟ้าโดยอัตโนมัติ

🎉 ขอบคุณที่อ่านจนจบ!

หวังว่าบทความนี้จะเป็นประโยชน์สำหรับโปรเจกต์ IoT ของคุณ
หากมีข้อสงสัยหรือต้องการคำแนะนำเพิ่มเติม สามารถติดต่อเราได้ที่ CynoIoT Contact