เนื้อหาในบทความ
📖 คำนำ
การวัดพลังงานไฟฟ้าที่แม่นยำเป็นสิ่งสำคัญสำหรับระบบ 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 Board | 1 | ฿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 หรือ PCB | 1 | ฿30-50 |
| สาย Jumper และ สายไฟ AC | 1 ชุด | ฿50 |
งบประมาณรวม: ประมาณ ฿400-700
🔌 การต่อสาย
ขั้นตอนการต่อสาย
📌 ขั้นตอนที่ 1: ต่อ Current Sensor (SCT-013)
- สายไฟ AC ที่ต้องการวัดผ่านห่วงของ SCT-013 (เฉพาะสาย Phase/เฟส ไม่ใช่ Neutral)
- SCT-013 จะสร้างกระแสไฟฟ้าสัมพันธ์กับกระแสหลัก (เช่น 100A → 50mA)
- ต่อขา SCT-013 เข้ากับ Burden Resistor และ ESP32 GPIO34 (ADC1_CH6)
📌 ขั้นตอนที่ 2: ต่อ Voltage Sensor (ZMPT101B)
- ต่อ ZMPT101B ข้ามระหว่าง Phase และ Neutral (เป็น Voltage Divider)
- สัญญาณ output จะเป็น AC ที่ลดระดับลงเหลือ ±5V
- ต่อเข้า 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. Current Calibration: เปิด Serial Monitor และเปรียบเทียบค่ากระแสกับมัลติมิเตอร์ แก้ไข
CURRENT_CALIBRATION - 2. Voltage Calibration: เปรียบเทียบค่าแรงดันกับมัลติมิเตอร์ แก้ไข
VOLTAGE_CALIBRATION - 3. Phase Calibration: เปรียบเทียบค่า Power Factor ที่ควรจะเป็น (โหลดตัวต้านทาน PF ≈ 1.0) แก้ไข phase_shift
🌐 เชื่อมต่อกับ CynoIoT Platform
ขั้นตอนการลงทะเบียนอุปกรณ์
- ไปที่ cynoiot.com และลงทะเบียนบัญชี (ฟรี)
- สร้าง Device ใหม่ ใน Dashboard
- คัดลอก API Key และ Device ID
- แก้ไขโค้ดในส่วน:
const char* CYNOIOT_API_KEY = "YOUR_CYNOIOT_API_KEY"; const char* CYNOIOT_DEVICE_ID = "YOUR_DEVICE_ID";
- อัปโหลดโค้ดและดูผลใน 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 แสดงการใช้พลังงาน
- กราฟย้อนหลังเพื่อวิเคราะห์การใช้งาน
- แจ้งเตือนเมื่อใช้พลังงานเกินกำหนด
- คำนวณค่าไฟฟ้าโดยประมาณ
🧪 การทดสอบ
การทดสอบเบื้องต้น
- อัปโหลดโค้ดไปยัง ESP32
- เปิด Serial Monitor (115200 baud)
- ตรวจสอบว่า WiFi เชื่อมต่อสำเร็จ
- เสียบ SCT-013 ไปที่สายไฟของอุปกรณ์ทดสอบ (เช่น หลอดไฟ 60W)
- ดูค่าที่แสดงใน Serial Monitor
- เปรียบเทียบกับมัลติมิเตอร์ (ถ้ามี)
- ตรวจสอบ 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