ESPHome  2024.4.0
pzemac.cpp
Go to the documentation of this file.
1 #include "pzemac.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace pzemac {
6 
7 static const char *const TAG = "pzemac";
8 
9 static const uint8_t PZEM_CMD_READ_IN_REGISTERS = 0x04;
10 static const uint8_t PZEM_CMD_RESET_ENERGY = 0x42;
11 static const uint8_t PZEM_REGISTER_COUNT = 10; // 10x 16-bit registers
12 
13 void PZEMAC::on_modbus_data(const std::vector<uint8_t> &data) {
14  if (data.size() < 20) {
15  ESP_LOGW(TAG, "Invalid size for PZEM AC!");
16  return;
17  }
18 
19  // See https://github.com/esphome/feature-requests/issues/49#issuecomment-538636809
20  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
21  // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34
22  // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
23  // 0 2 6 10 14 16
24 
25  auto pzem_get_16bit = [&](size_t i) -> uint16_t {
26  return (uint16_t(data[i + 0]) << 8) | (uint16_t(data[i + 1]) << 0);
27  };
28  auto pzem_get_32bit = [&](size_t i) -> uint32_t {
29  return (uint32_t(pzem_get_16bit(i + 2)) << 16) | (uint32_t(pzem_get_16bit(i + 0)) << 0);
30  };
31 
32  uint16_t raw_voltage = pzem_get_16bit(0);
33  float voltage = raw_voltage / 10.0f; // max 6553.5 V
34 
35  uint32_t raw_current = pzem_get_32bit(2);
36  float current = raw_current / 1000.0f; // max 4294967.295 A
37 
38  uint32_t raw_active_power = pzem_get_32bit(6);
39  float active_power = raw_active_power / 10.0f; // max 429496729.5 W
40 
41  float active_energy = static_cast<float>(pzem_get_32bit(10));
42 
43  uint16_t raw_frequency = pzem_get_16bit(14);
44  float frequency = raw_frequency / 10.0f;
45 
46  uint16_t raw_power_factor = pzem_get_16bit(16);
47  float power_factor = raw_power_factor / 100.0f;
48 
49  ESP_LOGD(TAG, "PZEM AC: V=%.1f V, I=%.3f A, P=%.1f W, E=%.1f Wh, F=%.1f Hz, PF=%.2f", voltage, current, active_power,
50  active_energy, frequency, power_factor);
51  if (this->voltage_sensor_ != nullptr)
52  this->voltage_sensor_->publish_state(voltage);
53  if (this->current_sensor_ != nullptr)
54  this->current_sensor_->publish_state(current);
55  if (this->power_sensor_ != nullptr)
56  this->power_sensor_->publish_state(active_power);
57  if (this->energy_sensor_ != nullptr)
58  this->energy_sensor_->publish_state(active_energy);
59  if (this->frequency_sensor_ != nullptr)
60  this->frequency_sensor_->publish_state(frequency);
61  if (this->power_factor_sensor_ != nullptr)
62  this->power_factor_sensor_->publish_state(power_factor);
63 }
64 
65 void PZEMAC::update() { this->send(PZEM_CMD_READ_IN_REGISTERS, 0, PZEM_REGISTER_COUNT); }
67  ESP_LOGCONFIG(TAG, "PZEMAC:");
68  ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
69  LOG_SENSOR("", "Voltage", this->voltage_sensor_);
70  LOG_SENSOR("", "Current", this->current_sensor_);
71  LOG_SENSOR("", "Power", this->power_sensor_);
72  LOG_SENSOR("", "Energy", this->energy_sensor_);
73  LOG_SENSOR("", "Frequency", this->frequency_sensor_);
74  LOG_SENSOR("", "Power Factor", this->power_factor_sensor_);
75 }
76 
78  std::vector<uint8_t> cmd;
79  cmd.push_back(this->address_);
80  cmd.push_back(PZEM_CMD_RESET_ENERGY);
81  this->send_raw(cmd);
82 }
83 
84 } // namespace pzemac
85 } // namespace esphome
void dump_config() override
Definition: pzemac.cpp:66
u_int8_t raw_voltage
sensor::Sensor * frequency_sensor_
Definition: pzemac.h:36
sensor::Sensor * power_sensor_
Definition: pzemac.h:34
sensor::Sensor * energy_sensor_
Definition: pzemac.h:35
void send_raw(const std::vector< uint8_t > &payload)
Definition: modbus.h:57
void update() override
Definition: pzemac.cpp:65
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
void on_modbus_data(const std::vector< uint8_t > &data) override
Definition: pzemac.cpp:13
uint16_le_t frequency
Definition: bl0942.h:21
sensor::Sensor * power_factor_sensor_
Definition: pzemac.h:37
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
sensor::Sensor * current_sensor_
Definition: pzemac.h:33
void send(uint8_t function, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len=0, const uint8_t *payload=nullptr)
Definition: modbus.h:53
sensor::Sensor * voltage_sensor_
Definition: pzemac.h:32
stm32_cmd_t * cmd
Definition: stm32flash.h:96