esp-idf-hal
esp-idf-hal copied to clipboard
UART read timeout?
I am trying to read a success code that is sent to my ESP by a UART sensor. To do so, I use read_exact this way
fn read_success(uart: &mut UartDriver) -> anyhow::Result<()> {
let mut buffer = [0; 10];
uart.read_exact(&mut buffer)?;
assert_eq!(&buffer, b"$00023335&");
Ok(())
}
Can I set a read timeout in case the sensor never responds?
There seems to be uart_set_rx_timeout but I couldn’t find any function that does this in the wrappers.
I had the same problem. Not sure if that's the best way to solve this, but what I did is implement my own ReadWithTimeout trait, based on the Read trait from embedded_io:
use esp_idf_hal::delay::TickType;
use esp_idf_hal::io::{EspIOError, ReadExactError};
use esp_idf_hal::uart::UartDriver;
pub trait ReadWithTimeout {
fn read(&mut self, buf: &mut [u8], timeout_ms: u64) -> Result<usize, EspIOError>;
fn read_exact(
&mut self,
mut buf: &mut [u8],
timeout_ms: u64,
) -> Result<(), ReadExactError<EspIOError>> {
while !buf.is_empty() {
match self.read(buf, timeout_ms) {
Ok(0) => break,
Ok(n) => buf = &mut buf[n..],
Err(e) => return Err(ReadExactError::Other(e)),
}
}
if buf.is_empty() {
Ok(())
} else {
Err(ReadExactError::UnexpectedEof)
}
}
}
impl<'d> ReadWithTimeout for UartDriver<'d> {
fn read(&mut self, buf: &mut [u8], timeout_ms: u64) -> Result<usize, EspIOError> {
UartDriver::read(self, buf, TickType::new_millis(timeout_ms).ticks()).map_err(EspIOError)
}
}