ESPHome  2022.12.8
atm90e32.cpp
Go to the documentation of this file.
1 #include "atm90e32.h"
2 #include "atm90e32_reg.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace atm90e32 {
7 
8 static const char *const TAG = "atm90e32";
9 
11  if (this->read16_(ATM90E32_REGISTER_METEREN) != 1) {
12  this->status_set_warning();
13  return;
14  }
15 
16  if (this->phase_[0].voltage_sensor_ != nullptr) {
18  }
19  if (this->phase_[1].voltage_sensor_ != nullptr) {
21  }
22  if (this->phase_[2].voltage_sensor_ != nullptr) {
24  }
25  if (this->phase_[0].current_sensor_ != nullptr) {
27  }
28  if (this->phase_[1].current_sensor_ != nullptr) {
30  }
31  if (this->phase_[2].current_sensor_ != nullptr) {
33  }
34  if (this->phase_[0].power_sensor_ != nullptr) {
36  }
37  if (this->phase_[1].power_sensor_ != nullptr) {
39  }
40  if (this->phase_[2].power_sensor_ != nullptr) {
42  }
43  if (this->phase_[0].reactive_power_sensor_ != nullptr) {
45  }
46  if (this->phase_[1].reactive_power_sensor_ != nullptr) {
48  }
49  if (this->phase_[2].reactive_power_sensor_ != nullptr) {
51  }
52  if (this->phase_[0].power_factor_sensor_ != nullptr) {
54  }
55  if (this->phase_[1].power_factor_sensor_ != nullptr) {
57  }
58  if (this->phase_[2].power_factor_sensor_ != nullptr) {
60  }
61  if (this->phase_[0].forward_active_energy_sensor_ != nullptr) {
63  }
64  if (this->phase_[1].forward_active_energy_sensor_ != nullptr) {
66  }
67  if (this->phase_[2].forward_active_energy_sensor_ != nullptr) {
69  }
70  if (this->phase_[0].reverse_active_energy_sensor_ != nullptr) {
72  }
73  if (this->phase_[1].reverse_active_energy_sensor_ != nullptr) {
75  }
76  if (this->phase_[2].reverse_active_energy_sensor_ != nullptr) {
78  }
79  if (this->freq_sensor_ != nullptr) {
81  }
82  if (this->chip_temperature_sensor_ != nullptr) {
84  }
85  this->status_clear_warning();
86 }
87 
89  ESP_LOGCONFIG(TAG, "Setting up ATM90E32 Component...");
90  this->spi_setup();
91 
92  uint16_t mmode0 = 0x87; // 3P4W 50Hz
93  if (line_freq_ == 60) {
94  mmode0 |= 1 << 12; // sets 12th bit to 1, 60Hz
95  }
96 
97  if (current_phases_ == 2) {
98  mmode0 |= 1 << 8; // sets 8th bit to 1, 3P3W
99  mmode0 |= 0 << 1; // sets 1st bit to 0, phase b is not counted into the all-phase sum energy/power (P/Q/S)
100  }
101 
102  this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A); // Perform soft reset
103  this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
104  this->write16_(ATM90E32_REGISTER_METEREN, 0x0001); // Enable Metering
105  if (this->read16_(ATM90E32_REGISTER_LASTSPIDATA) != 0x0001) {
106  ESP_LOGW(TAG, "Could not initialize ATM90E32 IC, check SPI settings");
107  this->mark_failed();
108  return;
109  }
110  this->write16_(ATM90E32_REGISTER_PLCONSTH, 0x0861); // PL Constant MSB (default) = 140625000
111  this->write16_(ATM90E32_REGISTER_PLCONSTL, 0xC468); // PL Constant LSB (default)
112  this->write16_(ATM90E32_REGISTER_ZXCONFIG, 0xD654); // ZX2, ZX1, ZX0 pin config
113  this->write16_(ATM90E32_REGISTER_MMODE0, mmode0); // Mode Config (frequency set in main program)
114  this->write16_(ATM90E32_REGISTER_MMODE1, pga_gain_); // PGA Gain Configuration for Current Channels
115  this->write16_(ATM90E32_REGISTER_PSTARTTH, 0x1D4C); // All Active Startup Power Threshold - 0.02A/0.00032 = 7500
116  this->write16_(ATM90E32_REGISTER_QSTARTTH, 0x1D4C); // All Reactive Startup Power Threshold - 50%
117  this->write16_(ATM90E32_REGISTER_PPHASETH, 0x02EE); // Each Phase Active Phase Threshold - 0.002A/0.00032 = 750
118  this->write16_(ATM90E32_REGISTER_QPHASETH, 0x02EE); // Each phase Reactive Phase Threshold - 10%
119  this->write16_(ATM90E32_REGISTER_UGAINA, this->phase_[0].volt_gain_); // A Voltage rms gain
120  this->write16_(ATM90E32_REGISTER_IGAINA, this->phase_[0].ct_gain_); // A line current gain
121  this->write16_(ATM90E32_REGISTER_UGAINB, this->phase_[1].volt_gain_); // B Voltage rms gain
122  this->write16_(ATM90E32_REGISTER_IGAINB, this->phase_[1].ct_gain_); // B line current gain
123  this->write16_(ATM90E32_REGISTER_UGAINC, this->phase_[2].volt_gain_); // C Voltage rms gain
124  this->write16_(ATM90E32_REGISTER_IGAINC, this->phase_[2].ct_gain_); // C line current gain
125  this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x0000); // end configuration
126 }
127 
129  ESP_LOGCONFIG("", "ATM90E32:");
130  LOG_PIN(" CS Pin: ", this->cs_);
131  if (this->is_failed()) {
132  ESP_LOGE(TAG, "Communication with ATM90E32 failed!");
133  }
134  LOG_UPDATE_INTERVAL(this);
135  LOG_SENSOR(" ", "Voltage A", this->phase_[0].voltage_sensor_);
136  LOG_SENSOR(" ", "Current A", this->phase_[0].current_sensor_);
137  LOG_SENSOR(" ", "Power A", this->phase_[0].power_sensor_);
138  LOG_SENSOR(" ", "Reactive Power A", this->phase_[0].reactive_power_sensor_);
139  LOG_SENSOR(" ", "PF A", this->phase_[0].power_factor_sensor_);
140  LOG_SENSOR(" ", "Active Forward Energy A", this->phase_[0].forward_active_energy_sensor_);
141  LOG_SENSOR(" ", "Active Reverse Energy A", this->phase_[0].reverse_active_energy_sensor_);
142  LOG_SENSOR(" ", "Voltage B", this->phase_[1].voltage_sensor_);
143  LOG_SENSOR(" ", "Current B", this->phase_[1].current_sensor_);
144  LOG_SENSOR(" ", "Power B", this->phase_[1].power_sensor_);
145  LOG_SENSOR(" ", "Reactive Power B", this->phase_[1].reactive_power_sensor_);
146  LOG_SENSOR(" ", "PF B", this->phase_[1].power_factor_sensor_);
147  LOG_SENSOR(" ", "Active Forward Energy B", this->phase_[1].forward_active_energy_sensor_);
148  LOG_SENSOR(" ", "Active Reverse Energy B", this->phase_[1].reverse_active_energy_sensor_);
149  LOG_SENSOR(" ", "Voltage C", this->phase_[2].voltage_sensor_);
150  LOG_SENSOR(" ", "Current C", this->phase_[2].current_sensor_);
151  LOG_SENSOR(" ", "Power C", this->phase_[2].power_sensor_);
152  LOG_SENSOR(" ", "Reactive Power C", this->phase_[2].reactive_power_sensor_);
153  LOG_SENSOR(" ", "PF C", this->phase_[2].power_factor_sensor_);
154  LOG_SENSOR(" ", "Active Forward Energy C", this->phase_[2].forward_active_energy_sensor_);
155  LOG_SENSOR(" ", "Active Reverse Energy C", this->phase_[2].reverse_active_energy_sensor_);
156  LOG_SENSOR(" ", "Frequency", this->freq_sensor_);
157  LOG_SENSOR(" ", "Chip Temp", this->chip_temperature_sensor_);
158 }
160 
161 uint16_t ATM90E32Component::read16_(uint16_t a_register) {
162  uint8_t addrh = (1 << 7) | ((a_register >> 8) & 0x03);
163  uint8_t addrl = (a_register & 0xFF);
164  uint8_t data[2];
165  uint16_t output;
166 
167  this->enable();
168  delayMicroseconds(10);
169  this->write_byte(addrh);
170  this->write_byte(addrl);
172  this->read_array(data, 2);
173  this->disable();
174 
175  output = (uint16_t(data[0] & 0xFF) << 8) | (data[1] & 0xFF);
176  ESP_LOGVV(TAG, "read16_ 0x%04X output 0x%04X", a_register, output);
177  return output;
178 }
179 
180 int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
181  uint16_t val_h = this->read16_(addr_h);
182  uint16_t val_l = this->read16_(addr_l);
183  int32_t val = (val_h << 16) | val_l;
184 
185  ESP_LOGVV(TAG, "read32_ addr_h 0x%04X val_h 0x%04X addr_l 0x%04X val_l 0x%04X = %d", addr_h, val_h, addr_l, val_l,
186  val);
187 
188  return val;
189 }
190 
191 void ATM90E32Component::write16_(uint16_t a_register, uint16_t val) {
192  uint8_t addrh = (a_register >> 8) & 0x03;
193  uint8_t addrl = (a_register & 0xFF);
194 
195  ESP_LOGVV(TAG, "write16_ 0x%04X val 0x%04X", a_register, val);
196  this->enable();
197  delayMicroseconds(10);
198  this->write_byte(addrh);
199  this->write_byte(addrl);
201  this->write_byte((val >> 8) & 0xff);
202  this->write_byte(val & 0xFF);
203  this->disable();
204 }
205 
207  uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSA);
208  return (float) voltage / 100;
209 }
211  uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSB);
212  return (float) voltage / 100;
213 }
215  uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSC);
216  return (float) voltage / 100;
217 }
219  uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSA);
220  return (float) current / 1000;
221 }
223  uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSB);
224  return (float) current / 1000;
225 }
227  uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSC);
228  return (float) current / 1000;
229 }
231  int val = this->read32_(ATM90E32_REGISTER_PMEANA, ATM90E32_REGISTER_PMEANALSB);
232  return val * 0.00032f;
233 }
235  int val = this->read32_(ATM90E32_REGISTER_PMEANB, ATM90E32_REGISTER_PMEANBLSB);
236  return val * 0.00032f;
237 }
239  int val = this->read32_(ATM90E32_REGISTER_PMEANC, ATM90E32_REGISTER_PMEANCLSB);
240  return val * 0.00032f;
241 }
243  int val = this->read32_(ATM90E32_REGISTER_QMEANA, ATM90E32_REGISTER_QMEANALSB);
244  return val * 0.00032f;
245 }
247  int val = this->read32_(ATM90E32_REGISTER_QMEANB, ATM90E32_REGISTER_QMEANBLSB);
248  return val * 0.00032f;
249 }
251  int val = this->read32_(ATM90E32_REGISTER_QMEANC, ATM90E32_REGISTER_QMEANCLSB);
252  return val * 0.00032f;
253 }
255  int16_t pf = this->read16_(ATM90E32_REGISTER_PFMEANA);
256  return (float) pf / 1000;
257 }
259  int16_t pf = this->read16_(ATM90E32_REGISTER_PFMEANB);
260  return (float) pf / 1000;
261 }
263  int16_t pf = this->read16_(ATM90E32_REGISTER_PFMEANC);
264  return (float) pf / 1000;
265 }
267  uint16_t val = this->read16_(ATM90E32_REGISTER_APENERGYA);
268  if ((UINT32_MAX - this->phase_[0].cumulative_forward_active_energy_) > val) {
270  } else {
272  }
273  return ((float) this->phase_[0].cumulative_forward_active_energy_ * 10 / 3200);
274 }
276  uint16_t val = this->read16_(ATM90E32_REGISTER_APENERGYB);
277  if (UINT32_MAX - this->phase_[1].cumulative_forward_active_energy_ > val) {
279  } else {
281  }
282  return ((float) this->phase_[1].cumulative_forward_active_energy_ * 10 / 3200);
283 }
285  uint16_t val = this->read16_(ATM90E32_REGISTER_APENERGYC);
286  if (UINT32_MAX - this->phase_[2].cumulative_forward_active_energy_ > val) {
288  } else {
290  }
291  return ((float) this->phase_[2].cumulative_forward_active_energy_ * 10 / 3200);
292 }
294  uint16_t val = this->read16_(ATM90E32_REGISTER_ANENERGYA);
295  if (UINT32_MAX - this->phase_[0].cumulative_reverse_active_energy_ > val) {
297  } else {
299  }
300  return ((float) this->phase_[0].cumulative_reverse_active_energy_ * 10 / 3200);
301 }
303  uint16_t val = this->read16_(ATM90E32_REGISTER_ANENERGYB);
304  if (UINT32_MAX - this->phase_[1].cumulative_reverse_active_energy_ > val) {
306  } else {
308  }
309  return ((float) this->phase_[1].cumulative_reverse_active_energy_ * 10 / 3200);
310 }
312  uint16_t val = this->read16_(ATM90E32_REGISTER_ANENERGYC);
313  if (UINT32_MAX - this->phase_[2].cumulative_reverse_active_energy_ > val) {
315  } else {
317  }
318  return ((float) this->phase_[2].cumulative_reverse_active_energy_ * 10 / 3200);
319 }
321  uint16_t freq = this->read16_(ATM90E32_REGISTER_FREQ);
322  return (float) freq / 100;
323 }
325  uint16_t ctemp = this->read16_(ATM90E32_REGISTER_TEMP);
326  return (float) ctemp;
327 }
328 } // namespace atm90e32
329 } // namespace esphome
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:18
float get_setup_priority() const override
Definition: atm90e32.cpp:159
void write16_(uint16_t a_register, uint16_t val)
Definition: atm90e32.cpp:191
int read32_(uint16_t addr_h, uint16_t addr_l)
Definition: atm90e32.cpp:180
void status_clear_warning()
Definition: component.cpp:149
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:72
struct esphome::atm90e32::ATM90E32Component::ATM90E32Phase phase_[3]
void status_set_warning()
Definition: component.cpp:141
uint16_t read16_(uint16_t a_register)
Definition: atm90e32.cpp:161
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:112
sensor::Sensor * chip_temperature_sensor_
Definition: atm90e32.h:84
Definition: a4988.cpp:4
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition: core.cpp:29
uint32_t val
Definition: datatypes.h:85