mirror of
https://github.com/esphome/esphome.git
synced 2024-12-24 14:34:54 +01:00
pulse_counter_ulp: Store mean_exec_time in Ulp Program
This lets the estimated interval survive sleep, and finally provide reasonable interval estimates over deep sleep periods.
This commit is contained in:
parent
2b453289a9
commit
4a8907d70d
3 changed files with 28 additions and 24 deletions
|
@ -57,6 +57,7 @@ std::unique_ptr<UlpProgram> UlpProgram::start(gpio_num_t gpio_num, microseconds
|
|||
ulp_debounce_max_count = 3;
|
||||
ulp_next_edge = 0;
|
||||
ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */
|
||||
ulp_mean_exec_time = sleep_duration / microseconds{1};
|
||||
|
||||
/* Initialize selected GPIO as RTC IO, enable input */
|
||||
rtc_gpio_init(gpio_num);
|
||||
|
@ -78,19 +79,23 @@ std::unique_ptr<UlpProgram> UlpProgram::start(gpio_num_t gpio_num, microseconds
|
|||
return std::unique_ptr<UlpProgram>(new UlpProgram());
|
||||
}
|
||||
|
||||
UlpProgram::state UlpProgram::pop_state() {
|
||||
UlpProgram::State UlpProgram::pop_state() {
|
||||
// TODO count edges separately
|
||||
auto edge_count = static_cast<uint16_t>(ulp_edge_count);
|
||||
auto run_count = static_cast<uint16_t>(ulp_run_count);
|
||||
State state = UlpProgram::peek_state();
|
||||
ulp_edge_count = 0;
|
||||
ulp_run_count = 0;
|
||||
return {.edge_count = edge_count, .run_count = run_count};
|
||||
return state;
|
||||
}
|
||||
|
||||
UlpProgram::state UlpProgram::peek_state() const {
|
||||
UlpProgram::State UlpProgram::peek_state() const {
|
||||
auto edge_count = static_cast<uint16_t>(ulp_edge_count);
|
||||
auto run_count = static_cast<uint16_t>(ulp_run_count);
|
||||
return {.edge_count = edge_count, .run_count = run_count};
|
||||
auto mean_exec_time = microseconds{1} * static_cast<uint16_t>(ulp_mean_exec_time);
|
||||
return {.edge_count = edge_count, .run_count = run_count, .mean_exec_time = mean_exec_time};
|
||||
}
|
||||
|
||||
void UlpProgram::set_mean_exec_time(microseconds mean_exec_time) {
|
||||
ulp_mean_exec_time = static_cast<uint16_t>(mean_exec_time / microseconds{1});
|
||||
}
|
||||
|
||||
/* === END ULP ===*/
|
||||
|
@ -106,9 +111,9 @@ void PulseCounterUlpSensor::setup() {
|
|||
this->rising_edge_mode, this->falling_edge_mode);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Woke up from sleep, skipping set-up of ULP program");
|
||||
// TODO need to store estimate in UlpProgram and load it in load. Maybe.
|
||||
// this->storage_ = UlpProgram::load();
|
||||
// this->last_time = clock::now() - this->storage_->peek_state().run_count * this->storage_->estimate ;
|
||||
this->storage_ = std::unique_ptr<UlpProgram>(new UlpProgram);
|
||||
UlpProgram::State state = this->storage_->peek_state();
|
||||
this->last_time_ = clock::now() - state.run_count * state.mean_exec_time;
|
||||
}
|
||||
|
||||
if (!this->storage_) {
|
||||
|
@ -135,16 +140,13 @@ void PulseCounterUlpSensor::update() {
|
|||
if (!this->storage_) {
|
||||
return;
|
||||
}
|
||||
UlpProgram::state raw = this->storage_->pop_state();
|
||||
UlpProgram::State raw = this->storage_->pop_state();
|
||||
clock::time_point now = clock::now();
|
||||
clock::duration interval = now - this->last_time_;
|
||||
auto estimated_interval = ulp_mean_exec_time_ * raw.run_count;
|
||||
if (interval != clock::duration::zero()) {
|
||||
ulp_mean_exec_time_ = interval / static_cast<float>(raw.run_count);
|
||||
this->storage_->set_mean_exec_time(std::chrono::duration_cast<microseconds>(interval / raw.run_count));
|
||||
float value = std::chrono::minutes{1} * static_cast<float>(raw.edge_count) / interval; // pulses per minute
|
||||
ESP_LOGD(TAG, "'%s': Retrieved counter: %0.2f pulses/min", this->get_name().c_str(), value);
|
||||
ESP_LOGD(TAG, "'%s': Interval: %0.2f\nEstimated: %0.2f", this->get_name().c_str(),
|
||||
1.0f * interval / std::chrono::seconds{1}, 1.0f * estimated_interval / std::chrono::seconds{1});
|
||||
this->publish_state(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,16 +20,17 @@ using microseconds = std::chrono::duration<uint32_t, std::micro>;
|
|||
|
||||
class UlpProgram {
|
||||
public:
|
||||
struct state {
|
||||
struct State {
|
||||
uint16_t edge_count;
|
||||
uint16_t run_count;
|
||||
microseconds mean_exec_time;
|
||||
};
|
||||
state pop_state();
|
||||
state peek_state() const;
|
||||
State pop_state();
|
||||
State peek_state() const;
|
||||
void set_mean_exec_time(microseconds mean_exec_time);
|
||||
|
||||
static std::unique_ptr<UlpProgram> start(gpio_num_t gpio_num, microseconds sleep_duration, CountMode rising_edge_mode,
|
||||
CountMode falling_edge_mode);
|
||||
// static std::unique_ptr<UlpProgram> load();
|
||||
};
|
||||
|
||||
class PulseCounterUlpSensor : public sensor::Sensor, public PollingComponent {
|
||||
|
@ -39,11 +40,7 @@ class PulseCounterUlpSensor : public sensor::Sensor, public PollingComponent {
|
|||
void set_pin(InternalGPIOPin *pin) { pin_ = pin; }
|
||||
void set_rising_edge_mode(CountMode mode) { this->rising_edge_mode = mode; }
|
||||
void set_falling_edge_mode(CountMode mode) { this->falling_edge_mode = mode; }
|
||||
void set_sleep_duration(uint32_t duration_us) {
|
||||
this->sleep_duration_ = duration_us * microseconds{1};
|
||||
// Initial estimate assumes sleep duration >> execution time
|
||||
this->ulp_mean_exec_time_ = duration_us * microseconds{1};
|
||||
}
|
||||
void set_sleep_duration(uint32_t duration_us) { this->sleep_duration_ = duration_us * microseconds{1}; }
|
||||
void set_total_sensor(sensor::Sensor *total_sensor) { total_sensor_ = total_sensor; }
|
||||
|
||||
void set_total_pulses(uint32_t pulses);
|
||||
|
@ -60,7 +57,6 @@ class PulseCounterUlpSensor : public sensor::Sensor, public PollingComponent {
|
|||
CountMode falling_edge_mode{CountMode::disable};
|
||||
std::unique_ptr<UlpProgram> storage_{};
|
||||
clock::time_point last_time_{};
|
||||
std::chrono::duration<float> ulp_mean_exec_time_{};
|
||||
microseconds sleep_duration_{20000};
|
||||
uint32_t current_total_{0};
|
||||
sensor::Sensor *total_sensor_{nullptr};
|
||||
|
|
|
@ -71,6 +71,12 @@ edge_count_total:
|
|||
io_number:
|
||||
.long 0
|
||||
|
||||
/* Estimate of how long each execution of the ULP program takes. Managed
|
||||
* entirely by main program, it is only defined here to survive deep sleep */
|
||||
.global mean_exec_time
|
||||
mean_exec_time:
|
||||
.long 0
|
||||
|
||||
/* Code goes into .text section */
|
||||
.text
|
||||
.global entry
|
||||
|
|
Loading…
Reference in a new issue