ESPHome 2026.8.0b4
Loading...
Searching...
No Matches
pzemdc.cpp
Go to the documentation of this file.
1#include "pzemdc.h"
2#include "esphome/core/log.h"
3
4namespace esphome::pzemdc {
5
6static const char *const TAG = "pzemdc";
7
8static const uint8_t PZEM_CMD_RESET_ENERGY = 0x42;
9static const uint8_t PZEM_REGISTER_COUNT = 10; // 10x 16-bit registers
10
11void PZEMDC::on_response(std::span<const uint8_t> request_pdu, std::span<const uint8_t> response_pdu) {
12 auto data = modbus::helpers::server_pdu_payload(response_pdu);
13 if (data.size() < 16) {
14 ESP_LOGW(TAG, "Invalid size for PZEM DC!");
15 return;
16 }
17
18 // See https://github.com/esphome/feature-requests/issues/49#issuecomment-538636809
19 // 0 1 2 3 4 5 6 7 = ModBus register
20 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 = Buffer index
21 // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29
22 // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
23
24 auto pzem_get_16bit = [&](size_t i) -> uint16_t {
25 return (uint16_t(data[i + 0]) << 8) | (uint16_t(data[i + 1]) << 0);
26 };
27 auto pzem_get_32bit = [&](size_t i) -> uint32_t {
28 return (uint32_t(pzem_get_16bit(i + 2)) << 16) | (uint32_t(pzem_get_16bit(i + 0)) << 0);
29 };
30
31 uint16_t raw_voltage = pzem_get_16bit(0);
32 float voltage = raw_voltage / 100.0f; // max 655.35 V
33
34 uint16_t raw_current = pzem_get_16bit(2);
35 float current = raw_current / 100.0f; // max 655.35 A
36
37 uint32_t raw_power = pzem_get_32bit(4);
38 float power = raw_power / 10.0f; // max 429496729.5 W
39
40 uint32_t raw_energy = pzem_get_32bit(8);
41 float energy = raw_energy / 1000.0f; // max 4294967.295 kWh
42
43 ESP_LOGD(TAG, "PZEM DC: V=%.1f V, I=%.3f A, P=%.1f W", voltage, current, power);
44 if (this->voltage_sensor_ != nullptr)
45 this->voltage_sensor_->publish_state(voltage);
46 if (this->current_sensor_ != nullptr)
47 this->current_sensor_->publish_state(current);
48 if (this->power_sensor_ != nullptr)
49 this->power_sensor_->publish_state(power);
50 if (this->energy_sensor_ != nullptr)
51 this->energy_sensor_->publish_state(energy);
52}
53
54void PZEMDC::update() { this->read_input_registers(0, 8); }
56 ESP_LOGCONFIG(TAG,
57 "PZEMDC:\n"
58 " Address: 0x%02X",
59 this->address_);
60 LOG_SENSOR("", "Voltage", this->voltage_sensor_);
61 LOG_SENSOR("", "Current", this->current_sensor_);
62 LOG_SENSOR("", "Power", this->power_sensor_);
63 LOG_SENSOR("", "Energy", this->energy_sensor_);
64}
65
67 const uint8_t pdu[] = {PZEM_CMD_RESET_ENERGY};
68 this->queue_pdu(pdu);
69}
70
71} // namespace esphome::pzemdc
sensor::Sensor * power_sensor_
Definition pzemdc.h:30
void update() override
Definition pzemdc.cpp:54
sensor::Sensor * current_sensor_
Definition pzemdc.h:29
void on_response(std::span< const uint8_t > request_pdu, std::span< const uint8_t > response_pdu) override
Definition pzemdc.cpp:11
void dump_config() override
Definition pzemdc.cpp:55
sensor::Sensor * voltage_sensor_
Definition pzemdc.h:28
sensor::Sensor * energy_sensor_
Definition pzemdc.h:31
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
u_int8_t raw_voltage
std::span< const uint8_t > server_pdu_payload(std::span< const uint8_t > pdu)
Returns the payload portion of a server response PDU: the bytes after the function code,...
static void uint32_t