mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-05-20 04:53:28 +02:00
db968bc6b0
* Atmel M90E32AS Energy Metering IC. Found in CircuitSetup 2can and 6chan energy meters * fix style bugs * Update esphome/components/atm90e32/atm90e32.cpp Co-Authored-By: Otto Winter <otto@otto-winter.com> * Properly put atm90e32_reg in namespace * Use phase grouped config like ina3221 * Log why the component is marked failed, did not read back our register value * 32bit register reads are 2s compliment * Fix atm90e32 option name in test * clang-format changes from travis-ci * use new protected method names * Whitespace changes to please Travis * Update esphome/components/atm90e32/atm90e32.cpp Co-Authored-By: Otto Winter <otto@otto-winter.com> * Fix up type change for val_h/val_l * Remove conditions around values with defaults * Rename constants to match their value * Remove 2's complement check Co-authored-by: Andrew Thompson <andrew@whosonlocation.com> Co-authored-by: Otto Winter <otto@otto-winter.com>
189 lines
7.2 KiB
C++
189 lines
7.2 KiB
C++
#include "atm90e32.h"
|
|
#include "atm90e32_reg.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome {
|
|
namespace atm90e32 {
|
|
|
|
static const char *TAG = "atm90e32";
|
|
|
|
void ATM90E32Component::update() {
|
|
if (this->read16_(ATM90E32_REGISTER_METEREN) != 1) {
|
|
this->status_set_warning();
|
|
return;
|
|
}
|
|
|
|
if (this->phase_[0].voltage_sensor_ != nullptr) {
|
|
this->phase_[0].voltage_sensor_->publish_state(this->get_line_voltage_a_());
|
|
}
|
|
if (this->phase_[1].voltage_sensor_ != nullptr) {
|
|
this->phase_[1].voltage_sensor_->publish_state(this->get_line_voltage_b_());
|
|
}
|
|
if (this->phase_[2].voltage_sensor_ != nullptr) {
|
|
this->phase_[2].voltage_sensor_->publish_state(this->get_line_voltage_c_());
|
|
}
|
|
if (this->phase_[0].current_sensor_ != nullptr) {
|
|
this->phase_[0].current_sensor_->publish_state(this->get_line_current_a_());
|
|
}
|
|
if (this->phase_[1].current_sensor_ != nullptr) {
|
|
this->phase_[1].current_sensor_->publish_state(this->get_line_current_b_());
|
|
}
|
|
if (this->phase_[2].current_sensor_ != nullptr) {
|
|
this->phase_[2].current_sensor_->publish_state(this->get_line_current_c_());
|
|
}
|
|
if (this->phase_[0].power_sensor_ != nullptr) {
|
|
this->phase_[0].power_sensor_->publish_state(this->get_active_power_a_());
|
|
}
|
|
if (this->phase_[1].power_sensor_ != nullptr) {
|
|
this->phase_[1].power_sensor_->publish_state(this->get_active_power_b_());
|
|
}
|
|
if (this->phase_[2].power_sensor_ != nullptr) {
|
|
this->phase_[2].power_sensor_->publish_state(this->get_active_power_c_());
|
|
}
|
|
if (this->freq_sensor_ != nullptr) {
|
|
this->freq_sensor_->publish_state(this->get_frequency_());
|
|
}
|
|
this->status_clear_warning();
|
|
}
|
|
|
|
void ATM90E32Component::setup() {
|
|
ESP_LOGCONFIG(TAG, "Setting up ATM90E32Component...");
|
|
this->spi_setup();
|
|
|
|
uint16_t mmode0 = 0x185;
|
|
if (line_freq_ == 60) {
|
|
mmode0 |= 1 << 12;
|
|
}
|
|
|
|
this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A); // Perform soft reset
|
|
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
|
|
this->write16_(ATM90E32_REGISTER_METEREN, 0x0001); // Enable Metering
|
|
if (this->read16_(ATM90E32_REGISTER_LASTSPIDATA) != 0x0001) {
|
|
ESP_LOGW(TAG, "Could not initialize ATM90E32 IC, check SPI settings");
|
|
this->mark_failed();
|
|
return;
|
|
}
|
|
|
|
this->write16_(ATM90E32_REGISTER_ZXCONFIG, 0x0A55); // ZX2, ZX1, ZX0 pin config
|
|
this->write16_(ATM90E32_REGISTER_MMODE0, mmode0); // Mode Config (frequency set in main program)
|
|
this->write16_(ATM90E32_REGISTER_MMODE1, pga_gain_); // PGA Gain Configuration for Current Channels
|
|
this->write16_(ATM90E32_REGISTER_PSTARTTH, 0x0AFC); // Active Startup Power Threshold = 50%
|
|
this->write16_(ATM90E32_REGISTER_QSTARTTH, 0x0AEC); // Reactive Startup Power Threshold = 50%
|
|
this->write16_(ATM90E32_REGISTER_PPHASETH, 0x00BC); // Active Phase Threshold = 10%
|
|
this->write16_(ATM90E32_REGISTER_UGAINA, this->phase_[0].volt_gain_); // A Voltage rms gain
|
|
this->write16_(ATM90E32_REGISTER_IGAINA, this->phase_[0].ct_gain_); // A line current gain
|
|
this->write16_(ATM90E32_REGISTER_UGAINB, this->phase_[1].volt_gain_); // B Voltage rms gain
|
|
this->write16_(ATM90E32_REGISTER_IGAINB, this->phase_[1].ct_gain_); // B line current gain
|
|
this->write16_(ATM90E32_REGISTER_UGAINC, this->phase_[2].volt_gain_); // C Voltage rms gain
|
|
this->write16_(ATM90E32_REGISTER_IGAINC, this->phase_[2].ct_gain_); // C line current gain
|
|
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x0000); // end configuration
|
|
}
|
|
|
|
void ATM90E32Component::dump_config() {
|
|
ESP_LOGCONFIG("", "ATM90E32:");
|
|
LOG_PIN(" CS Pin: ", this->cs_);
|
|
if (this->is_failed()) {
|
|
ESP_LOGE(TAG, "Communication with ATM90E32 failed!");
|
|
}
|
|
LOG_UPDATE_INTERVAL(this);
|
|
LOG_SENSOR(" ", "Voltage A", this->phase_[0].voltage_sensor_);
|
|
LOG_SENSOR(" ", "Current A", this->phase_[0].current_sensor_);
|
|
LOG_SENSOR(" ", "Power A", this->phase_[0].power_sensor_);
|
|
LOG_SENSOR(" ", "Voltage B", this->phase_[1].voltage_sensor_);
|
|
LOG_SENSOR(" ", "Current B", this->phase_[1].current_sensor_);
|
|
LOG_SENSOR(" ", "Power B", this->phase_[1].power_sensor_);
|
|
LOG_SENSOR(" ", "Voltage C", this->phase_[2].voltage_sensor_);
|
|
LOG_SENSOR(" ", "Current C", this->phase_[2].current_sensor_);
|
|
LOG_SENSOR(" ", "Power C", this->phase_[2].power_sensor_);
|
|
LOG_SENSOR(" ", "Frequency", this->freq_sensor_)
|
|
}
|
|
float ATM90E32Component::get_setup_priority() const { return setup_priority::DATA; }
|
|
|
|
uint16_t ATM90E32Component::read16_(uint16_t a_register) {
|
|
uint8_t addrh = (1 << 7) | ((a_register >> 8) & 0x03);
|
|
uint8_t addrl = (a_register & 0xFF);
|
|
uint8_t data[2];
|
|
uint16_t output;
|
|
|
|
this->enable();
|
|
delayMicroseconds(10);
|
|
this->write_byte(addrh);
|
|
this->write_byte(addrl);
|
|
delayMicroseconds(4);
|
|
this->read_array(data, 2);
|
|
this->disable();
|
|
|
|
output = (uint16_t(data[0] & 0xFF) << 8) | (data[1] & 0xFF);
|
|
ESP_LOGVV(TAG, "read16_ 0x%04X output 0x%04X", a_register, output);
|
|
return output;
|
|
}
|
|
|
|
int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
|
|
uint16_t val_h = this->read16_(addr_h);
|
|
uint16_t val_l = this->read16_(addr_l);
|
|
int32_t val = (val_h << 16) | val_l;
|
|
|
|
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,
|
|
val);
|
|
|
|
return val;
|
|
}
|
|
|
|
void ATM90E32Component::write16_(uint16_t a_register, uint16_t val) {
|
|
uint8_t addrh = (a_register >> 8) & 0x03;
|
|
uint8_t addrl = (a_register & 0xFF);
|
|
|
|
ESP_LOGVV(TAG, "write16_ 0x%04X val 0x%04X", a_register, val);
|
|
this->enable();
|
|
delayMicroseconds(10);
|
|
this->write_byte(addrh);
|
|
this->write_byte(addrl);
|
|
delayMicroseconds(4);
|
|
this->write_byte((val >> 8) & 0xff);
|
|
this->write_byte(val & 0xFF);
|
|
this->disable();
|
|
}
|
|
|
|
float ATM90E32Component::get_line_voltage_a_() {
|
|
uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSA);
|
|
return (float) voltage / 100;
|
|
}
|
|
float ATM90E32Component::get_line_voltage_b_() {
|
|
uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSB);
|
|
return (float) voltage / 100;
|
|
}
|
|
float ATM90E32Component::get_line_voltage_c_() {
|
|
uint16_t voltage = this->read16_(ATM90E32_REGISTER_URMSC);
|
|
return (float) voltage / 100;
|
|
}
|
|
float ATM90E32Component::get_line_current_a_() {
|
|
uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSA);
|
|
return (float) current / 1000;
|
|
}
|
|
float ATM90E32Component::get_line_current_b_() {
|
|
uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSB);
|
|
return (float) current / 1000;
|
|
}
|
|
float ATM90E32Component::get_line_current_c_() {
|
|
uint16_t current = this->read16_(ATM90E32_REGISTER_IRMSC);
|
|
return (float) current / 1000;
|
|
}
|
|
float ATM90E32Component::get_active_power_a_() {
|
|
int val = this->read32_(ATM90E32_REGISTER_PMEANA, ATM90E32_REGISTER_PMEANALSB);
|
|
return val * 0.00032f;
|
|
}
|
|
float ATM90E32Component::get_active_power_b_() {
|
|
int val = this->read32_(ATM90E32_REGISTER_PMEANB, ATM90E32_REGISTER_PMEANBLSB);
|
|
return val * 0.00032f;
|
|
}
|
|
float ATM90E32Component::get_active_power_c_() {
|
|
int val = this->read32_(ATM90E32_REGISTER_PMEANC, ATM90E32_REGISTER_PMEANCLSB);
|
|
return val * 0.00032f;
|
|
}
|
|
float ATM90E32Component::get_frequency_() {
|
|
uint16_t freq = this->read16_(ATM90E32_REGISTER_FREQ);
|
|
return (float) freq / 100;
|
|
}
|
|
} // namespace atm90e32
|
|
} // namespace esphome
|