use embedded_hal::digital::OutputPin;
use embedded_hal::delay::DelayNs;
use crate::error::Error;
pub trait PulseReader {
fn measure_pulse(&mut self) -> Option<u32>;
}
pub struct Urm37Pwm<TRIG, READER, DELAY>
where
TRIG: OutputPin,
READER: PulseReader,
DELAY: DelayNs,
{
trig: TRIG,
pulse_reader: READER,
delay: DELAY,
trigger_duration_ms: u32,
max_timeout_us: u32,
}
impl<TRIG, READER, DELAY> Urm37Pwm<TRIG, READER, DELAY>
where
TRIG: OutputPin,
READER: PulseReader,
DELAY: DelayNs,
{
pub fn new(mut trig: TRIG, pulse_reader: READER, delay: DELAY) -> Result<Self, TRIG::Error> {
trig.set_high()?;
Ok(Self {
trig,
pulse_reader,
delay,
trigger_duration_ms: 10,
max_timeout_us: 60000,
})
}
pub fn set_trigger_duration(&mut self, ms: u32) {
self.trigger_duration_ms = ms;
}
pub fn trigger_duration(&self) -> u32 {
self.trigger_duration_ms
}
pub fn release(self) -> (TRIG, READER, DELAY) {
(self.trig, self.pulse_reader, self.delay)
}
pub fn read_distance(&mut self) -> Result<Option<u16>, Error<TRIG::Error>> {
self._measure_echo()
}
pub fn read_distance_manual(&mut self) -> Result<Option<u16>, Error<TRIG::Error>> {
self.trig.set_low().map_err(Error::Bus)?;
self.delay.delay_ms(self.trigger_duration_ms);
self.trig.set_high().map_err(Error::Bus)?;
self._measure_echo()
}
fn _measure_echo(&mut self) -> Result<Option<u16>, Error<TRIG::Error>> {
match self.pulse_reader.measure_pulse() {
Some(duration_us) => {
if duration_us > 0 && duration_us < self.max_timeout_us {
Ok(Some((duration_us / 50) as u16))
} else {
Ok(None)
}
}
None => {
Err(Error::Timeout)
}
}
}
}