ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
atm90e32.h
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4#include <unordered_map>
5#include "atm90e32_reg.h"
10#include "esphome/core/gpio.h"
13
14namespace esphome::atm90e32 {
15
16inline bool offset_register_value_matches(uint16_t actual, int16_t expected) {
17 return actual == static_cast<uint16_t>(expected);
18}
19
21 int16_t first_offset{0};
22 int16_t second_offset{0};
23};
24
25static_assert(sizeof(OffsetCalibration[3]) == 12, "Offset calibration preference layout must remain compatible");
26
31
36
37inline OffsetRestoreState resolve_offset_restore_state(bool has_stored_values, bool initial_values_verified,
38 bool fallback_values_verified) {
39 if (initial_values_verified)
40 return {has_stored_values, true};
41 return {false, fallback_values_verified};
42}
43
44inline void prepare_offset_rollback(const OffsetCalibration (&previous)[3], bool had_stored_values,
45 OffsetCalibration (&rollback)[3]) {
46 for (uint8_t phase = 0; phase < 3; phase++)
47 rollback[phase] = had_stored_values ? previous[phase] : OffsetCalibration{};
48}
49
51 public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH,
52 spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_1MHZ> {
53 public:
54 static const uint8_t PHASEA = 0;
55 static const uint8_t PHASEB = 1;
56 static const uint8_t PHASEC = 2;
57 const char *phase_labels[3] = {"A", "B", "C"};
58 // these registers are not sucessive, so we can't just do 'base + phase'
59 const uint16_t voltage_gain_registers[3] = {ATM90E32_REGISTER_UGAINA, ATM90E32_REGISTER_UGAINB,
60 ATM90E32_REGISTER_UGAINC};
61 const uint16_t current_gain_registers[3] = {ATM90E32_REGISTER_IGAINA, ATM90E32_REGISTER_IGAINB,
62 ATM90E32_REGISTER_IGAINC};
63 const uint16_t voltage_offset_registers[3] = {ATM90E32_REGISTER_UOFFSETA, ATM90E32_REGISTER_UOFFSETB,
64 ATM90E32_REGISTER_UOFFSETC};
65 const uint16_t current_offset_registers[3] = {ATM90E32_REGISTER_IOFFSETA, ATM90E32_REGISTER_IOFFSETB,
66 ATM90E32_REGISTER_IOFFSETC};
67 const uint16_t power_offset_registers[3] = {ATM90E32_REGISTER_POFFSETA, ATM90E32_REGISTER_POFFSETB,
68 ATM90E32_REGISTER_POFFSETC};
69 const uint16_t reactive_power_offset_registers[3] = {ATM90E32_REGISTER_QOFFSETA, ATM90E32_REGISTER_QOFFSETB,
70 ATM90E32_REGISTER_QOFFSETC};
71 const uint16_t over_voltage_flags[3] = {ATM90E32_STATUS_S0_OVPHASEAST, ATM90E32_STATUS_S0_OVPHASEBST,
72 ATM90E32_STATUS_S0_OVPHASECST};
73 const uint16_t voltage_sag_flags[3] = {ATM90E32_STATUS_S1_SAGPHASEAST, ATM90E32_STATUS_S1_SAGPHASEBST,
74 ATM90E32_STATUS_S1_SAGPHASECST};
75 const uint16_t phase_loss_flags[3] = {ATM90E32_STATUS_S1_PHASELOSSAST, ATM90E32_STATUS_S1_PHASELOSSBST,
76 ATM90E32_STATUS_S1_PHASELOSSCST};
77 void loop() override;
78 void setup() override;
79 void dump_config() override;
80 float get_setup_priority() const override;
81 void update() override;
82 void set_voltage_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].voltage_sensor_ = obj; }
83 void set_current_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].current_sensor_ = obj; }
84 void set_power_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].power_sensor_ = obj; }
85 void set_reactive_power_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].reactive_power_sensor_ = obj; }
86 void set_apparent_power_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].apparent_power_sensor_ = obj; }
88 this->phase_[phase].forward_active_energy_sensor_ = obj;
89 }
91 this->phase_[phase].reverse_active_energy_sensor_ = obj;
92 }
93 void set_power_factor_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].power_factor_sensor_ = obj; }
94 void set_phase_angle_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].phase_angle_sensor_ = obj; }
96 this->phase_[phase].harmonic_active_power_sensor_ = obj;
97 }
98 void set_peak_current_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].peak_current_sensor_ = obj; }
99 void set_volt_gain(int phase, uint16_t gain) {
100 this->phase_[phase].voltage_gain_ = gain;
101 this->has_config_voltage_gain_[phase] = true;
102 }
103 void set_ct_gain(int phase, uint16_t gain) {
104 this->phase_[phase].ct_gain_ = gain;
105 this->has_config_current_gain_[phase] = true;
106 }
107 void set_voltage_offset(uint8_t phase, int16_t offset) {
108 this->offset_phase_[phase].first_offset = offset;
109 this->has_config_voltage_offset_[phase] = true;
110 }
111 void set_current_offset(uint8_t phase, int16_t offset) {
112 this->offset_phase_[phase].second_offset = offset;
113 this->has_config_current_offset_[phase] = true;
114 }
115 void set_active_power_offset(uint8_t phase, int16_t offset) {
116 this->power_offset_phase_[phase].first_offset = offset;
117 this->has_config_active_power_offset_[phase] = true;
118 }
119 void set_reactive_power_offset(uint8_t phase, int16_t offset) {
120 this->power_offset_phase_[phase].second_offset = offset;
121 this->has_config_reactive_power_offset_[phase] = true;
122 }
123 void set_freq_sensor(sensor::Sensor *freq_sensor) { freq_sensor_ = freq_sensor; }
125 void set_chip_temperature_sensor(sensor::Sensor *chip_temperature_sensor) {
126 chip_temperature_sensor_ = chip_temperature_sensor;
127 }
128 void set_line_freq(int freq) { line_freq_ = freq; }
129 void set_current_phases(int phases) { current_phases_ = phases; }
130 void set_pga_gain(uint16_t gain) { pga_gain_ = gain; }
138 void set_instance_id(const char *id) { instance_id_ = id; }
139 int16_t calibrate_offset(uint8_t phase, bool voltage);
140 int16_t calibrate_power_offset(uint8_t phase, bool reactive);
142 // Body of the calibration buttons: logs the button name and the hint lines, then runs action.
143 void press_calibration_button(EntityBase *entity, void (ATM90E32Component::*action)(),
144 const LogString *hint = nullptr, const LogString *hint2 = nullptr);
145#ifdef USE_NUMBER
146 void set_reference_voltage(uint8_t phase, number::Number *ref_voltage) { ref_voltages_[phase] = ref_voltage; }
147 void set_reference_current(uint8_t phase, number::Number *ref_current) { ref_currents_[phase] = ref_current; }
148#endif
149 float get_reference_voltage(uint8_t phase) {
150#ifdef USE_NUMBER
151 return (phase < 3 && ref_voltages_[phase]) ? ref_voltages_[phase]->state : 120.0; // Default voltage
152#else
153 return 120.0; // Default voltage
154#endif
155 }
156 float get_reference_current(uint8_t phase) {
157#ifdef USE_NUMBER
158 return (phase < 3 && ref_currents_[phase]) ? ref_currents_[phase]->state : 5.0f; // Default current
159#else
160 return 5.0f; // Default current
161#endif
162 }
163 bool using_saved_calibrations_ = false; // Track if stored calibrations are being used
164#ifdef USE_TEXT_SENSOR
165 void check_phase_status();
166 void check_freq_status();
167 void check_over_current();
169 this->phase_status_text_sensor_[phase] = sensor;
170 }
172#endif
173 uint16_t calculate_voltage_threshold(int line_freq, uint16_t ugain, float multiplier);
174
175 protected:
176#ifdef USE_NUMBER
177 number::Number *ref_voltages_[3]{nullptr, nullptr, nullptr};
178 number::Number *ref_currents_[3]{nullptr, nullptr, nullptr};
179#endif
180 uint16_t read16_(uint16_t a_register);
181 int read32_(uint16_t addr_h, uint16_t addr_l);
182 void write16_(uint16_t a_register, uint16_t val, bool validate = true);
183 float get_local_phase_voltage_(uint8_t phase);
184 float get_local_phase_current_(uint8_t phase);
185 float get_local_phase_active_power_(uint8_t phase);
186 float get_local_phase_reactive_power_(uint8_t phase);
187 float get_local_phase_apparent_power_(uint8_t phase);
188 float get_local_phase_power_factor_(uint8_t phase);
189 float get_local_phase_forward_active_energy_(uint8_t phase);
190 float get_local_phase_reverse_active_energy_(uint8_t phase);
191 float get_local_phase_angle_(uint8_t phase);
192 float get_local_phase_harmonic_active_power_(uint8_t phase);
193 float get_local_phase_peak_current_(uint8_t phase);
194 float get_phase_voltage_(uint8_t phase);
195 float get_phase_voltage_avg_(uint8_t phase);
196 float get_phase_current_(uint8_t phase);
197 float get_phase_current_avg_(uint8_t phase);
198 float get_phase_active_power_(uint8_t phase);
199 float get_phase_reactive_power_(uint8_t phase);
200 float get_phase_apparent_power_(uint8_t phase);
201 float get_phase_power_factor_(uint8_t phase);
202 float get_phase_forward_active_energy_(uint8_t phase);
203 float get_phase_reverse_active_energy_(uint8_t phase);
204 float get_phase_angle_(uint8_t phase);
205 float get_phase_harmonic_active_power_(uint8_t phase);
206 float get_phase_peak_current_(uint8_t phase);
207 float get_frequency_();
208 float get_chip_temperature_();
214 void finish_offset_calibration_(const OffsetCalibration (&previous)[3], bool previous_restored,
215 bool previous_using_saved, OffsetCalibrationType type);
216 void write_offsets_to_registers_(uint8_t phase, int16_t first_offset, int16_t second_offset,
219 bool verify_gain_writes_();
221 bool validate_spi_read_(uint16_t expected, const char *context = nullptr);
223 const char *get_calibration_id_();
224 void get_cs_summary_(std::span<char, GPIO_SUMMARY_MAX_LEN> buffer);
225
258
263
265 uint16_t voltage_gain{1};
266 uint16_t current_gain{1};
268
270
271 bool has_config_voltage_offset_[3]{false, false, false};
272 bool has_config_current_offset_[3]{false, false, false};
273 bool has_config_active_power_offset_[3]{false, false, false};
274 bool has_config_reactive_power_offset_[3]{false, false, false};
275 bool has_config_voltage_gain_[3]{false, false, false};
276 bool has_config_current_gain_[3]{false, false, false};
277
281
283#ifdef USE_TEXT_SENSOR
286#endif
288 uint16_t pga_gain_{0x15};
289 int line_freq_{60};
295 const char *instance_id_{nullptr};
302 bool offset_calibration_mismatch_[3]{false, false, false};
303 bool power_offset_calibration_mismatch_[3]{false, false, false};
304 bool gain_calibration_mismatch_[3]{false, false, false};
305};
306
307} // namespace esphome::atm90e32
This class simplifies creating components that periodically check a state.
Definition component.h:519
void set_chip_temperature_sensor(sensor::Sensor *chip_temperature_sensor)
Definition atm90e32.h:125
void set_freq_sensor(sensor::Sensor *freq_sensor)
Definition atm90e32.h:123
float get_local_phase_reactive_power_(uint8_t phase)
Definition atm90e32.cpp:507
float get_phase_forward_active_energy_(uint8_t phase)
Definition atm90e32.cpp:590
void set_freq_status_text_sensor(text_sensor::TextSensor *sensor)
Definition atm90e32.h:171
OffsetCalibration config_power_offset_phase_[3]
Definition atm90e32.h:262
float get_phase_current_avg_(uint8_t phase)
Definition atm90e32.cpp:549
float get_local_phase_apparent_power_(uint8_t phase)
Definition atm90e32.cpp:509
void write16_(uint16_t a_register, uint16_t val, bool validate=true)
Definition atm90e32.cpp:486
void set_apparent_power_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:86
text_sensor::TextSensor * freq_status_text_sensor_
Definition atm90e32.h:285
ESPPreferenceObject power_offset_pref_
Definition atm90e32.h:279
const uint16_t voltage_gain_registers[3]
Definition atm90e32.h:59
void restore_offset_calibrations_(OffsetCalibrationType type)
Definition atm90e32.cpp:992
float get_phase_voltage_avg_(uint8_t phase)
Definition atm90e32.cpp:535
const uint16_t current_gain_registers[3]
Definition atm90e32.h:61
float get_reference_voltage(uint8_t phase)
Definition atm90e32.h:149
number::Number * ref_voltages_[3]
Definition atm90e32.h:177
void set_power_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:84
struct esphome::atm90e32::ATM90E32Component::GainCalibration gain_phase_[3]
void set_current_offset(uint8_t phase, int16_t offset)
Definition atm90e32.h:111
void press_calibration_button(EntityBase *entity, void(ATM90E32Component::*action)(), const LogString *hint=nullptr, const LogString *hint2=nullptr)
Definition atm90e32.cpp:640
const uint16_t current_offset_registers[3]
Definition atm90e32.h:65
static const uint8_t PHASEB
Definition atm90e32.h:55
float get_phase_reverse_active_energy_(uint8_t phase)
Definition atm90e32.cpp:601
void set_reactive_power_offset(uint8_t phase, int16_t offset)
Definition atm90e32.h:119
float get_local_phase_harmonic_active_power_(uint8_t phase)
Definition atm90e32.cpp:523
float get_phase_angle_(uint8_t phase)
Definition atm90e32.cpp:617
float get_local_phase_current_(uint8_t phase)
Definition atm90e32.cpp:503
bool validate_spi_read_(uint16_t expected, const char *context=nullptr)
void set_peak_current_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:98
const uint16_t reactive_power_offset_registers[3]
Definition atm90e32.h:69
const uint16_t over_voltage_flags[3]
Definition atm90e32.h:71
void set_reverse_active_energy_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:90
float get_phase_voltage_(uint8_t phase)
Definition atm90e32.cpp:529
void set_current_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:83
GainCalibration config_gain_phase_[3]
Definition atm90e32.h:269
int16_t calibrate_offset(uint8_t phase, bool voltage)
float get_local_phase_reverse_active_energy_(uint8_t phase)
Definition atm90e32.cpp:517
void finish_offset_calibration_(const OffsetCalibration(&previous)[3], bool previous_restored, bool previous_using_saved, OffsetCalibrationType type)
Definition atm90e32.cpp:765
void set_harmonic_active_power_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:95
float get_local_phase_forward_active_energy_(uint8_t phase)
Definition atm90e32.cpp:513
OffsetCalibration config_offset_phase_[3]
Definition atm90e32.h:260
void set_active_power_offset(uint8_t phase, int16_t offset)
Definition atm90e32.h:115
uint16_t calculate_voltage_threshold(int line_freq, uint16_t ugain, float multiplier)
float get_local_phase_power_factor_(uint8_t phase)
Definition atm90e32.cpp:511
float get_phase_reactive_power_(uint8_t phase)
Definition atm90e32.cpp:574
void set_enable_gain_calibration(bool flag)
Definition atm90e32.h:137
const uint16_t phase_loss_flags[3]
Definition atm90e32.h:75
float get_phase_apparent_power_(uint8_t phase)
Definition atm90e32.cpp:579
float get_local_phase_voltage_(uint8_t phase)
Definition atm90e32.cpp:501
void set_phase_status_text_sensor(uint8_t phase, text_sensor::TextSensor *sensor)
Definition atm90e32.h:168
void set_pga_gain(uint16_t gain)
Definition atm90e32.h:130
void set_reference_current(uint8_t phase, number::Number *ref_current)
Definition atm90e32.h:147
ESPPreferenceObject gain_calibration_pref_
Definition atm90e32.h:280
void set_instance_id(const char *id)
Definition atm90e32.h:138
static const uint8_t PHASEA
Definition atm90e32.h:54
float get_reference_current(uint8_t phase)
Definition atm90e32.h:156
number::Number * ref_currents_[3]
Definition atm90e32.h:178
float get_phase_peak_current_(uint8_t phase)
Definition atm90e32.cpp:622
void set_voltage_offset(uint8_t phase, int16_t offset)
Definition atm90e32.h:107
float get_phase_harmonic_active_power_(uint8_t phase)
Definition atm90e32.cpp:612
const uint16_t voltage_sag_flags[3]
Definition atm90e32.h:73
float get_phase_active_power_(uint8_t phase)
Definition atm90e32.cpp:569
void get_cs_summary_(std::span< char, GPIO_SUMMARY_MAX_LEN > buffer)
Definition atm90e32.cpp:131
static const uint8_t PHASEC
Definition atm90e32.h:56
const uint16_t power_offset_registers[3]
Definition atm90e32.h:67
float get_setup_priority() const override
Definition atm90e32.cpp:453
uint16_t read16_(uint16_t a_register)
Definition atm90e32.cpp:458
int read32_(uint16_t addr_h, uint16_t addr_l)
Definition atm90e32.cpp:473
sensor::Sensor * chip_temperature_sensor_
Definition atm90e32.h:287
void write_offsets_to_registers_(uint8_t phase, int16_t first_offset, int16_t second_offset, OffsetCalibrationType type)
Definition atm90e32.cpp:913
float get_phase_power_factor_(uint8_t phase)
Definition atm90e32.cpp:584
void set_voltage_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:82
OffsetCalibration power_offset_phase_[3]
Definition atm90e32.h:261
float get_local_phase_angle_(uint8_t phase)
Definition atm90e32.cpp:521
const uint16_t voltage_offset_registers[3]
Definition atm90e32.h:63
void set_ct_gain(int phase, uint16_t gain)
Definition atm90e32.h:103
void set_phase_angle_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:94
OffsetCalibration offset_phase_[3]
Definition atm90e32.h:259
void set_reference_voltage(uint8_t phase, number::Number *ref_voltage)
Definition atm90e32.h:146
void set_power_factor_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:93
void set_forward_active_energy_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:87
void set_volt_gain(int phase, uint16_t gain)
Definition atm90e32.h:99
text_sensor::TextSensor * phase_status_text_sensor_[3]
Definition atm90e32.h:284
float get_phase_current_(uint8_t phase)
Definition atm90e32.cpp:563
void set_peak_current_signed(bool flag)
Definition atm90e32.h:124
float get_local_phase_peak_current_(uint8_t phase)
Definition atm90e32.cpp:527
void set_publish_interval_flag_(bool flag)
Definition atm90e32.h:210
int16_t calibrate_power_offset(uint8_t phase, bool reactive)
struct esphome::atm90e32::ATM90E32Component::ATM90E32Phase phase_[3]
bool verify_offset_writes_(OffsetCalibrationType type)
void set_enable_offset_calibration(bool flag)
Definition atm90e32.h:136
ESPPreferenceObject offset_pref_
Definition atm90e32.h:278
void set_reactive_power_sensor(int phase, sensor::Sensor *obj)
Definition atm90e32.h:85
float get_local_phase_active_power_(uint8_t phase)
Definition atm90e32.cpp:505
Base-class for all numbers.
Definition number.h:29
Base-class for all sensors.
Definition sensor.h:47
The SPIDevice is what components using the SPI will create.
Definition spi.h:456
uint16_t id
uint8_t type
uint32_t buffer
Definition gif.cpp:50
AlsGain501 gain
mopeka_std_values val[3]
OffsetRestoreState resolve_offset_restore_state(bool has_stored_values, bool initial_values_verified, bool fallback_values_verified)
Definition atm90e32.h:37
bool offset_register_value_matches(uint16_t actual, int16_t expected)
Definition atm90e32.h:16
void prepare_offset_rollback(const OffsetCalibration(&previous)[3], bool had_stored_values, OffsetCalibration(&rollback)[3])
Definition atm90e32.h:44
static void uint32_t