This brief note explains how to connect ESP8266 and Peacefair PZEM-017 to read voltage and current from the sensor over Modbus RTU (the RS485 based serial protocol).
Parts List
- Wemos D1 (ESP 8266)
- MAX3485
- 120 ohm resistor (used 100 ohm for testing)
Connections
Code Example
#include // https://github.com/emelianov/modbus-esp8266
#include
// ESP8266 pins
#define D6 12
#define D7 13
#define D8 15
// PZEM-017 Shunt Range
#define PZEM_SHUNT_100A 0x0000
#define PZEM_SHUNT_50A 0x0001
#define PZEM_SHUNT_200A 0x0002
#define PZEM_SHUNT_300A 0x0003
// My settings
#define SERIAL_RX D8
#define SERIAL_TX D7
#define SERIAL_CONTROL D6
#define PZEM_MODBUS_ID 0x01
#define PZEM_SHUNT PZEM_SHUNT_200A
SoftwareSerial swSerial(SERIAL_RX, SERIAL_TX);
ModbusRTU modbus;
int modbusLastStatusCode = -1;
bool modbusStatusCallback(Modbus::ResultCode event, uint16_t transactionId, void* data) {
// Serial.printf_P("Request result: 0x%02X, Mem: %d\n", event, ESP.getFreeHeap());
modbusLastStatusCode = uint(event);
return true;
}
void setup() {
Serial.begin(115200);
swSerial.begin(9600, SWSERIAL_8N1);
modbus.begin(&swSerial, SERIAL_CONTROL);
modbus.client();
Serial.print("Setting shut value...");
// The write resulted always 0xE4 (timeout), so no callback here
modbus.writeHreg(PZEM_MODBUS_ID, 0x0003, PZEM_SHUNT);
modbus.task();
Serial.println("OK");
Serial.println("Setup finished");
}
uint16_t registers[2];
float voltage;
float current;
void loop() {
if (!modbus.slave()) {
modbus.readIreg(PZEM_MODBUS_ID, 0, registers, 2, modbusStatusCallback);
if (modbusLastStatusCode == 0) {
voltage = registers[0] / 100.0;
current = registers[1] / 100.0;
Serial.print(voltage);
Serial.print("V, ");
Serial.print(current);
Serial.println("A");
}
else {
Serial.printf_P("Result code: 0x%02X\n", modbusLastStatusCode);
}
}
modbus.task();
yield();
}
For PlatformIO users, the platformio.ini:
[platformio]
default_envs =
esp8266
[env]
lib_deps =
https://github.com/emelianov/modbus-esp8266
[env:esp8266]
platform = espressif8266
framework = arduino
board = d1
lib_ldf_mode = deep
monitor_speed = 115200
upload_speed = 460800
