mirror of
https://github.com/esphome/esphome.git
synced 2024-11-23 23:48:11 +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.
|
* 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_run_count = 0;
|
||||||
ulp_debounce_counter = 3;
|
ulp_debounce_counter = 3;
|
||||||
ulp_debounce_max_count = config.debounce_;
|
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_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */
|
||||||
ulp_mean_exec_time = config.sleep_duration_ / microseconds{1};
|
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() {
|
UlpProgram::State UlpProgram::pop_state() {
|
||||||
// TODO count edges separately
|
|
||||||
State state = UlpProgram::peek_state();
|
State state = UlpProgram::peek_state();
|
||||||
ulp_edge_count = 0;
|
ulp_rising_edge_count = 0;
|
||||||
|
ulp_falling_edge_count = 0;
|
||||||
ulp_run_count = 0;
|
ulp_run_count = 0;
|
||||||
return state;
|
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 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 run_count = static_cast<uint16_t>(ulp_run_count);
|
||||||
auto mean_exec_time = microseconds{1} * static_cast<uint16_t>(ulp_mean_exec_time);
|
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) {
|
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");
|
ESP_LOGD(TAG, "Woke up from sleep, skipping set-up of ULP program");
|
||||||
this->storage_ = std::unique_ptr<UlpProgram>(new UlpProgram);
|
this->storage_ = std::unique_ptr<UlpProgram>(new UlpProgram);
|
||||||
UlpProgram::State state = this->storage_->peek_state();
|
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_) {
|
if (!this->storage_) {
|
||||||
|
@ -126,8 +131,8 @@ void PulseCounterUlpSensor::dump_config() {
|
||||||
LOG_PIN(" Pin: ", this->config_.pin_);
|
LOG_PIN(" Pin: ", this->config_.pin_);
|
||||||
ESP_LOGCONFIG(TAG, " Rising Edge: %s", to_string(this->config_.rising_edge_mode_));
|
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, " 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, " Sleep Duration: %" PRIu32 " µs", this->config_.sleep_duration_ / microseconds{1});
|
||||||
ESP_LOGCONFIG(TAG, " Debounce: " PRIu16, this->config_.debounce_);
|
ESP_LOGCONFIG(TAG, " Debounce: %" PRIu16, this->config_.debounce_);
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +142,23 @@ void PulseCounterUlpSensor::update() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UlpProgram::State raw = this->storage_->pop_state();
|
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::time_point now = clock::now();
|
||||||
clock::duration interval = now - this->last_time_;
|
clock::duration interval = now - this->last_time_;
|
||||||
if (interval != clock::duration::zero()) {
|
if (interval != clock::duration::zero()) {
|
||||||
this->storage_->set_mean_exec_time(std::chrono::duration_cast<microseconds>(interval / 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
|
float value = std::chrono::minutes{1} * static_cast<float>(pulse_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': Retrieved counter: %" PRIu32 " pulses at %0.2f pulses/min", this->get_name().c_str(),
|
||||||
|
pulse_count, value);
|
||||||
this->publish_state(value);
|
this->publish_state(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,10 @@ class UlpProgram {
|
||||||
uint16_t debounce_;
|
uint16_t debounce_;
|
||||||
};
|
};
|
||||||
struct State {
|
struct State {
|
||||||
uint16_t edge_count;
|
uint16_t rising_edge_count_;
|
||||||
uint16_t run_count;
|
uint16_t falling_edge_count_;
|
||||||
microseconds mean_exec_time;
|
uint16_t run_count_;
|
||||||
|
microseconds mean_exec_time_;
|
||||||
};
|
};
|
||||||
State pop_state();
|
State pop_state();
|
||||||
State peek_state() const;
|
State peek_state() const;
|
||||||
|
|
|
@ -50,9 +50,14 @@ debounce_counter:
|
||||||
debounce_max_count:
|
debounce_max_count:
|
||||||
.long 0
|
.long 0
|
||||||
|
|
||||||
/* Number of signal edges acquired since last read */
|
/* Number of rising signal edges acquired since last read */
|
||||||
.global edge_count
|
.global rising_edge_count
|
||||||
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
|
.long 0
|
||||||
|
|
||||||
/* Number of times program run since last read */
|
/* Number of times program run since last read */
|
||||||
|
@ -161,13 +166,24 @@ edge_detected:
|
||||||
add r2, r2, 1
|
add r2, r2, 1
|
||||||
and r2, r2, 1
|
and r2, r2, 1
|
||||||
st r2, r3, 0
|
st r2, r3, 0
|
||||||
/* Increment edge_count */
|
/* Jump to increment of current edge counter */
|
||||||
move r3, edge_count
|
add r2, r2, 0 /* dummy ADD to use "jump if ALU result is zero" */
|
||||||
ld r2, r3, 0
|
jump rising, eq
|
||||||
add r2, r2, 1
|
|
||||||
st r2, r3, 0
|
.global falling
|
||||||
/* Increment edge_count_total */
|
falling:
|
||||||
move r3, edge_count_total
|
/* 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
|
ld r2, r3, 0
|
||||||
add r2, r2, 1
|
add r2, r2, 1
|
||||||
st r2, r3, 0
|
st r2, r3, 0
|
||||||
|
|
Loading…
Reference in a new issue