Pengertian tentang pzem DC 017
PZEM DC (Power & Energy Meter DC) adalah sebuah alat pengukur listrik yang dirancang khusus untuk mengukur parameter listrik arus searah (DC). Alat ini biasanya digunakan dalam sistem tenaga surya (solar panel), baterai, kendaraan listrik, dan aplikasi lain yang menggunakan listrik DC.
Fitur Utama PZEM DC:
- Pengukuran Parameter Listrik DC:
- Tegangan (Voltage): Mengukur tegangan DC (misalnya 12V, 24V, 48V, dll.).
- Arus (Current): Mengukur arus listrik DC yang mengalir.
- Daya (Power): Menghitung daya aktif (Watt).
- Energi (Energy): Mencatat total konsumsi energi dalam Watt-hour (Wh) atau kiloWatt-hour (kWh).
Kegunaan pzem DC 017
PZEM-017 adalah modul pengukur (meter) listrik arus searah (DC) yang dilengkapi dengan antarmuka komunikasi RS485. Alat ini digunakan untuk memantau berbagai parameter kelistrikan DC secara real-time dan dapat diintegrasikan dengan sistem kontrol seperti Arduino, Raspberry Pi, atau PLC.
Kegunaan PZEM-017:
- Monitoring Sistem Tenaga Surya (Solar Panel)
- Mengukur tegangan (V), arus (A), daya (W), dan energi (kWh) yang dihasilkan oleh panel surya.
- Memantau pengisian baterai dan efisiensi sistem.
- Manajemen Baterai DC
- Memonitor pengisian (charging) dan pengosongan (discharging) baterai (12V, 24V, 48V, dll.).
- Menghitung kapasitas baterai dalam Ampere-hour (Ah).
- Kendaraan Listrik & Robotika
- Mengukur konsumsi daya pada motor DC, seperti pada mobil listrik, drone, atau robot.
- Memantau performa sistem kelistrikan kendaraan.
- Sistem Catuan Daya DC (Power Supply Monitoring)
- Memverifikasi output power supply DC (misalnya pada server, telekomunikasi, atau industri).
- Mendeteksi kelebihan beban (overload) atau gangguan.
- Pengembangan Projek IoT & Automasi
- Dapat dihubungkan ke Arduino, ESP8266/ESP32, atau PLC melalui Modbus RTU (RS485).
- Data bisa ditampilkan di LCD, smartphone, atau cloud (seperti Blynk, ThingsBoard).
Parameter yang Diukur oleh PZEM-017:
- Tegangan (Voltage DC): 6.5V – 100V
- Arus (Current DC): 0 – 300A (dengan shunt eksternal).
- Daya (Power): Perkalian V × I (Watt).
- Energi (Energy): Total pemakaian dalam kWh.
Keunggulan PZEM-017:
✅ Akurasi tinggi (±1% untuk tegangan dan arus).
✅ Antarmuka RS485 (kompatibel dengan Modbus RTU).
✅ Dapat diprogram menggunakan mikrokontroler.
✅ Tanpa display (dirancang untuk sistem embedded).
Contoh Aplikasi:
- Solar Charge Controller Monitoring → Memantau input/output solar charge controller.
- Battery Management System (BMS) → Mengecek kesehatan baterai Li-ion/Lead-acid.
- Smart Energy Meter DC → Mengirim data ke platform IoT seperti Home Assistant.
Prinsip Kerja PZEM DC 017
PZEM-017 adalah modul pengukur listrik arus searah (DC) berbasis sensor shunt dan komunikasi RS485. Berikut prinsip kerjanya secara detail:
1. Pengukuran Tegangan (Voltage DC)
- Metode: Menggunakan resistive voltage divider (pembagi tegangan).
- Proses:
- Tegangan DC input (misalnya 12V, 24V, atau 48V) di-reduce ke level yang aman untuk ADC (Analog-to-Digital Converter).
- Mikrokontroler di dalam PZEM-017 membaca nilai ADC dan mengkonversinya ke nilai tegangan aktual.
- Akurasi: ±0.5% – 1%
2. Pengukuran Arus (Current DC)
- Metode: Menggunakan shunt resistor (resistor berdaya tinggi dengan nilai sangat kecil, misalnya 0.001Ω atau 0.01Ω).
- Proses:
- Arus DC yang mengalir melewati shunt resistor menciptakan tegangan drop (V = I × R).
- Tegangan drop ini diperkuat oleh amplifier (seperti op-amp) sebelum dibaca oleh ADC.
- Mikrokontroler menghitung arus menggunakan Hukum Ohm (I = V / R).
- Akurasi: ±1% (tergantung kualitas shunt).
3. Perhitungan Daya (Power) dan Energi (Energy)
- Daya (Watt):CopyDownloadDaya (P) = Tegangan (V) × Arus (I)
- Dihitung secara real-time oleh mikrokontroler.
- Energi (kWh):CopyDownloadEnergi = ∑ (Daya × Waktu)
- PZEM-017 mengakumulasi energi dalam Wh atau kWh dan menyimpannya di memori non-volatile (EEPROM).
4. Komunikasi Data (RS485 & Modbus RTU)
- Protokol: Modbus RTU (fungsi code 0x04 untuk membaca register).
- Proses:
- PZEM-017 mengirim data dalam bentuk register (alamat Modbus).
- Perangkat master (Arduino/PLC/PC) meminta data melalui RS485.
- Data dikirim dalam format hex, contoh:
- Register 0x0000 → Tegangan (V)
- Register 0x0001 → Arus (A)
- Register 0x0002 → Daya (W)
- Register 0x0003 → Energi (kWh)
5. Contoh Alur Data
- Input: Baterai 24V dengan beban 5A.
- Pengukuran:
- Tegangan: 24.1V (dibaca via ADC).
- Arus: 5.02A (dihitung dari shunt).
- Daya: 24.1V × 5.02A = 121 Watt.
- Energi: Akumulasi per jam (misalnya 121 Wh setelah 1 jam).
- Output: Data dikirim via RS485 ke Arduino/PC.
Wiring diagram pada pzem017

Menghubungkan Modul RS485 ke Mikrokontroler
- RO (Receiver Output): Data yang diterima dari RS485.
- DI (Driver Input): Data yang dikirim ke RS485.
- DE (Driver Enable): Mengaktifkan pengiriman data.
- RE (Receiver Enable): Mengaktifkan penerimaan data.
- VCC dan GND: Power supply modul.
Cara penggunaan menggunakan arduino uno
Arduino Uno adalah salah satu board mikrokontroler yang paling banyak digunakan. Untuk menghubungkan sensor pzem dengan Arduino Uno
wiring arduino menggunakan serial monitor

- Hubungkan RO ke pin RX (pin 9).
- Hubungkan DI ke pin TX (pin 10).
- Hubungkan DE dan RE ke pin digital pin 8
- Hubungkan VCC ke 5V dan GND ke GND.
#define EN_RS485 8
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
ModbusMaster node;
SoftwareSerial mySerial(9, 10); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
// put your setup code here, to run once:
pinMode(EN_RS485, OUTPUT);
Serial.begin(9600);
mySerial.begin(9600);
delay(1000);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(1000);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, mySerial);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}
Wiring arduino uno menggunakan lcd

Untuk Arduino Uno:
- Hubungkan RO ke pin RX (pin 9).
- Hubungkan DI ke pin TX (pin 10).
- Hubungkan DE dan RE ke pin digital pin 8
- Hubungkan VCC ke 5V dan GND ke GND.
#define EN_RS485 8
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>
const int col = 16;
const int row = 2;
LiquidCrystal_I2C lcd(0x27, col, row);
ModbusMaster node;
SoftwareSerial mySerial(9, 10); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
float voltage;
float current;
float power;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
// put your setup code here, to run once:
pinMode(EN_RS485, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(5, 0);
lcd.print("TEMINS");
lcd.setCursor(5, 1);
lcd.print("STORE");
delay(300);
Serial.begin(9600);
mySerial.begin(9600);
delay(1000);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(500);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, mySerial);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
lcd.init();
lcd.backlight();
lcd.print("V:");
lcd.setCursor(0, 0);
lcd.setCursor(2, 0);
lcd.print(voltage);
lcd.setCursor(2, 1);
lcd.print(current);
lcd.setCursor(0, 1);
lcd.print("I:");
lcd.setCursor(11, 0);
lcd.print(power);
lcd.setCursor(9, 0);
lcd.print("P:");
lcd.setCursor(11, 1);
lcd.print(energy);
lcd.setCursor(9, 1);
lcd.print("E:");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}
Cara Penggunaan dengan ESP32
ESP32 adalah mikrokontroler yang lebih canggih dengan konektivitas Wi-Fi dan Bluetooth. Dengan ESP32, Anda dapat mengirimkan data pzem ke server atau aplikasi web melalui jaringan
Wiring esp32 menggunakan serial monitor

esp32
- VCC pada modul MAX485 -> VIN pada ESP32.
- GND pada modul MAX485 -> GND pada ESP32.
- A pada modul MAX485 -> A pada sensor pzem.
- B pada modul MAX485 -> B pada sensor pzem.
- RO (Receiver Output) pada modul MAX485 -> RX (pin 16) pada ESP32.
- DI (Driver Input) pada modul MAX485 -> TX (pin 17) pada ESP32.
- DE dan RE pada modul MAX485 -> D18 pada ESP32
- download library softwareserial khusus esp 32
#define EN_RS485 18
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
ModbusMaster node;
SoftwareSerial mySerial(16, 17); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
// put your setup code here, to run once:
pinMode(EN_RS485, OUTPUT);
Serial.begin(9600);
mySerial.begin(9600);
delay(1000);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(1000);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, mySerial);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}
wiring esp32 menggunakan lcd

- VCC pada modul MAX485 -> VIN pada ESP32.
- GND pada modul MAX485 -> GND pada ESP32.
- A pada modul MAX485 -> A pada sensor pzem.
- B pada modul MAX485 -> B pada sensor pzem.
- RO (Receiver Output) pada modul MAX485 -> RX (pin 16) pada ESP32.
- DI (Driver Input) pada modul MAX485 -> TX (pin 17) pada ESP32.
- DE dan RE pada modul MAX485 -> D18 pada ESP32
- download library softwareserial khusus esp 32
#define EN_RS485 18
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>
const int col = 16;
const int row = 2;
LiquidCrystal_I2C lcd(0x27, col, row);
ModbusMaster node;
SoftwareSerial mySerial(16, 17); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
float voltage;
float current;
float power;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
// put your setup code here, to run once:
pinMode(EN_RS485, OUTPUT);
//lcd.init();
lcd.begin();
lcd.backlight();
lcd.setCursor(5, 0);
lcd.print("TEMINS");
lcd.setCursor(5, 1);
lcd.print("STORE");
delay(300);
Serial.begin(9600);
mySerial.begin(9600);
delay(1000);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(500);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, mySerial);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
//lcd.init();
lcd.begin();
lcd.backlight();
lcd.print("V:");
lcd.setCursor(0, 0);
lcd.setCursor(2, 0);
lcd.print(voltage);
lcd.setCursor(2, 1);
lcd.print(current);
lcd.setCursor(0, 1);
lcd.print("I:");
lcd.setCursor(11, 0);
lcd.print(power);
lcd.setCursor(9, 0);
lcd.print("P:");
lcd.setCursor(11, 1);
lcd.print(energy);
lcd.setCursor(9, 1);
lcd.print("E:");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}
Cara Penggunaan dengan Arduino Mega
Arduino Mega memiliki lebih banyak pin dan lebih banyak port serial dibandingkan dengan Arduino Uno, yang membuatnya lebih fleksibel untuk aplikasi dengan banyak perangkat RS485
Wiring arduino menggunakan serial monitor

arduino mega
- VCC pada modul MAX485 -> 5V pada Arduino.
- GND pada modul MAX485 -> GND pada Arduino.
- A pada modul MAX485 -> A pada sensor pzem.
- B pada modul MAX485 -> B pada sensor pzem.
- RO (Receiver Output) pada modul MAX485 -> RX 1 (pin 19) pada Arduino.
- DI (Driver Input) pada modul MAX485 -> TX 1 (pin 18) pada Arduino.
- DE dan RE pada modul MAX485 -> D10 pada Arduino (atau pin digital lainnya).
#define EN_RS485 10
#include <ModbusMaster.h>
ModbusMaster node;
//SoftwareSerial Serial1(19, 18); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
float voltage;
float current;
float power;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
pinMode(EN_RS485, OUTPUT);
delay(300);
Serial.begin(9600);
Serial1.begin(9600);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(500);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, Serial1);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}
Wiring arduino mega menggunakan lcd

arduino mega
- VCC pada modul MAX485 -> 5V pada Arduino.
- GND pada modul MAX485 -> GND pada Arduino.
- A pada modul MAX485 -> A pada sensor pzem.
- B pada modul MAX485 -> B pada sensor pzem.
- RO (Receiver Output) pada modul MAX485 -> RX 1 (pin 19) pada Arduino.
- DI (Driver Input) pada modul MAX485 -> TX 1 (pin 18) pada Arduino.
- DE dan RE pada modul MAX485 -> D10 pada Arduino (atau pin digital lainnya).
#define EN_RS485 10
#include <ModbusMaster.h>
#include <LiquidCrystal_I2C.h>
const int col = 16;
const int row = 2;
LiquidCrystal_I2C lcd(0x27, col, row);
ModbusMaster node;
//SoftwareSerial Serial1(19, 18); // RX, TX
#define SLAVE_ADDR ((uint16_t)0x01)
uint16_t nilai;
float ph;
float voltage;
float current;
float power;
void preTransmission() {
digitalWrite(EN_RS485, 1);
}
void postTransmission() {
digitalWrite(EN_RS485, 0);
}
void setup() {
pinMode(EN_RS485, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(5, 0);
lcd.print("TEMINS");
lcd.setCursor(5, 1);
lcd.print("STORE");
delay(300);
Serial.begin(9600);
Serial1.begin(9600);
//uint8_t result = node.writeSingleRegister(0x0002, 0x02); // Alamat 0x0002 adalah alamat register untuk ID
}
void loop() {
sensor();
delay(500);
}
void sensor() {
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
node.begin(SLAVE_ADDR, Serial1);
float voltage = baca_sensor(0) / 100.0;
Serial.println("V : " + String(voltage));
float current = baca_sensor(1) / 100.0;
Serial.println("I : " + String(current));
float power = baca_32bit(2) / 10.0;
Serial.println("P : " + String(power));
float energy = baca_32bit(4); // langsung satuan Wh
Serial.println("E : " + String(energy));
Serial.println("============================================");
lcd.init();
lcd.backlight();
lcd.print("V:");
lcd.setCursor(0, 0);
lcd.setCursor(2, 0);
lcd.print(voltage);
lcd.setCursor(2, 1);
lcd.print(current);
lcd.setCursor(0, 1);
lcd.print("I:");
lcd.setCursor(11, 0);
lcd.print(power);
lcd.setCursor(9, 0);
lcd.print("P:");
lcd.setCursor(11, 1);
lcd.print(energy);
lcd.setCursor(9, 1);
lcd.print("E:");
}
int baca_sensor(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 6);
if (result == node.ku8MBSuccess) {
nilai = node.getResponseBuffer(0);
} else {
Serial.println("modbus fail");
}
return nilai;
}
uint32_t baca_32bit(uint16_t alamat) {
int result;
result = node.readInputRegisters(alamat, 2); // baca 2 register (32-bit)
if (result == node.ku8MBSuccess) {
uint32_t msb = node.getResponseBuffer(1);
uint32_t lsb = node.getResponseBuffer(0);
return (msb << 16) | lsb;
} else {
Serial.println("modbus fail");
return 0;
}
}