mirror of
https://github.com/esphome/esphome.git
synced 2024-12-24 14:34:54 +01:00
pulse_counter_ulp: Count pulses not edges
- Count both separately in ULP program - Manage pin inversion manually in update() - Take into account configured mode
This commit is contained in:
parent
40b18666c9
commit
c57ad9fff9
3 changed files with 58 additions and 25 deletions
|
@ -51,11 +51,12 @@ std::unique_ptr<UlpProgram> UlpProgram::start(const Config &config) {
|
|||
*
|
||||
* Note that the ULP reads only the lower 16 bits of these variables.
|
||||
*/
|
||||
ulp_edge_count = 0;
|
||||
ulp_rising_edge_count = 0;
|
||||
ulp_falling_edge_count = 0;
|
||||
ulp_run_count = 0;
|
||||
ulp_debounce_counter = 3;
|
||||
ulp_debounce_max_count = config.debounce_;
|
||||
ulp_next_edge = 0;
|
||||
ulp_next_edge = static_cast<uint16_t>(!config.pin_->digital_read());
|
||||
ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */
|
||||
ulp_mean_exec_time = config.sleep_duration_ / microseconds{1};
|
||||
|
||||
|
@ -80,18 +81,22 @@ std::unique_ptr<UlpProgram> UlpProgram::start(const Config &config) {
|
|||
}
|
||||
|
||||
UlpProgram::State UlpProgram::pop_state() {
|
||||
// TODO count edges separately
|
||||
State state = UlpProgram::peek_state();
|
||||
ulp_edge_count = 0;
|
||||
ulp_rising_edge_count = 0;
|
||||
ulp_falling_edge_count = 0;
|
||||
ulp_run_count = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
UlpProgram::State UlpProgram::peek_state() const {
|
||||
auto edge_count = static_cast<uint16_t>(ulp_edge_count);
|
||||
auto rising_edge_count = static_cast<uint16_t>(ulp_rising_edge_count);
|
||||
auto falling_edge_count = static_cast<uint16_t>(ulp_falling_edge_count);
|
||||
auto run_count = static_cast<uint16_t>(ulp_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};
|
||||
return {.rising_edge_count_ = rising_edge_count,
|
||||
.falling_edge_count_ = falling_edge_count,
|
||||
.run_count_ = run_count,
|
||||
.mean_exec_time_ = mean_exec_time};
|
||||
}
|
||||
|
||||
void UlpProgram::set_mean_exec_time(microseconds mean_exec_time) {
|
||||
|
@ -112,7 +117,7 @@ void PulseCounterUlpSensor::setup() {
|
|||
ESP_LOGD(TAG, "Woke up from sleep, skipping set-up of ULP program");
|
||||
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;
|
||||
this->last_time_ = clock::now() - state.run_count_ * state.mean_exec_time_;
|
||||
}
|
||||
|
||||
if (!this->storage_) {
|
||||
|
@ -126,8 +131,8 @@ void PulseCounterUlpSensor::dump_config() {
|
|||
LOG_PIN(" Pin: ", this->config_.pin_);
|
||||
ESP_LOGCONFIG(TAG, " Rising Edge: %s", to_string(this->config_.rising_edge_mode_));
|
||||
ESP_LOGCONFIG(TAG, " Falling Edge: %s", to_string(this->config_.falling_edge_mode_));
|
||||
ESP_LOGCONFIG(TAG, " Sleep Duration: " PRIu32 " µs", this->config_.sleep_duration_ / microseconds{1});
|
||||
ESP_LOGCONFIG(TAG, " Debounce: " PRIu16, this->config_.debounce_);
|
||||
ESP_LOGCONFIG(TAG, " Sleep Duration: %" PRIu32 " µs", this->config_.sleep_duration_ / microseconds{1});
|
||||
ESP_LOGCONFIG(TAG, " Debounce: %" PRIu16, this->config_.debounce_);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
|
@ -137,12 +142,23 @@ void PulseCounterUlpSensor::update() {
|
|||
return;
|
||||
}
|
||||
UlpProgram::State raw = this->storage_->pop_state();
|
||||
// Since ULP can't use the GPIOPin abstraction, pin inversion needs to be
|
||||
// manually implemented.
|
||||
int32_t pulse_count;
|
||||
if (this->config_.pin_->is_inverted()) {
|
||||
pulse_count = static_cast<int32_t>(config_.rising_edge_mode_) * raw.falling_edge_count_ +
|
||||
static_cast<int32_t>(config_.falling_edge_mode_) * raw.rising_edge_count_;
|
||||
} else {
|
||||
pulse_count = static_cast<int32_t>(config_.rising_edge_mode_) * raw.rising_edge_count_ +
|
||||
static_cast<int32_t>(config_.falling_edge_mode_) * raw.falling_edge_count_;
|
||||
}
|
||||
clock::time_point now = clock::now();
|
||||
clock::duration interval = now - this->last_time_;
|
||||
if (interval != clock::duration::zero()) {
|
||||
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);
|
||||
this->storage_->set_mean_exec_time(std::chrono::duration_cast<microseconds>(interval / raw.run_count_));
|
||||
float value = std::chrono::minutes{1} * static_cast<float>(pulse_count) / interval; // pulses per minute
|
||||
ESP_LOGD(TAG, "'%s': Retrieved counter: %" PRIu32 " pulses at %0.2f pulses/min", this->get_name().c_str(),
|
||||
pulse_count, value);
|
||||
this->publish_state(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,10 @@ class UlpProgram {
|
|||
uint16_t debounce_;
|
||||
};
|
||||
struct State {
|
||||
uint16_t edge_count;
|
||||
uint16_t run_count;
|
||||
microseconds mean_exec_time;
|
||||
uint16_t rising_edge_count_;
|
||||
uint16_t falling_edge_count_;
|
||||
uint16_t run_count_;
|
||||
microseconds mean_exec_time_;
|
||||
};
|
||||
State pop_state();
|
||||
State peek_state() const;
|
||||
|
|
|
@ -50,9 +50,14 @@ debounce_counter:
|
|||
debounce_max_count:
|
||||
.long 0
|
||||
|
||||
/* Number of signal edges acquired since last read */
|
||||
.global edge_count
|
||||
edge_count:
|
||||
/* Number of rising signal edges acquired since last read */
|
||||
.global rising_edge_count
|
||||
rising_edge_count:
|
||||
.long 0
|
||||
|
||||
/* Number of falling signal edges acquired since last read */
|
||||
.global falling_edge_count
|
||||
falling_edge_count:
|
||||
.long 0
|
||||
|
||||
/* Number of times program run since last read */
|
||||
|
@ -161,13 +166,24 @@ edge_detected:
|
|||
add r2, r2, 1
|
||||
and r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* Increment edge_count */
|
||||
move r3, edge_count
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* Increment edge_count_total */
|
||||
move r3, edge_count_total
|
||||
/* Jump to increment of current edge counter */
|
||||
add r2, r2, 0 /* dummy ADD to use "jump if ALU result is zero" */
|
||||
jump rising, eq
|
||||
|
||||
.global falling
|
||||
falling:
|
||||
/* Increment falling_edge_count */
|
||||
move r3, falling_edge_count
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* End program */
|
||||
halt
|
||||
|
||||
.global rising
|
||||
rising:
|
||||
/* Increment rising_edge_count */
|
||||
move r3, rising_edge_count
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 1
|
||||
st r2, r3, 0
|
||||
|
|
Loading…
Reference in a new issue