mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-27 04:10:30 +00:00
Add support for ESP internal temperature sensor (#337)
* Add first version of temp sensor driver Code is very rudimentary and still suspect to change. Notably, error handling is not implemented yet. * Change cfg attribute to not any * Rename TemperatureSensor to TemperatureSensorDriver * Switch to `core::ptr` * Add error handling * Build the internal temperature sensor only on supported targets * Fix the derives in TemperatureSensorConfig, TemperatureSensorClockSource * Implement From<TemperatureSensorConfig> for temperature_sensor_config_t * Use right clocks for temperature sensor depending on target * Rename config and move it into own module * Provide const new constructor for temperature sensor config * Change config argument to be a reference * Rename TemperatureSensor to TempSensor * Avoid cloning config in temp driver constructor * Add back derived Copy trait for TempSensorClockSource * Add non_exhaustive option to TempSensorConfig * Add temp sensor peripheral * Cause panic if uninstalling the temp driver fails * Implement Send for TempSensorDriver * Make use of esp_idf_soc_temp_sensor_supported * Add an example for temperature_sensor --------- Co-authored-by: Luca Barbato <lu_zero@gentoo.org>
This commit is contained in:
parent
e20ef5c92f
commit
a619f13871
28
examples/temperature_sensor.rs
Normal file
28
examples/temperature_sensor.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use esp_idf_hal::delay::FreeRtos;
|
||||
use esp_idf_hal::peripherals::Peripherals;
|
||||
|
||||
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
|
||||
fn main() -> anyhow::Result<()> {
|
||||
use esp_idf_hal::temp_sensor::*;
|
||||
esp_idf_hal::sys::link_patches();
|
||||
|
||||
let peripherals = Peripherals::take()?;
|
||||
let cfg = TempSensorConfig::default();
|
||||
let mut temp = TempSensorDriver::new(&cfg, peripherals.temp_sensor)?;
|
||||
temp.enable()?;
|
||||
|
||||
loop {
|
||||
let t = temp.get_celsius()?;
|
||||
println!("Temperature {t}C");
|
||||
FreeRtos::delay_ms(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5")))]
|
||||
fn main() -> anyhow::Result<()> {
|
||||
println!("This example requires feature `esp_idf_soc_temp_sensor_supported` enabled");
|
||||
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
}
|
||||
}
|
@ -64,6 +64,8 @@ pub mod sd;
|
||||
pub mod spi;
|
||||
pub mod sys;
|
||||
pub mod task;
|
||||
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
|
||||
pub mod temp_sensor;
|
||||
pub mod timer;
|
||||
pub mod uart;
|
||||
#[cfg(all(
|
||||
|
@ -22,6 +22,8 @@ use crate::spi;
|
||||
any(esp_idf_version_major = "4", esp_idf_version = "5.0")
|
||||
))]
|
||||
use crate::task::watchdog;
|
||||
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
|
||||
use crate::temp_sensor;
|
||||
use crate::timer;
|
||||
use crate::uart;
|
||||
#[cfg(all(
|
||||
@ -86,6 +88,8 @@ pub struct Peripherals {
|
||||
pub sdmmc0: sd::mmc::SDMMC0,
|
||||
#[cfg(all(esp_idf_soc_sdmmc_host_supported, feature = "experimental"))]
|
||||
pub sdmmc1: sd::mmc::SDMMC1,
|
||||
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
|
||||
pub temp_sensor: temp_sensor::TempSensor,
|
||||
// TODO: Check the timer story for c2, h2, c5, c6, and p4
|
||||
pub timer00: timer::TIMER00,
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
@ -187,6 +191,8 @@ impl Peripherals {
|
||||
sdmmc0: sd::mmc::SDMMC0::new(),
|
||||
#[cfg(all(esp_idf_soc_sdmmc_host_supported, feature = "experimental"))]
|
||||
sdmmc1: sd::mmc::SDMMC1::new(),
|
||||
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
|
||||
temp_sensor: temp_sensor::TempSensor::new(),
|
||||
timer00: timer::TIMER00::new(),
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
timer01: timer::TIMER01::new(),
|
||||
|
190
src/temp_sensor.rs
Normal file
190
src/temp_sensor.rs
Normal file
@ -0,0 +1,190 @@
|
||||
use esp_idf_sys::{
|
||||
esp, soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_DEFAULT,
|
||||
temperature_sensor_clk_src_t, temperature_sensor_config_t, temperature_sensor_disable,
|
||||
temperature_sensor_enable, temperature_sensor_get_celsius, temperature_sensor_handle_t,
|
||||
temperature_sensor_install, temperature_sensor_uninstall, EspError,
|
||||
};
|
||||
|
||||
#[cfg(esp32p4)]
|
||||
use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI;
|
||||
#[cfg(any(
|
||||
esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
|
||||
))]
|
||||
use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST;
|
||||
#[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
|
||||
use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL;
|
||||
|
||||
use crate::peripheral::Peripheral;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
// -- TempSensorClockSource --
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
/// Rust translation of `temperature_sensor_clk_src_t`
|
||||
pub enum TempSensorClockSource {
|
||||
Default,
|
||||
#[cfg(any(
|
||||
esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
|
||||
))]
|
||||
RcFast,
|
||||
#[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
|
||||
XTAL,
|
||||
#[cfg(esp32p4)]
|
||||
LpPeri,
|
||||
}
|
||||
|
||||
impl From<TempSensorClockSource> for temperature_sensor_clk_src_t {
|
||||
fn from(value: TempSensorClockSource) -> Self {
|
||||
match value {
|
||||
#[cfg(any(
|
||||
esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
|
||||
))]
|
||||
TempSensorClockSource::RcFast => {
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST
|
||||
}
|
||||
#[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
|
||||
TempSensorClockSource::XTAL => {
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL
|
||||
}
|
||||
#[cfg(esp32p4)]
|
||||
TempSensorClockSource::LpPeri => {
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI
|
||||
}
|
||||
TempSensorClockSource::Default => {
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_DEFAULT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<temperature_sensor_clk_src_t> for TempSensorClockSource {
|
||||
fn from(value: temperature_sensor_clk_src_t) -> Self {
|
||||
match value {
|
||||
#[cfg(any(
|
||||
esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
|
||||
))]
|
||||
#[allow(non_upper_case_globals)]
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST => {
|
||||
Self::RcFast
|
||||
}
|
||||
#[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
|
||||
#[allow(non_upper_case_globals)]
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL => Self::XTAL,
|
||||
#[cfg(esp32p4)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI => {
|
||||
Self::LpPeri
|
||||
}
|
||||
// TODO: Perhaps the default value should be mapped explicitly
|
||||
// and all other (u32) values should cause a failure
|
||||
_ => Self::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- TempSensorConfig --
|
||||
pub type TempSensorConfig = config::Config;
|
||||
pub mod config {
|
||||
use super::*;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
/// Rust wrapper for `temperature_sensor_config_t`
|
||||
pub struct Config {
|
||||
// TODO: check int size
|
||||
pub range_min: i32,
|
||||
pub range_max: i32,
|
||||
pub clk_src: TempSensorClockSource,
|
||||
}
|
||||
|
||||
impl From<temperature_sensor_config_t> for Config {
|
||||
fn from(value: temperature_sensor_config_t) -> Self {
|
||||
Config {
|
||||
range_min: value.range_min,
|
||||
range_max: value.range_max,
|
||||
clk_src: value.clk_src.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Config> for temperature_sensor_config_t {
|
||||
fn from(value: &Config) -> Self {
|
||||
temperature_sensor_config_t {
|
||||
clk_src: value.clk_src.into(),
|
||||
range_max: value.range_max,
|
||||
range_min: value.range_min,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Config::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
range_min: -10,
|
||||
range_max: 80,
|
||||
clk_src: TempSensorClockSource::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- TempSensorDriver --
|
||||
|
||||
pub struct TempSensorDriver<'d> {
|
||||
ptr: temperature_sensor_handle_t,
|
||||
_p: PhantomData<&'d mut ()>,
|
||||
}
|
||||
|
||||
impl<'d> TempSensorDriver<'d> {
|
||||
pub fn new(
|
||||
config: &TempSensorConfig,
|
||||
_sensor: impl Peripheral<P = TempSensor> + 'd,
|
||||
) -> Result<Self, EspError> {
|
||||
let mut sensor = core::ptr::null_mut();
|
||||
esp!(unsafe { temperature_sensor_install(&config.into(), &mut sensor) })?;
|
||||
Ok(TempSensorDriver {
|
||||
ptr: sensor,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn enable(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { temperature_sensor_enable(self.ptr) })
|
||||
}
|
||||
|
||||
pub fn disable(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { temperature_sensor_disable(self.ptr) })
|
||||
}
|
||||
|
||||
pub fn get_celsius(&self) -> Result<f32, EspError> {
|
||||
let mut val = 0.0;
|
||||
esp!(unsafe { temperature_sensor_get_celsius(self.ptr, &mut val) })?;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn get_fahrenheit(&self) -> Result<f32, EspError> {
|
||||
let celsius = self.get_celsius()?;
|
||||
Ok((celsius * 1.8) + 32.0)
|
||||
}
|
||||
|
||||
pub fn get_kelvin(&self) -> Result<f32, EspError> {
|
||||
let celsius = self.get_celsius()?;
|
||||
Ok(celsius + 273.15)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempSensorDriver<'_> {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.disable();
|
||||
esp!(unsafe { temperature_sensor_uninstall(self.ptr) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d> Send for TempSensorDriver<'d> {}
|
||||
|
||||
crate::impl_peripheral!(TempSensor);
|
Loading…
x
Reference in New Issue
Block a user