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