Compare commits
2 Commits
d0b792be0e
...
f06582caed
| Author | SHA1 | Date | |
|---|---|---|---|
| f06582caed | |||
| 2a0d9e0097 |
+2
-1
@@ -124,7 +124,6 @@ libm = ["dep:libm", "num-traits/libm"]
|
|||||||
resistive-divider = []
|
resistive-divider = []
|
||||||
thermocouple-k = ["libm"]
|
thermocouple-k = ["libm"]
|
||||||
thermistor = ["libm"]
|
thermistor = ["libm"]
|
||||||
lm35 = []
|
|
||||||
pid = []
|
pid = []
|
||||||
stm32 = []
|
stm32 = []
|
||||||
|
|
||||||
@@ -143,6 +142,8 @@ optional = true
|
|||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
workspace = true
|
workspace = true
|
||||||
optional = true
|
optional = true
|
||||||
|
[dependencies.thiserror]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[dev-dependencies.float-cmp]
|
[dev-dependencies.float-cmp]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
+10
-4
@@ -1,9 +1,13 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Indicates the transducer value is known to be impossible.
|
/// Indicates the transducer value is known to be impossible.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Error)]
|
||||||
|
#[error("invalid value")]
|
||||||
pub struct InvalidValue;
|
pub struct InvalidValue;
|
||||||
|
|
||||||
/// Indicates that the encoded data is not valid for the type.
|
/// Indicates that the encoded data is not valid for the type.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Error)]
|
||||||
|
#[error("invalid encoding")]
|
||||||
pub struct InvalidEncoding;
|
pub struct InvalidEncoding;
|
||||||
/// An error that it is likely impossible to recover from. This error should only be created in
|
/// An error that it is likely impossible to recover from. This error should only be created in
|
||||||
/// situations where attempts to recover have already been attempted and have failed. Error handling
|
/// situations where attempts to recover have already been attempted and have failed. Error handling
|
||||||
@@ -12,11 +16,13 @@ pub struct InvalidEncoding;
|
|||||||
///
|
///
|
||||||
/// In many systems there can be a single function for handling any critical error as a critical
|
/// In many systems there can be a single function for handling any critical error as a critical
|
||||||
/// error always means everything needs to be stopped.
|
/// error always means everything needs to be stopped.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Error)]
|
||||||
pub enum CriticalError {
|
pub enum CriticalError {
|
||||||
/// Critical communication failed and retries are either impossible or also failed.
|
/// Critical communication failed and retries are either impossible or also failed.
|
||||||
|
#[error("critical communication failure")]
|
||||||
Communication,
|
Communication,
|
||||||
InvalidValue(InvalidValue),
|
#[error(transparent)]
|
||||||
|
InvalidValue(#[from] InvalidValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A state of this type may mean the program has encountered an error that prevents it from continuing to run
|
/// A state of this type may mean the program has encountered an error that prevents it from continuing to run
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
use crate::error::InvalidValue;
|
|
||||||
use crate::quantity::{DeciCelsius, MilliVolts, Quantity};
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn convert(
|
|
||||||
voltage: MilliVolts<i16>,
|
|
||||||
) -> Result<DeciCelsius<i16>, InvalidValue> {
|
|
||||||
const MIN_VOLTAGE: MilliVolts<i16> = MilliVolts(-550);
|
|
||||||
const MAX_VOLTAGE: MilliVolts<i16> = MilliVolts(1_500);
|
|
||||||
|
|
||||||
if voltage >= MIN_VOLTAGE && voltage <= MAX_VOLTAGE {
|
|
||||||
Ok(DeciCelsius(voltage.value()))
|
|
||||||
} else {
|
|
||||||
Err(InvalidValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
mod thermocouple;
|
pub mod thermocouple;
|
||||||
|
|
||||||
#[cfg(feature = "lm35")]
|
|
||||||
pub mod lm35;
|
|
||||||
|
|
||||||
#[cfg(feature = "thermistor")]
|
#[cfg(feature = "thermistor")]
|
||||||
pub mod thermistor;
|
pub mod thermistor;
|
||||||
|
|
||||||
#[cfg(feature = "thermocouple-k")]
|
|
||||||
pub use thermocouple::type_k as thermocouple_k;
|
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
#[cfg(feature = "thermocouple-k")]
|
||||||
|
pub mod k {
|
||||||
|
//! Type K thermocouple conversion using [f64] arithmetic internally.
|
||||||
|
//!
|
||||||
|
//! All conversion functions clamp their inputs to the valid range rather than returning errors.
|
||||||
|
//! Use the `MIN_*` / `MAX_*` constants to check whether an input is in range before
|
||||||
|
//! calling a conversion function if out-of-range detection is needed.
|
||||||
|
|
||||||
|
use libm::exp;
|
||||||
|
use crate::quantity::{Celsius, MilliVolts};
|
||||||
|
|
||||||
|
// ----- Voltage-to-temperature constants -----
|
||||||
|
|
||||||
|
/// Minimum voltage accepted by the NIST inverse polynomial (-5.891 mV ≈ -210 °C).
|
||||||
|
pub const MIN_VOLTAGE: MilliVolts<f64> = MilliVolts(-5.891);
|
||||||
|
/// Maximum voltage accepted by the NIST inverse polynomial (54.886 mV ≈ 1372 °C).
|
||||||
|
pub const MAX_VOLTAGE: MilliVolts<f64> = MilliVolts(54.886);
|
||||||
|
|
||||||
|
// ----- Temperature-to-voltage constants -----
|
||||||
|
|
||||||
|
/// Minimum temperature accepted by the NIST forward polynomial (-270 °C).
|
||||||
|
pub const MIN_TEMP_POLY: Celsius<f64> = Celsius(-270.0);
|
||||||
|
/// Maximum temperature accepted by the NIST forward polynomial (1372 °C).
|
||||||
|
pub const MAX_TEMP_POLY: Celsius<f64> = Celsius(1372.0);
|
||||||
|
|
||||||
|
/// Minimum temperature accepted by the Seebeck approximation (-2 °C).
|
||||||
|
pub const MIN_TEMP_SEEBECK: Celsius<f32> = Celsius(-2.0);
|
||||||
|
/// Maximum temperature accepted by the Seebeck approximation (800 °C).
|
||||||
|
pub const MAX_TEMP_SEEBECK: Celsius<f32> = Celsius(800.0);
|
||||||
|
|
||||||
|
// ----- Voltage to temperature (inverse polynomial) -----
|
||||||
|
|
||||||
|
/// Core NIST ITS-90 inverse polynomial for type K.
|
||||||
|
/// Input is clamped to [`MIN_VOLTAGE`]..=[`MAX_VOLTAGE`].
|
||||||
|
fn voltage_to_temp(voltage: MilliVolts<f64>) -> Celsius<f32> {
|
||||||
|
let mv = voltage.0.clamp(MIN_VOLTAGE.0, MAX_VOLTAGE.0);
|
||||||
|
let mv_pow2 = mv * mv;
|
||||||
|
let mv_pow3 = mv_pow2 * mv;
|
||||||
|
let mv_pow4 = mv_pow3 * mv;
|
||||||
|
let mv_pow5 = mv_pow4 * mv;
|
||||||
|
let mv_pow6 = mv_pow5 * mv;
|
||||||
|
|
||||||
|
let celsius = if mv >= -5.891 && mv <= 0.0 {
|
||||||
|
let mv_pow7 = mv_pow6 * mv;
|
||||||
|
let mv_pow8 = mv_pow7 * mv;
|
||||||
|
|
||||||
|
2.5173462E+1 * mv
|
||||||
|
+ -1.1662878 * mv_pow2
|
||||||
|
+ -1.0833638 * mv_pow3
|
||||||
|
+ -8.9773540E-1 * mv_pow4
|
||||||
|
+ -3.7342377E-1 * mv_pow5
|
||||||
|
+ -8.6632643E-2 * mv_pow6
|
||||||
|
+ -1.0450598E-2 * mv_pow7
|
||||||
|
+ -5.1920577E-4 * mv_pow8
|
||||||
|
} else if mv > 0.0 && mv < 20.644 {
|
||||||
|
let mv_pow7 = mv_pow6 * mv;
|
||||||
|
let mv_pow8 = mv_pow7 * mv;
|
||||||
|
let mv_pow9 = mv_pow8 * mv;
|
||||||
|
|
||||||
|
2.508355E+1 * mv
|
||||||
|
+ 7.860106E-2 * mv_pow2
|
||||||
|
+ -2.503131E-1 * mv_pow3
|
||||||
|
+ 8.315270E-2 * mv_pow4
|
||||||
|
+ -1.228034E-2 * mv_pow5
|
||||||
|
+ 9.804036E-4 * mv_pow6
|
||||||
|
+ -4.413030E-5 * mv_pow7
|
||||||
|
+ 1.057734E-6 * mv_pow8
|
||||||
|
+ -1.052755E-8 * mv_pow9
|
||||||
|
} else {
|
||||||
|
// mv >= 20.644 && mv <= 54.886
|
||||||
|
-1.318058e2
|
||||||
|
+ 4.830222E+1 * mv
|
||||||
|
+ -1.646031 * mv_pow2
|
||||||
|
+ 5.464731E-2 * mv_pow3
|
||||||
|
+ -9.650715E-4 * mv_pow4
|
||||||
|
+ 8.802193E-6 * mv_pow5
|
||||||
|
+ -3.110810E-8 * mv_pow6
|
||||||
|
};
|
||||||
|
|
||||||
|
Celsius(celsius as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- Public voltage-to-temperature conversions -----
|
||||||
|
|
||||||
|
/// Convert thermocouple voltage to temperature by directly adding the reference junction
|
||||||
|
/// temperature to the polynomial result for cold-junction compensation.
|
||||||
|
///
|
||||||
|
/// Can be useful compared to [`convert_seebeck`] when the reference temperature or the
|
||||||
|
/// temperature being read by the thermocouple is fairly close to 0 °C.
|
||||||
|
///
|
||||||
|
/// Voltage is clamped to [`MIN_VOLTAGE`]..=[`MAX_VOLTAGE`].
|
||||||
|
///
|
||||||
|
/// Uses the [NIST type K inverse polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
|
#[inline]
|
||||||
|
pub fn convert_direct(
|
||||||
|
voltage: MilliVolts<f64>,
|
||||||
|
r_junction: Celsius<f32>,
|
||||||
|
) -> Celsius<f32> {
|
||||||
|
voltage_to_temp(voltage) + r_junction
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert thermocouple voltage to temperature using a constant Seebeck coefficient to
|
||||||
|
/// correct the input voltage for cold-junction compensation.
|
||||||
|
///
|
||||||
|
/// Probably the right choice most of the time.
|
||||||
|
///
|
||||||
|
/// Voltage is clamped to [`MIN_VOLTAGE`]..=[`MAX_VOLTAGE`].
|
||||||
|
/// Reference junction temperature is clamped to [`MIN_TEMP_SEEBECK`]..=[`MAX_TEMP_SEEBECK`].
|
||||||
|
///
|
||||||
|
/// Uses the [NIST type K inverse polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
|
#[inline]
|
||||||
|
pub fn convert_seebeck(
|
||||||
|
voltage: MilliVolts<f64>,
|
||||||
|
r_junction: Celsius<f32>,
|
||||||
|
) -> Celsius<f32> {
|
||||||
|
let voltage_correction = temp_to_voltage_seebeck(r_junction);
|
||||||
|
voltage_to_temp(MilliVolts(voltage.0 + voltage_correction.0 as f64))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert thermocouple voltage to temperature using the full NIST forward polynomial to
|
||||||
|
/// correct the input voltage for cold-junction compensation.
|
||||||
|
///
|
||||||
|
/// This is the most accurate method but uses the most processor cycles by a wide margin.
|
||||||
|
///
|
||||||
|
/// Voltage is clamped to [`MIN_VOLTAGE`]..=[`MAX_VOLTAGE`].
|
||||||
|
/// Reference junction temperature is clamped to [`MIN_TEMP_POLY`]..=[`MAX_TEMP_POLY`].
|
||||||
|
///
|
||||||
|
/// Uses the [NIST type K inverse polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
|
#[inline]
|
||||||
|
pub fn convert_polynomial(
|
||||||
|
voltage: MilliVolts<f64>,
|
||||||
|
r_junction: Celsius<f64>,
|
||||||
|
) -> Celsius<f32> {
|
||||||
|
let voltage_correction = temp_to_voltage_poly(r_junction);
|
||||||
|
voltage_to_temp(MilliVolts(voltage.0 + voltage_correction.0 as f64))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- Temperature to voltage (forward functions) -----
|
||||||
|
|
||||||
|
/// Convert a temperature to a type K thermocouple voltage using the full NIST forward
|
||||||
|
/// polynomial.
|
||||||
|
///
|
||||||
|
/// Temperature is clamped to [`MIN_TEMP_POLY`]..=[`MAX_TEMP_POLY`].
|
||||||
|
pub fn temp_to_voltage_poly(temperature: Celsius<f64>) -> MilliVolts<f32> {
|
||||||
|
let celsius = temperature.0.clamp(MIN_TEMP_POLY.0, MAX_TEMP_POLY.0);
|
||||||
|
let cel_pow2 = celsius * celsius;
|
||||||
|
let cel_pow3 = cel_pow2 * celsius;
|
||||||
|
let cel_pow4 = cel_pow3 * celsius;
|
||||||
|
let cel_pow5 = cel_pow4 * celsius;
|
||||||
|
let cel_pow6 = cel_pow5 * celsius;
|
||||||
|
let cel_pow7 = cel_pow6 * celsius;
|
||||||
|
let cel_pow8 = cel_pow7 * celsius;
|
||||||
|
let cel_pow9 = cel_pow8 * celsius;
|
||||||
|
|
||||||
|
let mv = if celsius >= -270.0 && celsius < 0.0 {
|
||||||
|
let cel_pow10 = cel_pow9 * celsius;
|
||||||
|
|
||||||
|
0.394501280250E-01 * celsius
|
||||||
|
+ 0.236223735980E-04 * cel_pow2
|
||||||
|
+ -0.328589067840E-06 * cel_pow3
|
||||||
|
+ -0.499048287770E-08 * cel_pow4
|
||||||
|
+ -0.675090591730E-10 * cel_pow5
|
||||||
|
+ -0.574103274280E-12 * cel_pow6
|
||||||
|
+ -0.310888728940E-14 * cel_pow7
|
||||||
|
+ -0.104516093650E-16 * cel_pow8
|
||||||
|
+ -0.198892668780E-19 * cel_pow9
|
||||||
|
+ -0.163226974860E-22 * cel_pow10
|
||||||
|
} else {
|
||||||
|
// celsius >= 0.0 && celsius <= 1372.0
|
||||||
|
let base = celsius - 0.126968600000E+03;
|
||||||
|
let exponent = -0.118343200000E-03 * (base * base);
|
||||||
|
let addition = 0.1185976 * exp(exponent);
|
||||||
|
|
||||||
|
-0.176004136860E-01
|
||||||
|
+ 0.389212049750E-01 * celsius
|
||||||
|
+ 0.185587700320E-04 * cel_pow2
|
||||||
|
+ -0.994575928740E-07 * cel_pow3
|
||||||
|
+ 0.318409457190E-09 * cel_pow4
|
||||||
|
+ -0.560728448890E-12 * cel_pow5
|
||||||
|
+ 0.560750590590E-15 * cel_pow6
|
||||||
|
+ -0.320207200030E-18 * cel_pow7
|
||||||
|
+ 0.971511471520E-22 * cel_pow8
|
||||||
|
+ -0.121047212750E-25 * cel_pow9
|
||||||
|
+ addition
|
||||||
|
};
|
||||||
|
|
||||||
|
MilliVolts(mv as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a temperature to a type K thermocouple voltage using a constant Seebeck
|
||||||
|
/// coefficient approximation (41 µV/°C).
|
||||||
|
///
|
||||||
|
/// Temperature is clamped to [`MIN_TEMP_SEEBECK`]..=[`MAX_TEMP_SEEBECK`].
|
||||||
|
#[inline]
|
||||||
|
pub fn temp_to_voltage_seebeck(temperature: Celsius<f32>) -> MilliVolts<f32> {
|
||||||
|
MilliVolts(0.041 * temperature.0.clamp(MIN_TEMP_SEEBECK.0, MAX_TEMP_SEEBECK.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#[cfg(feature = "thermocouple-k")]
|
|
||||||
pub mod type_k;
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
//! Note - Thermocouple conversion uses [f64] arithmetic internally.
|
|
||||||
|
|
||||||
use libm::exp;
|
|
||||||
use crate::error::InvalidValue;
|
|
||||||
use crate::quantity::{Celsius, MilliVolts, Quantity};
|
|
||||||
|
|
||||||
fn _convert(
|
|
||||||
voltage: MilliVolts<f64>,
|
|
||||||
) -> Result<Celsius<f32>, InvalidValue> {
|
|
||||||
let mv = voltage.value();
|
|
||||||
let mv_pow2 = mv * mv;
|
|
||||||
let mv_pow3 = mv_pow2 * mv;
|
|
||||||
let mv_pow4 = mv_pow3 * mv;
|
|
||||||
let mv_pow5 = mv_pow4 * mv;
|
|
||||||
let mv_pow6 = mv_pow5 * mv;
|
|
||||||
|
|
||||||
if mv >= -5.891 && mv <= 0.0 {
|
|
||||||
let mv_pow7 = mv_pow6 * mv;
|
|
||||||
let mv_pow8 = mv_pow7 * mv;
|
|
||||||
|
|
||||||
let celsius = 2.5173462E+1 * mv
|
|
||||||
+ -1.1662878 * mv_pow2
|
|
||||||
+ -1.0833638 * mv_pow3
|
|
||||||
+ -8.9773540E-1 * mv_pow4
|
|
||||||
+ -3.7342377E-1 * mv_pow5
|
|
||||||
+ -8.6632643E-2 * mv_pow6
|
|
||||||
+ -1.0450598E-2 * mv_pow7
|
|
||||||
+ -5.1920577E-4 * mv_pow8;
|
|
||||||
|
|
||||||
Ok(Celsius(celsius as f32))
|
|
||||||
} else if mv > 0.0 && mv < 20.644 {
|
|
||||||
let mv_pow7 = mv_pow6 * mv;
|
|
||||||
let mv_pow8 = mv_pow7 * mv;
|
|
||||||
let mv_pow9 = mv_pow8 * mv;
|
|
||||||
|
|
||||||
let celsius = 2.508355E+1 * mv
|
|
||||||
+ 7.860106E-2 * mv_pow2
|
|
||||||
+ -2.503131E-1 * mv_pow3
|
|
||||||
+ 8.315270E-2 * mv_pow4
|
|
||||||
+ -1.228034E-2 * mv_pow5
|
|
||||||
+ 9.804036E-4 * mv_pow6
|
|
||||||
+ -4.413030E-5 * mv_pow7
|
|
||||||
+ 1.057734E-6 * mv_pow8
|
|
||||||
+ -1.052755E-8 * mv_pow9;
|
|
||||||
|
|
||||||
Ok(Celsius(celsius as f32))
|
|
||||||
} else if mv >= 20.644 && mv <= 54.886 {
|
|
||||||
let celsius = -1.318058e2
|
|
||||||
+ 4.830222E+1 * mv
|
|
||||||
+ -1.646031 * mv_pow2
|
|
||||||
+ 5.464731E-2 * mv_pow3
|
|
||||||
+ -9.650715E-4 * mv_pow4
|
|
||||||
+ 8.802193E-6 * mv_pow5
|
|
||||||
+ -3.110810E-8 * mv_pow6;
|
|
||||||
|
|
||||||
Ok(Celsius(celsius as f32))
|
|
||||||
} else {
|
|
||||||
Err(InvalidValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
|
||||||
/// directly adding the reference junction temperature to the result for offset compensation.
|
|
||||||
///
|
|
||||||
/// Can be useful compared to [convert_seebeck] when the reference temperature or the temperature
|
|
||||||
/// being read by the thermocouple is fairly close to 0.
|
|
||||||
///
|
|
||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
|
||||||
#[inline]
|
|
||||||
pub fn convert_direct(
|
|
||||||
voltage: MilliVolts<f64>,
|
|
||||||
r_junction: Celsius<f32>,
|
|
||||||
) -> Result<Celsius<f32>, InvalidValue> {
|
|
||||||
let base_temp = _convert(voltage)?;
|
|
||||||
|
|
||||||
Ok(base_temp + r_junction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
|
||||||
/// using a constant seebeck coefficient to correct the input voltage for offset compensation.
|
|
||||||
///
|
|
||||||
/// Probably the right choice most of the time.
|
|
||||||
///
|
|
||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
|
||||||
#[inline]
|
|
||||||
pub fn convert_seebeck(
|
|
||||||
voltage: MilliVolts<f64>,
|
|
||||||
r_junction: Celsius<f32>,
|
|
||||||
) -> Result<Celsius<f32>, InvalidValue> {
|
|
||||||
let voltage_correction = temp_to_voltage_seebeck(r_junction)?;
|
|
||||||
_convert(MilliVolts(voltage.0 + voltage_correction.0 as f64))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
|
||||||
/// using a polynomial to correct the input voltage for offset compensation.
|
|
||||||
///
|
|
||||||
/// This is the most accurate method but uses the most processor cycles by a wide margin.
|
|
||||||
///
|
|
||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
|
||||||
#[inline]
|
|
||||||
pub fn convert_polynomial(
|
|
||||||
voltage: MilliVolts<f64>,
|
|
||||||
r_junction: Celsius<f64>,
|
|
||||||
) -> Result<Celsius<f32>, InvalidValue> {
|
|
||||||
let voltage_correction = temp_to_voltage_poly(r_junction)?;
|
|
||||||
_convert(MilliVolts(voltage.0 + voltage_correction.0 as f64))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn temp_to_voltage_poly(
|
|
||||||
temperature: Celsius<f64>,
|
|
||||||
) -> Result<MilliVolts<f32>, InvalidValue> {
|
|
||||||
let celsius = temperature.value();
|
|
||||||
let cel_pow2 = celsius * celsius;
|
|
||||||
let cel_pow3 = cel_pow2 * celsius;
|
|
||||||
let cel_pow4 = cel_pow3 * celsius;
|
|
||||||
let cel_pow5 = cel_pow4 * celsius;
|
|
||||||
let cel_pow6 = cel_pow5 * celsius;
|
|
||||||
let cel_pow7 = cel_pow6 * celsius;
|
|
||||||
let cel_pow8 = cel_pow7 * celsius;
|
|
||||||
let cel_pow9 = cel_pow8 * celsius;
|
|
||||||
|
|
||||||
if celsius >= -270.0 && celsius < 0.0 {
|
|
||||||
let cel_pow10 = cel_pow9 * celsius;
|
|
||||||
|
|
||||||
let mv = 0.394501280250E-01 * celsius
|
|
||||||
+ 0.236223735980E-04 * cel_pow2
|
|
||||||
+ -0.328589067840E-06 * cel_pow3
|
|
||||||
+ -0.499048287770E-08 * cel_pow4
|
|
||||||
+ -0.675090591730E-10 * cel_pow5
|
|
||||||
+ -0.574103274280E-12 * cel_pow6
|
|
||||||
+ -0.310888728940E-14 * cel_pow7
|
|
||||||
+ -0.104516093650E-16 * cel_pow8
|
|
||||||
+ -0.198892668780E-19 * cel_pow9
|
|
||||||
+ -0.163226974860E-22 * cel_pow10;
|
|
||||||
|
|
||||||
Ok(MilliVolts(mv as f32))
|
|
||||||
} else if celsius >= 0.0 && celsius <= 1372.0 {
|
|
||||||
let base = celsius - 0.126968600000E+03;
|
|
||||||
let exponent = -0.118343200000E-03 * (base * base);
|
|
||||||
let addition = 0.1185976 * exp(exponent);
|
|
||||||
|
|
||||||
let mv = -0.176004136860E-01
|
|
||||||
+ 0.389212049750E-01 * celsius
|
|
||||||
+ 0.185587700320E-04 * cel_pow2
|
|
||||||
+ -0.994575928740E-07 * cel_pow3
|
|
||||||
+ 0.318409457190E-09 * cel_pow4
|
|
||||||
+ -0.560728448890E-12 * cel_pow5
|
|
||||||
+ 0.560750590590E-15 * cel_pow6
|
|
||||||
+ -0.320207200030E-18 * cel_pow7
|
|
||||||
+ 0.971511471520E-22 * cel_pow8
|
|
||||||
+ -0.121047212750E-25 * cel_pow9
|
|
||||||
+ addition;
|
|
||||||
|
|
||||||
Ok(MilliVolts(mv as f32))
|
|
||||||
} else {
|
|
||||||
Err(InvalidValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn temp_to_voltage_seebeck(
|
|
||||||
temperature: Celsius<f32>,
|
|
||||||
) -> Result<MilliVolts<f32>, InvalidValue> {
|
|
||||||
if temperature.value() >= -2.0 && temperature.value() <= 800.0 {
|
|
||||||
Ok(MilliVolts(0.041 * temperature.value()))
|
|
||||||
} else {
|
|
||||||
Err(InvalidValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user