- Modified some thermocouple functions to use f64 instead of f32
- Added thermistor - Added resistive divider
This commit is contained in:
@ -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 }
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
31
src/resistive_divider.rs
Normal file
31
src/resistive_divider.rs
Normal file
@ -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<f32>,
|
||||
voltage_read: ElectricPotential<f32>,
|
||||
r2: ElectricalResistance<f32>,
|
||||
) -> ElectricalResistance<f32> {
|
||||
let volts_src = voltage_src.get::<volt>();
|
||||
let volts_read = voltage_read.get::<volt>();
|
||||
let ohms2 = r2.get::<ohm>();
|
||||
|
||||
let ohms1 = ohms2 * (volts_src / volts_read - 1.0);
|
||||
ElectricalResistance::new::<ohm>(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<f32>,
|
||||
voltage_read: ElectricPotential<f32>,
|
||||
r1: ElectricalResistance<f32>,
|
||||
) -> ElectricalResistance<f32> {
|
||||
let volts_src = voltage_src.get::<volt>();
|
||||
let volts_read = voltage_read.get::<volt>();
|
||||
let ohms1 = r1.get::<ohm>();
|
||||
|
||||
let ohms2 = ohms1 * (1.0 / (volts_src / volts_read) - 1.0);
|
||||
ElectricalResistance::new::<ohm>(ohms2)
|
||||
}
|
@ -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;
|
33
src/transducer/part/thermistor.rs
Normal file
33
src/transducer/part/thermistor.rs
Normal file
@ -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<f32>,
|
||||
beta: f32,
|
||||
reference_temp: ThermodynamicTemperature<f32>,
|
||||
reference_resist: ElectricalResistance<f32>,
|
||||
) -> ThermodynamicTemperature<f32> {
|
||||
let ohms = resistance.get::<ohm>();
|
||||
let reference_kelvin = reference_temp.get::<kelvin>();
|
||||
let reference_ohms = reference_resist.get::<ohm>();
|
||||
|
||||
let result_kelvin = 1.0 / ((1.0 / reference_kelvin) + (1.0 / beta) * logf(ohms / reference_ohms));
|
||||
ThermodynamicTemperature::new::<kelvin>(result_kelvin)
|
||||
}
|
||||
|
||||
/// Convert thermistor resistance to a temperature using Steinhart-Hart equation
|
||||
pub fn convert_steinhart(
|
||||
resistance: ElectricalResistance<f32>,
|
||||
a: f64,
|
||||
b: f64,
|
||||
c: f64,
|
||||
) -> ThermodynamicTemperature<f32> {
|
||||
let ohms = resistance.get::<ohm>() as f64;
|
||||
|
||||
let log_omhs = log(ohms);
|
||||
let kelvins = 1.0 / (a + b * log_omhs + c * log_omhs * log_omhs * log_omhs);
|
||||
ThermodynamicTemperature::new::<kelvin>(kelvins as f32)
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
#[cfg(feature = "thermocouple_k")]
|
||||
#[cfg(feature = "thermocouple-k")]
|
||||
pub mod type_k;
|
@ -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<f32>,
|
||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
||||
let mv = voltage.get::<millivolt>();
|
||||
let mv = voltage.get::<millivolt>() 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::<degree_celsius>(celsius))
|
||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(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::<degree_celsius>(celsius))
|
||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(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::<degree_celsius>(celsius))
|
||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(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<f32>,
|
||||
) -> Result<ElectricPotential<f32>, InvalidValue> {
|
||||
let celsius = temperature.get::<degree_celsius>();
|
||||
let celsius = temperature.get::<degree_celsius>() 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::<millivolt>(mv))
|
||||
Ok(ElectricPotential::new::<millivolt>(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::<millivolt>(mv))
|
||||
Ok(ElectricPotential::new::<millivolt>(mv as f32))
|
||||
} else {
|
||||
Err(InvalidValue)
|
||||
}
|
||||
|
Reference in New Issue
Block a user