feat: add Temperature struct to avoid enforcing usage of floats
- Also add misc derives to multiple structs - Add power_up / power_down methods to TemperatureSensor - Enable ApbSarAdc via PeripheralGuard
This commit is contained in:
parent
59f2b7e52f
commit
1410db7ac2
@ -31,10 +31,10 @@
|
|||||||
//! Config::default()
|
//! Config::default()
|
||||||
//! ).unwrap();
|
//! ).unwrap();
|
||||||
//! let delay = Delay::new();
|
//! let delay = Delay::new();
|
||||||
//!
|
//! delay.delay_micros(200);
|
||||||
//! loop {
|
//! loop {
|
||||||
//! let temp = temperature_sensor.get_celsius();
|
//! let temp = temperature_sensor.get_temperature();
|
||||||
//! println!("Temperature: {:.2}°C", temp);
|
//! println!("Temperature: {:.2}°C", temp.to_celcius());
|
||||||
//! delay.delay_millis(1_000);
|
//! delay.delay_millis(1_000);
|
||||||
//! }
|
//! }
|
||||||
//! # }
|
//! # }
|
||||||
@ -48,11 +48,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::TSENS,
|
peripherals::TSENS,
|
||||||
system::{GenericPeripheralGuard, PeripheralClockControl},
|
system::GenericPeripheralGuard,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Clock source for the temperature sensor
|
/// 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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum ClockSource {
|
pub enum ClockSource {
|
||||||
/// Use RC_FAST clock source
|
/// Use RC_FAST clock source
|
||||||
@ -63,48 +63,104 @@ pub enum ClockSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Temperature sensor configuration
|
/// 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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
clock_source: ClockSource,
|
clock_source: ClockSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temperature sensor configuration error
|
/// Temperature sensor configuration error
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum ConfigError {}
|
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
|
/// Temperature sensor driver
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct TemperatureSensor<'d> {
|
pub struct TemperatureSensor<'d> {
|
||||||
_peripheral: PeripheralRef<'d, TSENS>,
|
_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> {
|
impl<'d> TemperatureSensor<'d> {
|
||||||
/// Create a new temperature sensor instance with configuration
|
/// Create a new temperature sensor instance with configuration
|
||||||
|
/// The sensor will be automatically powered up
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peripheral: impl Peripheral<P = TSENS> + 'd,
|
peripheral: impl Peripheral<P = TSENS> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Result<Self, ConfigError> {
|
) -> Result<Self, ConfigError> {
|
||||||
crate::into_ref!(peripheral);
|
crate::into_ref!(peripheral);
|
||||||
let guard = GenericPeripheralGuard::new();
|
// NOTE: We need enable ApbSarAdc before enabling Tsens
|
||||||
|
let apb_saradc_guard = GenericPeripheralGuard::new();
|
||||||
// We need to enable ApbSarAdc clock before trying to write on the tsens_ctrl
|
let tsens_guard = GenericPeripheralGuard::new();
|
||||||
// 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());
|
|
||||||
|
|
||||||
let mut tsens = Self {
|
let mut tsens = Self {
|
||||||
_guard: guard,
|
|
||||||
_peripheral: peripheral,
|
_peripheral: peripheral,
|
||||||
|
_tsens_guard: tsens_guard,
|
||||||
|
_abp_saradc_guard: apb_saradc_guard,
|
||||||
};
|
};
|
||||||
tsens.apply_config(&config)?;
|
tsens.apply_config(&config)?;
|
||||||
|
|
||||||
|
tsens.power_up();
|
||||||
|
|
||||||
Ok(tsens)
|
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
|
/// Change the temperature sensor configuration
|
||||||
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR };
|
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR };
|
||||||
@ -118,29 +174,16 @@ impl<'d> TemperatureSensor<'d> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the temperature in Celsius
|
/// Get the raw temperature value
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_celsius(&self) -> f32 {
|
pub fn get_temperature(&self) -> Temperature {
|
||||||
let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR };
|
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
|
// TODO Address multiple temperature ranges and offsets
|
||||||
let offset = -1f32;
|
let offset = -1i8;
|
||||||
(measurement as f32) * 0.4386 - offset * 27.88 - 20.52
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the temperature in Fahrenheit
|
Temperature::new(raw_value, offset)
|
||||||
#[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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
//% CHIPS: esp32c6 esp32c3
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ fn main() -> ! {
|
|||||||
delay.delay_micros(200);
|
delay.delay_micros(200);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let temp = temperature_sensor.get_celsius();
|
let temp = temperature_sensor.get_temperature();
|
||||||
println!("Temperature: {:.2}°C", temp);
|
println!("Temperature: {:.2}°C", temp.to_celsius());
|
||||||
delay.delay_millis(1_000);
|
delay.delay_millis(1_000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user