diff --git a/embedded-hal-async/src/adc.rs b/embedded-hal-async/src/adc.rs index 1863fdfe..59096a37 100644 --- a/embedded-hal-async/src/adc.rs +++ b/embedded-hal-async/src/adc.rs @@ -2,23 +2,19 @@ pub use embedded_hal::adc::{Error, ErrorKind, ErrorType}; -/// Read data from an ADC. -/// -/// # Note for Implementers -/// -/// This should wait until data is ready and then read it. +/// Asynchronous voltmeter for measuring voltage. /// /// # Examples /// -/// In the first naive example, [`AdcChannel`] is implemented +/// In the first naive example, [`Voltmeter`] is implemented /// using a spin loop and only returns once data is ready. /// /// ``` -/// # use embedded_hal_async::adc::{AdcChannel, ErrorKind, ErrorType, Error}; -/// # -/// struct MySpinningAdc; +/// use embedded_hal_async::adc::{ErrorKind, ErrorType, Error, Voltmeter}; +/// +/// struct MySpinningVoltmeter; /// -/// impl MySpinningAdc { +/// impl MySpinningVoltmeter { /// pub fn is_ready(&mut self) -> bool { /// // Just pretend this returns `false` the first few times. /// true @@ -29,21 +25,21 @@ pub use embedded_hal::adc::{Error, ErrorKind, ErrorType}; /// } /// } /// -/// impl ErrorType for MySpinningAdc { +/// impl ErrorType for MySpinningVoltmeter { /// type Error = ErrorKind; /// } /// -/// impl AdcChannel for MySpinningAdc { +/// impl Voltmeter for MySpinningVoltmeter { /// async fn measure_nv(&mut self) -> Result { /// Ok(self.measure_mv().await? as i64 * 1_000_000) /// } /// -/// async fn measure_mv(&mut self) -> Result { +/// async fn measure_mv(&mut self) -> Result { /// while !self.is_ready() { /// core::hint::spin_loop(); /// } /// -/// Ok(self.data() as i32) +/// Ok(self.data() as i16) /// } /// } /// ``` @@ -52,28 +48,31 @@ pub use embedded_hal::adc::{Error, ErrorKind, ErrorType}; /// When the “ready pin” goes high, data is ready. /// /// ``` -/// # use embedded_hal_async::{adc::{self, ErrorKind, ErrorType, Error, AdcChannel}, digital::{self, Wait, Error as _, ErrorType as _}}; -/// # -/// struct MyWaitingAdc { +/// use embedded_hal_async::{ +/// adc::{self, ErrorKind, ErrorType, Error, Voltmeter}, +/// digital::{self, Wait, Error as _, ErrorType as _}, +/// }; +/// +/// struct MyWaitingVoltmeter { /// ready_pin: T, /// }; /// -/// impl MyWaitingAdc { +/// impl MyWaitingVoltmeter { /// pub fn data(&mut self) -> u16 { /// 3300 /// } /// } /// -/// impl adc::ErrorType for MyWaitingAdc { +/// impl adc::ErrorType for MyWaitingVoltmeter { /// type Error = adc::ErrorKind; /// } /// -/// impl AdcChannel for MyWaitingAdc { +/// impl Voltmeter for MyWaitingVoltmeter { /// async fn measure_nv(&mut self) -> Result { /// Ok(self.measure_mv().await? as i64 * 1_000_000) /// } /// -/// async fn measure_mv(&mut self) -> Result { +/// async fn measure_mv(&mut self) -> Result { /// match self.ready_pin.wait_for_high().await { /// Ok(()) => (), /// Err(err) => return Err(match err.kind() { @@ -82,28 +81,43 @@ pub use embedded_hal::adc::{Error, ErrorKind, ErrorType}; /// }) /// } /// -/// Ok(self.data() as i32) +/// Ok(self.data() as i16) /// } /// } /// ``` -pub trait AdcChannel: ErrorType { - /// Take a measurement in nV (nanovolts). +pub trait Voltmeter: ErrorType { + /// Measures voltage in nV (nanovolts). + /// + /// This can measure between -9223372036.854775808V and 9223372036.854775807V. async fn measure_nv(&mut self) -> Result; - /// Take a measurement in mV (microvolts). + /// Measures voltage in mV (microvolts). + /// + /// This can measure between -2147.483648V and 2147.483647V. + /// If you need to measure a larger range, use [`measure_nv`](Voltmeter::measure_nv) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i32::MIN`] and [`i32::MAX`]. async fn measure_uv(&mut self) -> Result { - Ok((self.measure_nv().await? / 1_000) as i32) + Ok((self.measure_nv().await? / 1_000).clamp(i32::MIN.into(), i32::MAX.into()) as i32) } - /// Take a measurement in mV (millivolts). - async fn measure_mv(&mut self) -> Result { - Ok(self.measure_uv().await? / 1_000) + /// Measures voltage in mV (millivolts). + /// + /// This can measure between between -32.768V and 32.767V. + /// If you need to measure a larger range, + /// use [`measure_uv`](Voltmeter::measure_uv) or [`measure_nv`](Voltmeter::measure_nv) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i16::MIN`] and [`i16::MAX`]. + async fn measure_mv(&mut self) -> Result { + Ok((self.measure_uv().await? / 1_000).clamp(i16::MIN.into(), i16::MAX.into()) as i16) } } -impl AdcChannel for &mut T +impl Voltmeter for &mut T where - T: AdcChannel + ?Sized, + T: Voltmeter + ?Sized, { #[inline] async fn measure_nv(&mut self) -> Result { @@ -116,7 +130,58 @@ where } #[inline] - async fn measure_mv(&mut self) -> Result { + async fn measure_mv(&mut self) -> Result { (*self).measure_mv().await } } + +/// Asynchronous ammeter (ampere meter) for measuring current. +pub trait Ammeter: ErrorType { + /// Measures current in nA (nanoampere). + /// + /// This can measure between -9223372036.854775808A and 9223372036.854775807A. + async fn measure_na(&mut self) -> Result; + + /// Measures current in uA (microampere). + /// + /// This can measure between -2147.483648A and 2147.483647A. + /// If you need to measure a larger range, use [`measure_na`](Ammeter::measure_na) instead. + /// + /// When overriding the default implementation, ensure that the measured current is clamped + /// between [`i32::MIN`] and [`i32::MAX`]. + async fn measure_ua(&mut self) -> Result { + Ok((self.measure_na().await? / 1_000).clamp(i32::MIN.into(), i32::MAX.into()) as i32) + } + + /// Measures current in mA (milliampere). + /// + /// This can measure between between -32.768A and 32.767A. + /// If you need to measure a larger range, + /// use [`measure_ua`](Ammeter::measure_ua) or [`measure_na`](Ammeter::measure_na) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i16::MIN`] and [`i16::MAX`]. + async fn measure_ma(&mut self) -> Result { + Ok((self.measure_ua().await? / 1_000).clamp(i16::MIN.into(), i16::MAX.into()) as i16) + } +} + +impl Ammeter for &mut T +where + T: Ammeter + ?Sized, +{ + #[inline] + async fn measure_na(&mut self) -> Result { + (*self).measure_na().await + } + + #[inline] + async fn measure_ua(&mut self) -> Result { + (*self).measure_ua().await + } + + #[inline] + async fn measure_ma(&mut self) -> Result { + (*self).measure_ma().await + } +} diff --git a/embedded-hal/src/adc.rs b/embedded-hal/src/adc.rs index f6d6ccc5..f9f86554 100644 --- a/embedded-hal/src/adc.rs +++ b/embedded-hal/src/adc.rs @@ -5,23 +5,19 @@ use core::fmt::{Debug, Display}; #[cfg(feature = "defmt-03")] use crate::defmt; -/// Read data from an ADC. -/// -/// # Note for Implementers -/// -/// This should wait until data is ready and then read it. +/// Blocking voltmeter for measuring voltage. /// /// # Examples /// -/// In the first naive example, [`AdcChannel`] is implemented +/// In the first naive example, [`Voltmeter`] is implemented /// using a spin loop and only returns once data is ready. /// /// ``` -/// use embedded_hal::adc::{AdcChannel, ErrorKind, ErrorType, Error}; +/// use embedded_hal::adc::{ErrorKind, ErrorType, Error, Voltmeter}; /// -/// struct MySpinningAdc; +/// struct MySpinningVoltmeter; /// -/// impl MySpinningAdc { +/// impl MySpinningVoltmeter { /// pub fn is_ready(&mut self) -> bool { /// // Just pretend this returns `false` the first few times. /// true @@ -32,42 +28,57 @@ use crate::defmt; /// } /// } /// -/// impl ErrorType for MySpinningAdc { +/// impl ErrorType for MySpinningVoltmeter { /// type Error = ErrorKind; /// } /// -/// impl AdcChannel for MySpinningAdc { +/// impl Voltmeter for MySpinningVoltmeter { /// fn measure_nv(&mut self) -> Result { /// Ok(self.measure_mv()? as i64 * 1_000_000) /// } /// -/// fn measure_mv(&mut self) -> Result { +/// fn measure_mv(&mut self) -> Result { /// while !self.is_ready() { /// core::hint::spin_loop(); /// } /// -/// Ok(self.data() as i32) +/// Ok(self.data() as i16) /// } /// } /// ``` -pub trait AdcChannel: ErrorType { - /// Take a measurement in nV (nanovolts). +pub trait Voltmeter: ErrorType { + /// Measures voltage in nV (nanovolts). + /// + /// This can measure between -9223372036.854775808V and 9223372036.854775807V. fn measure_nv(&mut self) -> Result; - /// Take a measurement in mV (microvolts). + /// Measures voltage in mV (microvolts). + /// + /// This can measure between -2147.483648V and 2147.483647V. + /// If you need to measure a larger range, use [`measure_nv`](Voltmeter::measure_nv) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i32::MIN`] and [`i32::MAX`]. fn measure_uv(&mut self) -> Result { - Ok((self.measure_nv()? / 1_000) as i32) + Ok((self.measure_nv()? / 1_000).clamp(i32::MIN.into(), i32::MAX.into()) as i32) } - /// Take a measurement in mV (millivolts). - fn measure_mv(&mut self) -> Result { - Ok(self.measure_uv()? / 1_000) + /// Measures voltage in mV (millivolts). + /// + /// This can measure between between -32.768V and 32.767V. + /// If you need to measure a larger range, + /// use [`measure_uv`](Voltmeter::measure_uv) or [`measure_mv`](Voltmeter::measure_mv) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i16::MIN`] and [`i16::MAX`]. + fn measure_mv(&mut self) -> Result { + Ok((self.measure_uv()? / 1_000).clamp(i16::MIN.into(), i16::MAX.into()) as i16) } } -impl AdcChannel for &mut T +impl Voltmeter for &mut T where - T: AdcChannel + ?Sized, + T: Voltmeter + ?Sized, { #[inline] fn measure_nv(&mut self) -> Result { @@ -80,11 +91,62 @@ where } #[inline] - fn measure_mv(&mut self) -> Result { + fn measure_mv(&mut self) -> Result { (*self).measure_mv() } } +/// Blocking ammeter (ampere meter) for measuring current. +pub trait Ammeter: ErrorType { + /// Measures current in nA (nanoampere). + /// + /// This can measure between -9223372036.854775808A and 9223372036.854775807A. + fn measure_na(&mut self) -> Result; + + /// Measures current in uA (microampere). + /// + /// This can measure between -2147.483648A and 2147.483647A. + /// If you need to measure a larger range, use [`measure_na`](Ammeter::measure_na) instead. + /// + /// When overriding the default implementation, ensure that the measured current is clamped + /// between [`i32::MIN`] and [`i32::MAX`]. + fn measure_ua(&mut self) -> Result { + Ok((self.measure_na()? / 1_000).clamp(i32::MIN.into(), i32::MAX.into()) as i32) + } + + /// Measures current in mA (milliampere). + /// + /// This can measure between between -32.768A and 32.767A. + /// If you need to measure a larger range, + /// use [`measure_ua`](Ammeter::measure_ua) or [`measure_na`](Ammeter::measure_na) instead. + /// + /// When overriding the default implementation, ensure that the measured voltage is clamped + /// between [`i16::MIN`] and [`i16::MAX`]. + fn measure_ma(&mut self) -> Result { + Ok((self.measure_ua()? / 1_000).clamp(i16::MIN.into(), i16::MAX.into()) as i16) + } +} + +impl Ammeter for &mut T +where + T: Ammeter + ?Sized, +{ + #[inline] + fn measure_na(&mut self) -> Result { + (*self).measure_na() + } + + #[inline] + fn measure_ua(&mut self) -> Result { + (*self).measure_ua() + } + + #[inline] + fn measure_ma(&mut self) -> Result { + (*self).measure_ma() + } +} + /// ADC error. pub trait Error: Debug { /// Convert error to a generic ADC error kind.