mirror of
https://github.com/esphome/esphome.git
synced 2026-05-26 19:26:25 +08:00
[ultrasonic] Fix ISR edge detection with debounce and trigger filtering (#15014)
This commit is contained in:
committed by
Jesse Hills
parent
de3292c828
commit
bbfe324dd6
@@ -6,11 +6,17 @@ namespace esphome::ultrasonic {
|
|||||||
|
|
||||||
static const char *const TAG = "ultrasonic.sensor";
|
static const char *const TAG = "ultrasonic.sensor";
|
||||||
|
|
||||||
|
static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us of each other (noise filtering)
|
||||||
|
static constexpr uint32_t START_DELAY_US = 100; // Ignore edges within 100us of trigger (filters bleed-through)
|
||||||
static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start
|
static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start
|
||||||
|
|
||||||
void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) {
|
void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) {
|
||||||
uint32_t now = micros();
|
uint32_t now = micros();
|
||||||
if (arg->echo_pin_isr.digital_read()) {
|
// Ignore edges after measurement complete or too soon after trigger pulse
|
||||||
|
if (arg->echo_end || (now - arg->measurement_start_us) <= START_DELAY_US) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) {
|
||||||
arg->echo_start_us = now;
|
arg->echo_start_us = now;
|
||||||
arg->echo_start = true;
|
arg->echo_start = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -21,15 +27,14 @@ void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) {
|
|||||||
|
|
||||||
void IRAM_ATTR UltrasonicSensorComponent::send_trigger_pulse_() {
|
void IRAM_ATTR UltrasonicSensorComponent::send_trigger_pulse_() {
|
||||||
InterruptLock lock;
|
InterruptLock lock;
|
||||||
this->store_.echo_start_us = 0;
|
|
||||||
this->store_.echo_end_us = 0;
|
|
||||||
this->store_.echo_start = false;
|
this->store_.echo_start = false;
|
||||||
this->store_.echo_end = false;
|
this->store_.echo_end = false;
|
||||||
|
this->store_.measurement_start_us = micros();
|
||||||
this->trigger_pin_isr_.digital_write(true);
|
this->trigger_pin_isr_.digital_write(true);
|
||||||
delayMicroseconds(this->pulse_time_us_);
|
delayMicroseconds(this->pulse_time_us_);
|
||||||
this->trigger_pin_isr_.digital_write(false);
|
this->trigger_pin_isr_.digital_write(false);
|
||||||
this->measurement_pending_ = true;
|
this->measurement_pending_ = true;
|
||||||
this->measurement_start_us_ = micros();
|
this->measurement_start_us_ = this->store_.measurement_start_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UltrasonicSensorComponent::setup() {
|
void UltrasonicSensorComponent::setup() {
|
||||||
@@ -37,7 +42,6 @@ void UltrasonicSensorComponent::setup() {
|
|||||||
this->trigger_pin_->digital_write(false);
|
this->trigger_pin_->digital_write(false);
|
||||||
this->trigger_pin_isr_ = this->trigger_pin_->to_isr();
|
this->trigger_pin_isr_ = this->trigger_pin_->to_isr();
|
||||||
this->echo_pin_->setup();
|
this->echo_pin_->setup();
|
||||||
this->store_.echo_pin_isr = this->echo_pin_->to_isr();
|
|
||||||
this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE);
|
this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,17 +81,10 @@ void UltrasonicSensorComponent::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->store_.echo_end) {
|
if (this->store_.echo_end) {
|
||||||
float result;
|
uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us;
|
||||||
if (this->store_.echo_start) {
|
ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration);
|
||||||
uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us;
|
float result = UltrasonicSensorComponent::us_to_m(pulse_duration);
|
||||||
ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us",
|
ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result);
|
||||||
this->store_.echo_start_us - this->measurement_start_us_, pulse_duration);
|
|
||||||
result = UltrasonicSensorComponent::us_to_m(pulse_duration);
|
|
||||||
ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result);
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str());
|
|
||||||
result = NAN;
|
|
||||||
}
|
|
||||||
this->publish_state(result);
|
this->publish_state(result);
|
||||||
this->measurement_pending_ = false;
|
this->measurement_pending_ = false;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ namespace esphome::ultrasonic {
|
|||||||
struct UltrasonicSensorStore {
|
struct UltrasonicSensorStore {
|
||||||
static void gpio_intr(UltrasonicSensorStore *arg);
|
static void gpio_intr(UltrasonicSensorStore *arg);
|
||||||
|
|
||||||
ISRInternalGPIOPin echo_pin_isr;
|
volatile uint32_t measurement_start_us{0};
|
||||||
volatile uint32_t wait_start_us{0};
|
|
||||||
volatile uint32_t echo_start_us{0};
|
volatile uint32_t echo_start_us{0};
|
||||||
volatile uint32_t echo_end_us{0};
|
volatile uint32_t echo_end_us{0};
|
||||||
volatile bool echo_start{false};
|
volatile bool echo_start{false};
|
||||||
|
|||||||
Reference in New Issue
Block a user