#![cfg_attr(any(feature = "k-type"), doc = " ```rust")]
#![cfg_attr(not(any(feature = "k-type")), doc = " ```rust,ignore")]
#![cfg_attr(any(feature = "k-type"), doc = " ```rust")]
#![cfg_attr(not(any(feature = "k-type")), doc = " ```rust,ignore")]
#![no_std]
#![forbid(unsafe_code)]
#![warn(
bare_trait_objects,
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results
)]
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(any(feature = "f32"))]
#[doc = "Underlying storage type: `f32`"]
pub type FP = f32;
#[cfg(any(feature = "f64"))]
#[doc = "Underlying storage type: `f64`"]
pub type FP = f64;
#[cfg(not(any(feature = "f32", feature = "f64")))]
compile_error!(
"A least one underlying storage type must be enabled.
Use a feature gate to enable."
);
#[cfg(all(feature = "f32", feature = "f64"))]
compile_error!(
"Cannot enable multiple storage types. Try setting
`default-features = false`."
);
#[macro_use]
mod test_utils;
mod units;
pub use units::{
Celsius, FPExt, Fahrenheit, Kelvin, Millivolts, Rankine, Reaumur,
};
pub trait ThermocoupleCore<W> {
fn sense_temperature(&self, voltage: Millivolts) -> W;
fn sense_voltage(&self, temperature: W) -> Millivolts;
}
macro_rules! thermocouple {
($($Type:ident, $mod:ident: $doc:expr => $($unit:ty),+;)*) => {
$(
mod $mod;
#[doc=$doc]
#[derive(Clone, Copy, Debug)]
pub struct $Type {
reference_potential: Millivolts,
}
impl $Type {
pub fn new() -> $Type {
$Type {
reference_potential: $mod::e((25.0).celsius()),
}
}
pub fn with_reference_temperature<T>(
self,
reference_temperature: T,
) -> Self where
T: Into<Celsius>,
{
$Type {
reference_potential: $mod::e(reference_temperature.into()),
}
}
}
impl Default for $Type {
fn default() -> Self {
$Type::new()
}
}
$(
impl ThermocoupleCore<$unit> for $Type {
fn sense_temperature(
&self,
voltage: Millivolts,
) -> $unit {
$mod::t(voltage + self.reference_potential).into()
}
fn sense_voltage(&self, temperature: $unit) -> Millivolts {
$mod::e(temperature.into()) - self.reference_potential
}
}
)+
)*
};
}
#[cfg(any(feature = "k-type"))]
thermocouple! {
KType, k_type: "Type K thermocouple (chromel-alumel)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
}
thermocouple! {
BType, b_type: "Type B thermocouple (platinum/rhodium alloy)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
EType, e_type: "Type E thermocouple (chromel-constantan)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
JType, j_type: "Type J thermocouple (iron-constantan)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
NType, n_type: "Type N thermocouple (nicrosil-nisil)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
RType, r_type: "Type R thermocouple (platinum/rhodium alloy)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
SType, s_type: "Type S thermocouple (platinum/rhodium alloy)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
TType, t_type: "Type T thermocouple (copper-constantan)" =>
Celsius, Kelvin, Fahrenheit, Rankine, Reaumur;
}
pub mod prelude {
pub use crate::units::FPExt as _thermocouple_FPExt;
pub use crate::ThermocoupleCore;
pub use crate::{
Celsius, Fahrenheit, Kelvin, Millivolts, Rankine, Reaumur,
};
}
#[cfg(test)]
mod tests {
use super::*;
pub fn compare(a: FP, b: FP, tol: FP) {
assert!((a - b).abs() < tol);
}
macro_rules! test_temperature_default {
($($Type:ident, $testname:ident, $result:expr;)*) => {
$(
#[test]
fn $testname() {
let temperature: Celsius =
$Type::new().sense_temperature(Millivolts(1.1));
println!("{}", temperature.0);
compare(temperature.0, $result, 0.05);
}
)*
}
}
#[cfg(any(feature = "k-type"))]
test_temperature_default! {
KType, k_type_1_1m_v, 51.870;
}
test_temperature_default! {
BType, b_type_1_1m_v, 470.511;
EType, e_type_1_1m_v, 42.808;
JType, j_type_1_1m_v, 46.058;
NType, n_type_1_1m_v, 64.953;
RType, r_type_1_1m_v, 173.779;
SType, s_type_1_1m_v, 176.278;
TType, t_type_1_1m_v, 51.312;
}
}