From 96ae59087e6828f9eb892ca484469f76de1f541a Mon Sep 17 00:00:00 2001 From: Zachary Sunforge Date: Sun, 7 Jul 2024 18:57:59 -0700 Subject: [PATCH] - Modified some thermocouple functions to use f64 instead of f32 - Added thermistor - Added resistive divider --- Cargo.toml | 8 ++++-- src/lib.rs | 2 ++ src/resistive_divider.rs | 31 ++++++++++++++++++++ src/transducer/part/mod.rs | 5 +++- src/transducer/part/thermistor.rs | 33 ++++++++++++++++++++++ src/transducer/part/thermocouple/mod.rs | 2 +- src/transducer/part/thermocouple/type_k.rs | 21 +++++++------- 7 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 src/resistive_divider.rs create mode 100644 src/transducer/part/thermistor.rs diff --git a/Cargo.toml b/Cargo.toml index f2d2a45..eea3093 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "0.3.3" +version = "0.3.4" edition = "2021" repository = "https://git.bfpower.io/BFPOWER/physical" readme = "README.md" @@ -107,7 +107,9 @@ readme.workspace = true license.workspace = true [features] -thermocouple_k = [] +resistive-divider = [] +thermocouple-k = ["libm"] +thermistor = ["libm"] lm35 = [] pid = [] stm32 = [] @@ -115,7 +117,7 @@ stm32 = [] [dependencies] uom = { workspace = true } num-traits = { workspace = true } -libm = { workspace = true } +libm = { workspace = true, optional = true } serde = { workspace = true, optional = true } #--------------------------------------------------------------------------------------------------------------------- diff --git a/src/lib.rs b/src/lib.rs index f51a0ab..94a73c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,5 +5,7 @@ pub mod control; pub mod error; pub mod adc; +#[cfg(feature = "resistive-divider")] +pub mod resistive_divider; pub use error::CriticalError; diff --git a/src/resistive_divider.rs b/src/resistive_divider.rs new file mode 100644 index 0000000..a82b752 --- /dev/null +++ b/src/resistive_divider.rs @@ -0,0 +1,31 @@ +use uom::si::electric_potential::volt; +use uom::si::electrical_resistance::ohm; +use uom::si::quantities::{ElectricPotential, ElectricalResistance}; + +/// Given the resistance of the second resistor in a resistive voltage divider, calculate the resistance of the first resistor. +pub fn solve_r1( + voltage_src: ElectricPotential, + voltage_read: ElectricPotential, + r2: ElectricalResistance, +) -> ElectricalResistance { + let volts_src = voltage_src.get::(); + let volts_read = voltage_read.get::(); + let ohms2 = r2.get::(); + + let ohms1 = ohms2 * (volts_src / volts_read - 1.0); + ElectricalResistance::new::(ohms1) +} + +/// Given the resistance of the first resistor in a resistive voltage divider, calculate the resistance of the second resistor. +pub fn solve_r2( + voltage_src: ElectricPotential, + voltage_read: ElectricPotential, + r1: ElectricalResistance, +) -> ElectricalResistance { + let volts_src = voltage_src.get::(); + let volts_read = voltage_read.get::(); + let ohms1 = r1.get::(); + + let ohms2 = ohms1 * (1.0 / (volts_src / volts_read) - 1.0); + ElectricalResistance::new::(ohms2) +} diff --git a/src/transducer/part/mod.rs b/src/transducer/part/mod.rs index cd42413..0485ee0 100644 --- a/src/transducer/part/mod.rs +++ b/src/transducer/part/mod.rs @@ -3,5 +3,8 @@ mod thermocouple; #[cfg(feature = "lm35")] pub mod lm35; -#[cfg(feature = "thermocouple_k")] +#[cfg(feature = "thermistor")] +pub mod thermistor; + +#[cfg(feature = "thermocouple-k")] pub use thermocouple::type_k as thermocouple_k; \ No newline at end of file diff --git a/src/transducer/part/thermistor.rs b/src/transducer/part/thermistor.rs new file mode 100644 index 0000000..ab23d83 --- /dev/null +++ b/src/transducer/part/thermistor.rs @@ -0,0 +1,33 @@ +use libm::{log, logf}; +use uom::si::electrical_resistance::ohm; +use uom::si::quantities::{ThermodynamicTemperature, ElectricalResistance}; +use uom::si::thermodynamic_temperature::kelvin; + +/// Convert thermistor resistance to a temperature using beta parameter equation +pub fn convert_beta( + resistance: ElectricalResistance, + beta: f32, + reference_temp: ThermodynamicTemperature, + reference_resist: ElectricalResistance, +) -> ThermodynamicTemperature { + let ohms = resistance.get::(); + let reference_kelvin = reference_temp.get::(); + let reference_ohms = reference_resist.get::(); + + let result_kelvin = 1.0 / ((1.0 / reference_kelvin) + (1.0 / beta) * logf(ohms / reference_ohms)); + ThermodynamicTemperature::new::(result_kelvin) +} + +/// Convert thermistor resistance to a temperature using Steinhart-Hart equation +pub fn convert_steinhart( + resistance: ElectricalResistance, + a: f64, + b: f64, + c: f64, +) -> ThermodynamicTemperature { + let ohms = resistance.get::() as f64; + + let log_omhs = log(ohms); + let kelvins = 1.0 / (a + b * log_omhs + c * log_omhs * log_omhs * log_omhs); + ThermodynamicTemperature::new::(kelvins as f32) +} diff --git a/src/transducer/part/thermocouple/mod.rs b/src/transducer/part/thermocouple/mod.rs index 9ce86f4..108a162 100644 --- a/src/transducer/part/thermocouple/mod.rs +++ b/src/transducer/part/thermocouple/mod.rs @@ -1,2 +1,2 @@ -#[cfg(feature = "thermocouple_k")] +#[cfg(feature = "thermocouple-k")] pub mod type_k; \ No newline at end of file diff --git a/src/transducer/part/thermocouple/type_k.rs b/src/transducer/part/thermocouple/type_k.rs index b95ecba..08451d3 100644 --- a/src/transducer/part/thermocouple/type_k.rs +++ b/src/transducer/part/thermocouple/type_k.rs @@ -1,5 +1,7 @@ +//! Note - Thermocouple conversion uses [f64] arithmetic internally. + +use libm::pow; use crate::error::InvalidValue; -use libm::powf; use uom::si::electric_potential::millivolt; use uom::si::quantities::{ElectricPotential, ThermodynamicTemperature}; use uom::si::thermodynamic_temperature::degree_celsius; @@ -7,7 +9,7 @@ use uom::si::thermodynamic_temperature::degree_celsius; fn _convert( voltage: ElectricPotential, ) -> Result, InvalidValue> { - let mv = voltage.get::(); + let mv = voltage.get::() as f64; let mv_pow2 = mv * mv; let mv_pow3 = mv_pow2 * mv; let mv_pow4 = mv_pow3 * mv; @@ -27,7 +29,7 @@ fn _convert( + -1.0450598E-2 * mv_pow7 + -5.1920577E-4 * mv_pow8; - Ok(ThermodynamicTemperature::new::(celsius)) + Ok(ThermodynamicTemperature::new::(celsius as f32)) } else if mv > 0.0 && mv < 20.644 { let mv_pow7 = mv_pow6 * mv; let mv_pow8 = mv_pow7 * mv; @@ -43,7 +45,7 @@ fn _convert( + 1.057734E-6 * mv_pow8 + -1.052755E-8 * mv_pow9; - Ok(ThermodynamicTemperature::new::(celsius)) + Ok(ThermodynamicTemperature::new::(celsius as f32)) } else if mv >= 20.644 && mv <= 54.886 { let celsius = 1.318058e2 + 4.830222E+1 * mv @@ -53,7 +55,7 @@ fn _convert( + 8.802193E-6 * mv_pow5 + -3.110810E-8 * mv_pow6; - Ok(ThermodynamicTemperature::new::(celsius)) + Ok(ThermodynamicTemperature::new::(celsius as f32)) } else { Err(InvalidValue) } @@ -107,11 +109,10 @@ pub fn convert_polynomial( _convert(voltage + voltage_correction) } -//TODO: This is not working, check libm pow. pub fn temp_to_voltage_poly( temperature: ThermodynamicTemperature, ) -> Result, InvalidValue> { - let celsius = temperature.get::(); + let celsius = temperature.get::() as f64; let cel_pow2 = celsius * celsius; let cel_pow3 = cel_pow2 * celsius; let cel_pow4 = cel_pow3 * celsius; @@ -135,11 +136,11 @@ pub fn temp_to_voltage_poly( + -0.198892668780E-19 * cel_pow9 + -0.163226974860E-22 * cel_pow10; - Ok(ElectricPotential::new::(mv)) + Ok(ElectricPotential::new::(mv as f32)) } else if celsius >= 0.0 && celsius <= 1372.0 { let base = celsius - 0.126968600000E+03; let exp = -0.118343200000E-03 * (base * base); - let addition = powf(0.1185976, exp); + let addition = pow(0.1185976, exp); let mv = -0.176004136860E-01 + 0.389212049750E-01 * celsius @@ -153,7 +154,7 @@ pub fn temp_to_voltage_poly( + -0.121047212750E-25 * cel_pow9 + addition; - Ok(ElectricPotential::new::(mv)) + Ok(ElectricPotential::new::(mv as f32)) } else { Err(InvalidValue) }