mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:53:26 +00:00
[bl0906] Disable loop when idle and introduce BL0906Stage enum (#15884)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@@ -20,58 +20,77 @@ constexpr uint8_t bl0906_checksum(const uint8_t address, const DataPacket *data)
|
||||
}
|
||||
|
||||
void BL0906::loop() {
|
||||
if (this->current_channel_ == UINT8_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (this->available())
|
||||
this->flush();
|
||||
|
||||
if (this->current_channel_ == 0) {
|
||||
if (this->current_stage_ == STAGE_IDLE) {
|
||||
// Woken up between cycles to drain the action queue. Go back to sleep.
|
||||
this->handle_actions_();
|
||||
this->disable_loop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->current_stage_ == STAGE_TEMP) {
|
||||
// Temperature
|
||||
this->read_data_(BL0906_TEMPERATURE, BL0906_TREF, this->temperature_sensor_);
|
||||
} else if (this->current_channel_ == 1) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_1) {
|
||||
this->read_data_(BL0906_I_1_RMS, BL0906_IREF, this->current_1_sensor_);
|
||||
this->read_data_(BL0906_WATT_1, BL0906_PREF, this->power_1_sensor_);
|
||||
this->read_data_(BL0906_CF_1_CNT, BL0906_EREF, this->energy_1_sensor_);
|
||||
} else if (this->current_channel_ == 2) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_2) {
|
||||
this->read_data_(BL0906_I_2_RMS, BL0906_IREF, this->current_2_sensor_);
|
||||
this->read_data_(BL0906_WATT_2, BL0906_PREF, this->power_2_sensor_);
|
||||
this->read_data_(BL0906_CF_2_CNT, BL0906_EREF, this->energy_2_sensor_);
|
||||
} else if (this->current_channel_ == 3) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_3) {
|
||||
this->read_data_(BL0906_I_3_RMS, BL0906_IREF, this->current_3_sensor_);
|
||||
this->read_data_(BL0906_WATT_3, BL0906_PREF, this->power_3_sensor_);
|
||||
this->read_data_(BL0906_CF_3_CNT, BL0906_EREF, this->energy_3_sensor_);
|
||||
} else if (this->current_channel_ == 4) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_4) {
|
||||
this->read_data_(BL0906_I_4_RMS, BL0906_IREF, this->current_4_sensor_);
|
||||
this->read_data_(BL0906_WATT_4, BL0906_PREF, this->power_4_sensor_);
|
||||
this->read_data_(BL0906_CF_4_CNT, BL0906_EREF, this->energy_4_sensor_);
|
||||
} else if (this->current_channel_ == 5) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_5) {
|
||||
this->read_data_(BL0906_I_5_RMS, BL0906_IREF, this->current_5_sensor_);
|
||||
this->read_data_(BL0906_WATT_5, BL0906_PREF, this->power_5_sensor_);
|
||||
this->read_data_(BL0906_CF_5_CNT, BL0906_EREF, this->energy_5_sensor_);
|
||||
} else if (this->current_channel_ == 6) {
|
||||
} else if (this->current_stage_ == STAGE_CHANNEL_6) {
|
||||
this->read_data_(BL0906_I_6_RMS, BL0906_IREF, this->current_6_sensor_);
|
||||
this->read_data_(BL0906_WATT_6, BL0906_PREF, this->power_6_sensor_);
|
||||
this->read_data_(BL0906_CF_6_CNT, BL0906_EREF, this->energy_6_sensor_);
|
||||
} else if (this->current_channel_ == UINT8_MAX - 2) {
|
||||
} else if (this->current_stage_ == STAGE_FREQ) {
|
||||
// Frequency
|
||||
this->read_data_(BL0906_FREQUENCY, BL0906_FREF, frequency_sensor_);
|
||||
this->read_data_(BL0906_FREQUENCY, BL0906_FREF, this->frequency_sensor_);
|
||||
// Voltage
|
||||
this->read_data_(BL0906_V_RMS, BL0906_UREF, voltage_sensor_);
|
||||
} else if (this->current_channel_ == UINT8_MAX - 1) {
|
||||
this->read_data_(BL0906_V_RMS, BL0906_UREF, this->voltage_sensor_);
|
||||
} else if (this->current_stage_ == STAGE_POWER) {
|
||||
// Total power
|
||||
this->read_data_(BL0906_WATT_SUM, BL0906_WATT, this->total_power_sensor_);
|
||||
// Total Energy
|
||||
this->read_data_(BL0906_CF_SUM_CNT, BL0906_CF, this->total_energy_sensor_);
|
||||
} else {
|
||||
this->current_channel_ = UINT8_MAX - 2; // Go to frequency and voltage
|
||||
return;
|
||||
}
|
||||
this->current_channel_++;
|
||||
this->advance_stage_();
|
||||
this->handle_actions_();
|
||||
}
|
||||
|
||||
void BL0906::advance_stage_() {
|
||||
switch (this->current_stage_) {
|
||||
case STAGE_CHANNEL_6:
|
||||
this->current_stage_ = STAGE_FREQ;
|
||||
break;
|
||||
case STAGE_FREQ:
|
||||
this->current_stage_ = STAGE_POWER;
|
||||
break;
|
||||
case STAGE_POWER:
|
||||
// Cycle complete; sleep until the next update().
|
||||
this->current_stage_ = STAGE_IDLE;
|
||||
this->disable_loop();
|
||||
break;
|
||||
default:
|
||||
this->current_stage_ = static_cast<BL0906Stage>(this->current_stage_ + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BL0906::setup() {
|
||||
while (this->available())
|
||||
this->flush();
|
||||
@@ -85,12 +104,20 @@ void BL0906::setup() {
|
||||
this->bias_correction_(BL0906_RMSOS_6, 0.01200, 0); // Calibration current_6
|
||||
|
||||
this->write_array(USR_WRPROT_ONLYREAD, sizeof(USR_WRPROT_ONLYREAD));
|
||||
|
||||
// Loop stays idle until the first update() or enqueued action.
|
||||
this->disable_loop();
|
||||
}
|
||||
|
||||
void BL0906::update() { this->current_channel_ = 0; }
|
||||
void BL0906::update() {
|
||||
this->current_stage_ = STAGE_TEMP;
|
||||
this->enable_loop();
|
||||
}
|
||||
|
||||
size_t BL0906::enqueue_action_(ActionCallbackFuncPtr function) {
|
||||
this->action_queue_.push_back(function);
|
||||
// Ensure the queue is serviced even if the read cycle has already completed.
|
||||
this->enable_loop();
|
||||
return this->action_queue_.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,22 @@
|
||||
namespace esphome {
|
||||
namespace bl0906 {
|
||||
|
||||
// Stage values for the read state machine. After STAGE_CHANNEL_6 the state machine
|
||||
// jumps to the two sentinel stages below, then to STAGE_IDLE which marks the cycle
|
||||
// as complete and disables the loop.
|
||||
enum BL0906Stage : uint8_t {
|
||||
STAGE_TEMP = 0, // chip temperature
|
||||
STAGE_CHANNEL_1 = 1, // per-phase current + power + energy
|
||||
STAGE_CHANNEL_2 = 2,
|
||||
STAGE_CHANNEL_3 = 3,
|
||||
STAGE_CHANNEL_4 = 4,
|
||||
STAGE_CHANNEL_5 = 5,
|
||||
STAGE_CHANNEL_6 = 6,
|
||||
STAGE_FREQ = UINT8_MAX - 2, // frequency + voltage
|
||||
STAGE_POWER = UINT8_MAX - 1, // total power + total energy
|
||||
STAGE_IDLE = UINT8_MAX, // cycle complete
|
||||
};
|
||||
|
||||
struct DataPacket { // NOLINT(altera-struct-pack-align)
|
||||
uint8_t l{0};
|
||||
uint8_t m{0};
|
||||
@@ -79,7 +95,8 @@ class BL0906 : public PollingComponent, public uart::UARTDevice {
|
||||
|
||||
void bias_correction_(uint8_t address, float measurements, float correction);
|
||||
|
||||
uint8_t current_channel_{0};
|
||||
BL0906Stage current_stage_{STAGE_IDLE};
|
||||
void advance_stage_();
|
||||
size_t enqueue_action_(ActionCallbackFuncPtr function);
|
||||
void handle_actions_();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user