diff --git a/esp-hal/src/tsens.rs b/esp-hal/src/tsens.rs index e75f9d9fa..6fe5cfc46 100644 --- a/esp-hal/src/tsens.rs +++ b/esp-hal/src/tsens.rs @@ -31,10 +31,10 @@ //! Config::default() //! ).unwrap(); //! let delay = Delay::new(); -//! +//! delay.delay_micros(200); //! loop { -//! let temp = temperature_sensor.get_celsius(); -//! println!("Temperature: {:.2}°C", temp); +//! let temp = temperature_sensor.get_temperature(); +//! println!("Temperature: {:.2}°C", temp.to_celcius()); //! delay.delay_millis(1_000); //! } //! # } @@ -48,11 +48,11 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::TSENS, - system::{GenericPeripheralGuard, PeripheralClockControl}, + system::GenericPeripheralGuard, }; /// Clock source for the temperature sensor -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ClockSource { /// Use RC_FAST clock source @@ -63,48 +63,104 @@ pub enum ClockSource { } /// Temperature sensor configuration -#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, procmacros::BuilderLite)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, Hash, procmacros::BuilderLite)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] pub struct Config { clock_source: ClockSource, } /// Temperature sensor configuration error -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +#[non_exhaustive] pub enum ConfigError {} +/// Temperature value +/// This struct stores the raw ADC value, and can be used to calculate the +/// temperature in Celsius using the formula: +/// `(raw_value * 0.4386) - (offset * 27.88) - 20.52` +#[derive(Debug)] +pub struct Temperature { + /// Raw ADC value + pub raw_value: u8, + + /// Offset value - depends on the temperature range configured + pub offset: i8, +} + +impl Temperature { + /// Create a new temperature value + #[inline] + pub fn new(raw_value: u8, offset: i8) -> Self { + Self { raw_value, offset } + } + + /// Get the temperature in Celsius + #[inline] + pub fn to_celsius(&self) -> f32 { + (self.raw_value as f32) * 0.4386 - (self.offset as f32) * 27.88 - 20.52 + } + + /// Get the temperature in Fahrenheit + #[inline] + pub fn to_fahrenheit(&self) -> f32 { + let celsius = self.to_celsius(); + (celsius * 1.8) + 32.0 + } + + /// Get the temperature in Kelvin + #[inline] + pub fn to_kelvin(&self) -> f32 { + let celsius = self.to_celsius(); + celsius + 273.15 + } +} + /// Temperature sensor driver +#[derive(Debug)] pub struct TemperatureSensor<'d> { _peripheral: PeripheralRef<'d, TSENS>, - _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, + _tsens_guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, + _abp_saradc_guard: GenericPeripheralGuard<{ crate::system::Peripheral::ApbSarAdc as u8 }>, } impl<'d> TemperatureSensor<'d> { /// Create a new temperature sensor instance with configuration + /// The sensor will be automatically powered up pub fn new( peripheral: impl Peripheral

+ 'd, config: Config, ) -> Result { crate::into_ref!(peripheral); - let guard = GenericPeripheralGuard::new(); - - // We need to enable ApbSarAdc clock before trying to write on the tsens_ctrl - // register - PeripheralClockControl::enable(crate::system::Peripheral::ApbSarAdc); - let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; - - // Power Up - apb_saradc.tsens_ctrl().write(|w| w.pu().set_bit()); + // NOTE: We need enable ApbSarAdc before enabling Tsens + let apb_saradc_guard = GenericPeripheralGuard::new(); + let tsens_guard = GenericPeripheralGuard::new(); let mut tsens = Self { - _guard: guard, _peripheral: peripheral, + _tsens_guard: tsens_guard, + _abp_saradc_guard: apb_saradc_guard, }; tsens.apply_config(&config)?; + tsens.power_up(); + Ok(tsens) } + /// Power up the temperature sensor + pub fn power_up(&self) { + debug!("Power up"); + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + abp_saradc.tsens_ctrl().modify(|_, w| w.pu().set_bit()); + } + + /// Power down the temperature sensor - useful if you want to save power + pub fn power_down(&self) { + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + abp_saradc.tsens_ctrl().modify(|_, w| w.pu().clear_bit()); + } + /// Change the temperature sensor configuration pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; @@ -118,29 +174,16 @@ impl<'d> TemperatureSensor<'d> { Ok(()) } - /// Get the temperature in Celsius + /// Get the raw temperature value #[inline] - pub fn get_celsius(&self) -> f32 { + pub fn get_temperature(&self) -> Temperature { let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; - let measurement = abp_saradc.tsens_ctrl().read().out().bits(); + let raw_value = abp_saradc.tsens_ctrl().read().out().bits(); // TODO Address multiple temperature ranges and offsets - let offset = -1f32; - (measurement as f32) * 0.4386 - offset * 27.88 - 20.52 - } + let offset = -1i8; - /// Get the temperature in Fahrenheit - #[inline] - pub fn get_fahrenheit(&self) -> f32 { - let celsius = self.get_celsius(); - (celsius * 1.8) + 32.0 - } - - /// Get the temperature in Kelvin - #[inline] - pub fn get_kelvin(&self) -> f32 { - let celsius = self.get_celsius(); - celsius + 273.15 + Temperature::new(raw_value, offset) } } diff --git a/examples/src/bin/temperature_sensor.rs b/qa-test/src/bin/temperature_sensor.rs similarity index 81% rename from examples/src/bin/temperature_sensor.rs rename to qa-test/src/bin/temperature_sensor.rs index d016bd15c..8158af8d0 100644 --- a/examples/src/bin/temperature_sensor.rs +++ b/qa-test/src/bin/temperature_sensor.rs @@ -1,5 +1,5 @@ -//! This example uses the internal temperature sensor to measure the chip's temperature -//! +//! This example uses the internal temperature sensor to measure the chip's +//! temperature //% CHIPS: esp32c6 esp32c3 @@ -26,8 +26,8 @@ fn main() -> ! { delay.delay_micros(200); loop { - let temp = temperature_sensor.get_celsius(); - println!("Temperature: {:.2}°C", temp); + let temp = temperature_sensor.get_temperature(); + println!("Temperature: {:.2}°C", temp.to_celsius()); delay.delay_millis(1_000); } }