-
Notifications
You must be signed in to change notification settings - Fork 369
feat: add support for internal temperature sensor (tsens) for esp32c6 and esp32c3 #2875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+265
−0
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0ce94e9
feat: add basic support for temperature sensor (tsens) for esp32c6
davoclavo 5a06687
feat: add basic support for temperature sensor (tsens) for esp32c3
davoclavo 59f2b7e
feat: add configurable clock source for temperature sensor
davoclavo 1410db7
feat: add Temperature struct to avoid enforcing usage of floats
davoclavo ad3e44b
fix: move tsens module to unstable module list
davoclavo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| //! # Temperature Sensor (tsens) | ||
| //! | ||
| //! ## Overview | ||
| //! | ||
| //! The Temperature Sensor peripheral is used to measure the internal | ||
| //! temperature inside the chip. The voltage is internally converted via an ADC | ||
| //! into a digital value, and has a measuring range of –40 °C to 125 °C. | ||
| //! The temperature value depends on factors like microcontroller clock | ||
| //! frequency or I/O load. Generally, the chip’s internal temperature is higher | ||
| //! than the operating ambient temperature. | ||
| //! | ||
| //! It is recommended to wait a few hundred microseconds after turning it on | ||
| //! before measuring, in order to allow the sensor to stabilize. | ||
| //! | ||
| //! ## Configuration | ||
| //! | ||
| //! The temperature sensor can be configured with different clock sources. | ||
| //! | ||
| //! ## Examples | ||
| //! | ||
| //! The following example will measure the internal chip temperature every | ||
| //! second, and print it | ||
| //! | ||
| //! ```rust, no_run | ||
| #![doc = crate::before_snippet!()] | ||
| //! # use esp_hal::tsens::{TemperatureSensor, Config}; | ||
| //! # use esp_hal::delay::Delay; | ||
| //! | ||
| //! let temperature_sensor = TemperatureSensor::new( | ||
| //! peripherals.TSENS, | ||
| //! Config::default() | ||
| //! ).unwrap(); | ||
| //! let delay = Delay::new(); | ||
| //! delay.delay_micros(200); | ||
| //! loop { | ||
| //! let temp = temperature_sensor.get_temperature(); | ||
| //! println!("Temperature: {:.2}°C", temp.to_celcius()); | ||
| //! delay.delay_millis(1_000); | ||
| //! } | ||
| //! # } | ||
| //! ``` | ||
| //! | ||
| //! ## Implementation State | ||
| //! | ||
| //! - Temperature calibration range is not supported | ||
| //! - Interrupts are not supported | ||
|
|
||
| use crate::{ | ||
| peripheral::{Peripheral, PeripheralRef}, | ||
| peripherals::TSENS, | ||
| system::GenericPeripheralGuard, | ||
| }; | ||
|
|
||
| /// Clock source for the temperature sensor | ||
| #[derive(Debug, Clone, Default, PartialEq, Eq, Copy, Hash)] | ||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| pub enum ClockSource { | ||
| /// Use RC_FAST clock source | ||
| RcFast, | ||
| /// Use XTAL clock source | ||
| #[default] | ||
| Xtal, | ||
| } | ||
|
|
||
| /// Temperature sensor configuration | ||
| #[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, PartialEq, Eq, Copy, Hash)] | ||
| #[non_exhaustive] | ||
| pub enum ConfigError {} | ||
davoclavo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /// 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> { | ||
davoclavo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _peripheral: PeripheralRef<'d, TSENS>, | ||
| _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<P = TSENS> + 'd, | ||
| config: Config, | ||
| ) -> Result<Self, ConfigError> { | ||
| crate::into_ref!(peripheral); | ||
| // NOTE: We need enable ApbSarAdc before enabling Tsens | ||
| let apb_saradc_guard = GenericPeripheralGuard::new(); | ||
| let tsens_guard = GenericPeripheralGuard::new(); | ||
|
|
||
| let mut tsens = Self { | ||
| _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 }; | ||
|
|
||
| // Set clock source | ||
| apb_saradc.tsens_ctrl2().write(|w| { | ||
| w.clk_sel() | ||
| .bit(matches!(config.clock_source, ClockSource::Xtal)) | ||
| }); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Get the raw temperature value | ||
| #[inline] | ||
| pub fn get_temperature(&self) -> Temperature { | ||
| let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; | ||
|
|
||
| let raw_value = abp_saradc.tsens_ctrl().read().out().bits(); | ||
|
|
||
| // TODO Address multiple temperature ranges and offsets | ||
davoclavo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let offset = -1i8; | ||
|
|
||
| Temperature::new(raw_value, offset) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ symbols = [ | |
| "phy", | ||
| "bt", | ||
| "wifi", | ||
| "tsens", | ||
|
|
||
| # ROM capabilities | ||
| "rom_crc_le", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,6 +83,7 @@ symbols = [ | |
| "wifi6", | ||
| "ieee802154", | ||
| "lp_core", | ||
| "tsens", | ||
|
|
||
| # ROM capabilities | ||
| "rom_crc_le", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| //! This example uses the internal temperature sensor to measure the chip's | ||
| //! temperature | ||
|
|
||
| //% CHIPS: esp32c6 esp32c3 | ||
|
|
||
| #![no_std] | ||
| #![no_main] | ||
|
|
||
| use esp_backtrace as _; | ||
| use esp_hal::{ | ||
| delay::Delay, | ||
| entry, | ||
| tsens::{Config, TemperatureSensor}, | ||
| }; | ||
| use esp_println::println; | ||
|
|
||
| #[entry] | ||
| fn main() -> ! { | ||
| esp_println::logger::init_logger_from_env(); | ||
| let peripherals = esp_hal::init(esp_hal::Config::default()); | ||
|
|
||
| let temperature_sensor = TemperatureSensor::new(peripherals.TSENS, Config::default()).unwrap(); | ||
| let delay = Delay::new(); | ||
|
|
||
| // Wait for the sensor to stabilize | ||
| delay.delay_micros(200); | ||
|
|
||
| loop { | ||
| let temp = temperature_sensor.get_temperature(); | ||
| println!("Temperature: {:.2}°C", temp.to_celsius()); | ||
| delay.delay_millis(1_000); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.