Migrated from uom to custom quantity implementation.
This commit is contained in:
37
Cargo.toml
37
Cargo.toml
@ -9,7 +9,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://git.bfpower.io/BFPOWER/physical"
|
repository = "https://git.bfpower.io/BFPOWER/physical"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -22,11 +22,8 @@ version = "0.2.*"
|
|||||||
default-features = false
|
default-features = false
|
||||||
[workspace.dependencies.libm]
|
[workspace.dependencies.libm]
|
||||||
version = "0.2.*"
|
version = "0.2.*"
|
||||||
# Units of measurement
|
[workspace.dependencies.float-cmp]
|
||||||
[workspace.dependencies.uom]
|
version = "0.9.*"
|
||||||
version = "0.36.*"
|
|
||||||
default-features = false
|
|
||||||
features = ["f32", "si"]
|
|
||||||
# Logging
|
# Logging
|
||||||
[workspace.dependencies.tracing]
|
[workspace.dependencies.tracing]
|
||||||
version = "0.1.*"
|
version = "0.1.*"
|
||||||
@ -61,7 +58,6 @@ git = "https://git.bfpower.io/BFPOWER/bfpower-drivers.git"
|
|||||||
features = ["defmt"]
|
features = ["defmt"]
|
||||||
[workspace.dependencies.ads1256]
|
[workspace.dependencies.ads1256]
|
||||||
git = "https://git.bfpower.io/BFPOWER/bfpower-drivers.git"
|
git = "https://git.bfpower.io/BFPOWER/bfpower-drivers.git"
|
||||||
features = ["uom"]
|
|
||||||
# Embassy
|
# Embassy
|
||||||
[workspace.dependencies.embassy-futures]
|
[workspace.dependencies.embassy-futures]
|
||||||
version = "0.1.*"
|
version = "0.1.*"
|
||||||
@ -85,7 +81,9 @@ features = ["defmt", "unstable-pac"]
|
|||||||
[workspace.dependencies.embassy-nrf]
|
[workspace.dependencies.embassy-nrf]
|
||||||
version = "0.1.*"
|
version = "0.1.*"
|
||||||
features = ["defmt"]
|
features = ["defmt"]
|
||||||
# Macros
|
# Meta
|
||||||
|
[workspace.dependencies.derive_more]
|
||||||
|
version = "0.99.*"
|
||||||
[workspace.dependencies.syn]
|
[workspace.dependencies.syn]
|
||||||
version = "2.0.*"
|
version = "2.0.*"
|
||||||
features = ["extra-traits", "parsing"]
|
features = ["extra-traits", "parsing"]
|
||||||
@ -107,6 +105,8 @@ readme.workspace = true
|
|||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
std = ["num-traits/std"]
|
||||||
|
libm = ["dep:libm", "num-traits/libm"]
|
||||||
resistive-divider = []
|
resistive-divider = []
|
||||||
thermocouple-k = ["libm"]
|
thermocouple-k = ["libm"]
|
||||||
thermistor = ["libm"]
|
thermistor = ["libm"]
|
||||||
@ -114,11 +114,22 @@ lm35 = []
|
|||||||
pid = []
|
pid = []
|
||||||
stm32 = []
|
stm32 = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies.num-traits]
|
||||||
uom = { workspace = true }
|
workspace = true
|
||||||
num-traits = { workspace = true }
|
[dependencies.derive_more]
|
||||||
libm = { workspace = true, optional = true }
|
workspace = true
|
||||||
serde = { workspace = true, optional = true }
|
[dependencies.defmt]
|
||||||
|
workspace = true
|
||||||
|
optional = true
|
||||||
|
[dependencies.libm]
|
||||||
|
workspace = true
|
||||||
|
optional = true
|
||||||
|
[dependencies.serde]
|
||||||
|
workspace = true
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dev-dependencies.float-cmp]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------------------------------------------
|
||||||
#----- Profiles ------------------------
|
#----- Profiles ------------------------
|
||||||
|
@ -21,8 +21,6 @@ workspace = true
|
|||||||
workspace = true
|
workspace = true
|
||||||
[dependencies.defmt]
|
[dependencies.defmt]
|
||||||
workspace = true
|
workspace = true
|
||||||
[dependencies.uom]
|
|
||||||
workspace = true
|
|
||||||
[dependencies.embassy-stm32]
|
[dependencies.embassy-stm32]
|
||||||
workspace = true
|
workspace = true
|
||||||
optional = true
|
optional = true
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
use uom::si::electric_potential::millivolt;
|
use crate::quantity::{MilliVolts, Quantity};
|
||||||
use uom::si::quantities::ElectricPotential;
|
|
||||||
|
|
||||||
pub fn reading_to_voltage(
|
pub fn reading_to_voltage(
|
||||||
reading: u16,
|
reading: u32,
|
||||||
reference_voltage: ElectricPotential<f32>,
|
reference_voltage: MilliVolts<u32>,
|
||||||
v_ref_int_scale: f32,
|
v_ref_int_scale: u32,
|
||||||
) -> ElectricPotential<f32> {
|
) -> MilliVolts<u16> {
|
||||||
let reference_mv = reference_voltage.get::<millivolt>();
|
MilliVolts((reading * v_ref_int_scale / reference_voltage.value()) as u16)
|
||||||
let reading = f32::from(reading);
|
|
||||||
|
|
||||||
ElectricPotential::new::<millivolt>(reading * v_ref_int_scale / reference_mv)
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,19 @@
|
|||||||
use uom::si::electric_potential::volt;
|
use crate::quantity::{Ohms, Quantity, Volts};
|
||||||
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.
|
/// Given the resistance of the second resistor in a resistive voltage divider, calculate the resistance of the first resistor.
|
||||||
pub fn solve_r1(
|
pub fn solve_r1(
|
||||||
voltage_src: ElectricPotential<f32>,
|
voltage_src: Volts<f32>,
|
||||||
voltage_read: ElectricPotential<f32>,
|
voltage_read: Volts<f32>,
|
||||||
r2: ElectricalResistance<f32>,
|
r2: Ohms<f32>,
|
||||||
) -> ElectricalResistance<f32> {
|
) -> Ohms<f32> {
|
||||||
let volts_src = voltage_src.get::<volt>();
|
Ohms(r2.value() * (voltage_src.value() / voltage_read.value() - 1.0))
|
||||||
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.
|
/// Given the resistance of the first resistor in a resistive voltage divider, calculate the resistance of the second resistor.
|
||||||
pub fn solve_r2(
|
pub fn solve_r2(
|
||||||
voltage_src: ElectricPotential<f32>,
|
voltage_src: Volts<f32>,
|
||||||
voltage_read: ElectricPotential<f32>,
|
voltage_read: Volts<f32>,
|
||||||
r1: ElectricalResistance<f32>,
|
r1: Ohms<f32>,
|
||||||
) -> ElectricalResistance<f32> {
|
) -> Ohms<f32> {
|
||||||
let volts_src = voltage_src.get::<volt>();
|
Ohms(r1.value() * (1.0 / (voltage_src.value() / voltage_read.value()) - 1.0))
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#![no_std]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
pub mod transducer;
|
pub mod transducer;
|
||||||
pub mod control;
|
pub mod control;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
pub mod adc;
|
pub mod adc;
|
||||||
pub mod uom;
|
|
||||||
pub mod circuit;
|
pub mod circuit;
|
||||||
|
pub mod quantity;
|
||||||
|
|
||||||
pub use error::CriticalError;
|
pub use error::CriticalError;
|
||||||
|
22
src/quantity/irradiance.rs
Normal file
22
src/quantity/irradiance.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use derive_more::{Add, AddAssign, Display, Sub, SubAssign};
|
||||||
|
use crate::quantity::{Quantity, Value};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Watts per Square Meter ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct WattsPerSquareMeter<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for WattsPerSquareMeter<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"W/m²"
|
||||||
|
}
|
||||||
|
}
|
205
src/quantity/mod.rs
Normal file
205
src/quantity/mod.rs
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
mod irradiance;
|
||||||
|
mod resistance;
|
||||||
|
mod temperature;
|
||||||
|
mod voltage;
|
||||||
|
mod volume_rate;
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
pub use defmt_impl::*;
|
||||||
|
|
||||||
|
pub use irradiance::*;
|
||||||
|
pub use resistance::*;
|
||||||
|
pub use temperature::*;
|
||||||
|
pub use voltage::*;
|
||||||
|
pub use volume_rate::*;
|
||||||
|
|
||||||
|
use core::fmt::Display;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::ops::{Add, Sub};
|
||||||
|
use num_traits::{FromPrimitive, Num, NumCast};
|
||||||
|
|
||||||
|
const DECA: u8 = 10;
|
||||||
|
const DECI: u8 = 10;
|
||||||
|
const HECTO: u8 = 100;
|
||||||
|
const CENTI: u8 = 100;
|
||||||
|
const KILO: u16 = 1_000;
|
||||||
|
const MILLI: u16 = 1_000;
|
||||||
|
const MEGA: u32 = 1_000_000;
|
||||||
|
const MICRO: u32 = 1_000_000;
|
||||||
|
const GIGA: u32 = 1_000_000_000;
|
||||||
|
const NANO: u32 = 1_000_000_000;
|
||||||
|
|
||||||
|
pub trait Quantity<V: Value>: Copy + PartialEq + PartialOrd + Add + Sub {
|
||||||
|
fn value(self) -> V;
|
||||||
|
|
||||||
|
fn symbol() -> &'static str;
|
||||||
|
|
||||||
|
/// Returns a wrapper that implements [Display] and [defmt::Format] for [Quantity]s with core number values.
|
||||||
|
///
|
||||||
|
/// - `rounding` - Sets the number of decimal places to round to when formatting (currently ignored with defmt).
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(self, rounding: Option<usize>) -> Fmt<V, Self> {
|
||||||
|
Fmt::new(self, rounding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Value: Num + Copy + PartialOrd + FromPrimitive + NumCast + Display {
|
||||||
|
//----- Temperature ----------------------------------
|
||||||
|
#[inline(always)]
|
||||||
|
fn kelvins(self) -> Kelvins<Self> {
|
||||||
|
Kelvins(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn deci_kelvins(self) -> DeciKelvins<Self> {
|
||||||
|
DeciKelvins(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn degrees_celsius(self) -> DegreesCelsius<Self> {
|
||||||
|
DegreesCelsius(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn deci_degrees_celsius(self) -> DeciDegreesCelsius<Self> {
|
||||||
|
DeciDegreesCelsius(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----- Voltage ----------------------------------
|
||||||
|
#[inline(always)]
|
||||||
|
fn volts(self) -> Volts<Self> {
|
||||||
|
Volts(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn millivolts(self) -> MilliVolts<Self> {
|
||||||
|
MilliVolts(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----- Resistance ----------------------------------
|
||||||
|
#[inline(always)]
|
||||||
|
fn ohms(self) -> Ohms<Self> {
|
||||||
|
Ohms(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----- Volume rate ----------------------------------
|
||||||
|
#[inline(always)]
|
||||||
|
fn liters_per_minute(self) -> LitersPerMinute<Self> {
|
||||||
|
LitersPerMinute(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----- Irradiance ----------------------------------
|
||||||
|
#[inline(always)]
|
||||||
|
fn watts_per_square_meter(self) -> WattsPerSquareMeter<Self> {
|
||||||
|
WattsPerSquareMeter(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> Value for V where V: Num + Copy + PartialOrd + FromPrimitive + NumCast + Display {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Fmt<V: Value, Q: Quantity<V>> {
|
||||||
|
quantity: Q,
|
||||||
|
rounding: Option<usize>,
|
||||||
|
_phantom: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value, Q: Quantity<V>> Fmt<V, Q> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn new(quantity: Q, rounding: Option<usize>) -> Self {
|
||||||
|
Self {
|
||||||
|
quantity,
|
||||||
|
rounding,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value, Q: Quantity<V>> Display for Fmt<V, Q> {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self.rounding {
|
||||||
|
Some(places) => {
|
||||||
|
write!(f, "{:.prec$} {}", self.quantity.value(), Q::symbol(), prec = places)
|
||||||
|
},
|
||||||
|
None => write!(f, "{} {}", self.quantity.value(), Q::symbol()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
mod defmt_impl {
|
||||||
|
use super::*;
|
||||||
|
use defmt::{write, Format, Formatter};
|
||||||
|
|
||||||
|
impl<Q: Quantity<u8>> Format for Fmt<u8, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<u16>> Format for Fmt<u16, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<u32>> Format for Fmt<u32, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<u64>> Format for Fmt<u64, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<u128>> Format for Fmt<u128, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<i8>> Format for Fmt<i8, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<i16>> Format for Fmt<i16, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<i32>> Format for Fmt<i32, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<i64>> Format for Fmt<i64, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<i128>> Format for Fmt<i128, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<f32>> Format for Fmt<f32, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Quantity<f64>> Format for Fmt<f64, Q> {
|
||||||
|
fn format(&self, fmt: Formatter) {
|
||||||
|
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/quantity/resistance.rs
Normal file
22
src/quantity/resistance.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use derive_more::{Add, AddAssign, Display, Sub, SubAssign};
|
||||||
|
use crate::quantity::{Quantity, Value};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Ohms ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Ohms<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for Ohms<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"Ω"
|
||||||
|
}
|
||||||
|
}
|
165
src/quantity/temperature.rs
Normal file
165
src/quantity/temperature.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
use derive_more::{Add, AddAssign, Display, Sub, SubAssign};
|
||||||
|
use num_traits::float::FloatCore;
|
||||||
|
use crate::quantity::{DECI, Quantity, Value};
|
||||||
|
|
||||||
|
const KELVIN_CELSIUS_OFFSET: f64 = 273.15;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Kelvins ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Kelvins<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for Kelvins<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"K"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <V: Value> Kelvins<V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_degrees_celsius(self) -> DegreesCelsius<V> {
|
||||||
|
//TODO: Make const
|
||||||
|
let offset = V::from_f64(KELVIN_CELSIUS_OFFSET).unwrap();
|
||||||
|
DegreesCelsius(self.0 - offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_deci_kelvins(self) -> DeciKelvins<V> {
|
||||||
|
let multiplier = V::from_u8(DECI).unwrap();
|
||||||
|
DeciKelvins(self.0 * multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Deci Kelvins ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DeciKelvins<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for DeciKelvins<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"dK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value> DeciKelvins<V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_kelvins(self) -> Kelvins<V> {
|
||||||
|
let divisor = V::from_u8(DECI).unwrap();
|
||||||
|
Kelvins(self.0 / divisor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Degrees Celsius ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DegreesCelsius<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for DegreesCelsius<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"℃"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <V: Value> DegreesCelsius<V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_kelvins(self) -> Kelvins<V> {
|
||||||
|
//TODO: Make const
|
||||||
|
let offset = V::from_f64(KELVIN_CELSIUS_OFFSET).unwrap();
|
||||||
|
Kelvins(self.0 + offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_deci_degrees_celsius(self) -> DeciDegreesCelsius<V> {
|
||||||
|
let multiplier = V::from_u8(DECI).unwrap();
|
||||||
|
DeciDegreesCelsius(self.0 * multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Deci Degrees Celsius ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DeciDegreesCelsius<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for DeciDegreesCelsius<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"d℃"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value> DeciDegreesCelsius<V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_degrees_celsius(self) -> DegreesCelsius<V> {
|
||||||
|
let divisor = V::from_u8(DECI).unwrap();
|
||||||
|
DegreesCelsius(self.0 / divisor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Tests ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use float_cmp::assert_approx_eq;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_f32() {
|
||||||
|
let kelvins: Kelvins<f32> = 298.15.kelvins();
|
||||||
|
let deci_kelvins: DeciKelvins<f32> = 2_981.5.deci_kelvins();
|
||||||
|
let celsius: DegreesCelsius<f32> = 25.0.degrees_celsius();
|
||||||
|
let deci_celsius: DeciDegreesCelsius<f32> = 250.0.deci_degrees_celsius();
|
||||||
|
|
||||||
|
assert_approx_eq!(f32, kelvins.to_degrees_celsius().0, celsius.0);
|
||||||
|
assert_approx_eq!(f32, celsius.to_kelvins().0, kelvins.0);
|
||||||
|
|
||||||
|
assert_approx_eq!(f32, deci_kelvins.to_kelvins().0, kelvins.0);
|
||||||
|
assert_approx_eq!(f32, kelvins.to_deci_kelvins().0, deci_kelvins.0);
|
||||||
|
|
||||||
|
assert_approx_eq!(f32, deci_celsius.to_degrees_celsius().0, celsius.0);
|
||||||
|
assert_approx_eq!(f32, celsius.to_deci_degrees_celsius().0, deci_celsius.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_u16() {
|
||||||
|
let kelvins: Kelvins<u16> = 298.kelvins();
|
||||||
|
let degrees_celsius: DegreesCelsius<u16> = 25.degrees_celsius();
|
||||||
|
|
||||||
|
assert_eq!(degrees_celsius.0, kelvins.to_degrees_celsius().0);
|
||||||
|
}
|
||||||
|
}
|
86
src/quantity/voltage.rs
Normal file
86
src/quantity/voltage.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use derive_more::{Add, AddAssign, Display, Sub, SubAssign};
|
||||||
|
use crate::quantity::{Quantity, Value};
|
||||||
|
|
||||||
|
const VOLT_MV_RATIO: u16 = 1_000;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Volts ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Volts<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for Volts<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"V"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value> Volts<V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_millivolts(self) -> MilliVolts<V> {
|
||||||
|
let multiplier = V::from_u16(VOLT_MV_RATIO).unwrap();
|
||||||
|
MilliVolts(self.0 * multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- MilliVolts ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct MilliVolts<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for MilliVolts<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"mV"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Value> MilliVolts<V> {
|
||||||
|
pub fn to_volts(self) -> Volts<V> {
|
||||||
|
let divisor = V::from_u16(VOLT_MV_RATIO).unwrap();
|
||||||
|
Volts(self.0 / divisor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Tests ------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use float_cmp::assert_approx_eq;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_u32() {
|
||||||
|
let volts: Volts<u32> = 3.volts();
|
||||||
|
let millivolts: MilliVolts<u32> = 3_000.millivolts();
|
||||||
|
|
||||||
|
assert_eq!(volts.to_millivolts().0, millivolts.0);
|
||||||
|
assert_eq!(millivolts.to_volts().0, volts.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_f64() {
|
||||||
|
let volts: Volts<f64> = 3.0.volts();
|
||||||
|
let millivolts: MilliVolts<f64> = 3_000.0.millivolts();
|
||||||
|
|
||||||
|
assert_approx_eq!(f64, volts.to_millivolts().0, millivolts.0);
|
||||||
|
assert_approx_eq!(f64, millivolts.to_volts().0, volts.0);
|
||||||
|
}
|
||||||
|
}
|
22
src/quantity/volume_rate.rs
Normal file
22
src/quantity/volume_rate.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use derive_more::{Add, AddAssign, Display, Sub, SubAssign};
|
||||||
|
use crate::quantity::{Quantity, Value};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// ----- Liters per Minute------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Add, AddAssign, Sub, SubAssign, Display)]
|
||||||
|
#[display(fmt = "{} {}", _0, "Self::symbol()")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct LitersPerMinute<V: Value>(pub V);
|
||||||
|
|
||||||
|
impl <V: Value> Quantity<V> for LitersPerMinute<V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn value(self) -> V {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn symbol() -> &'static str {
|
||||||
|
"L/min"
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,15 @@
|
|||||||
use crate::error::InvalidValue;
|
use crate::error::InvalidValue;
|
||||||
use uom::si::electric_potential::volt;
|
use crate::quantity::{DeciDegreesCelsius, MilliVolts, Quantity};
|
||||||
use uom::si::quantities::{ElectricPotential, ThermodynamicTemperature};
|
|
||||||
use uom::si::thermodynamic_temperature::degree_celsius;
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert(
|
pub fn convert(
|
||||||
voltage: ElectricPotential<f32>,
|
voltage: MilliVolts<i16>,
|
||||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
) -> Result<DeciDegreesCelsius<i16>, InvalidValue> {
|
||||||
const MIN_VOLTS: f32 = -0.55;
|
const MIN_VOLTAGE: MilliVolts<i16> = MilliVolts(-550);
|
||||||
const MAX_VOLTS: f32 = 1.50;
|
const MAX_VOLTAGE: MilliVolts<i16> = MilliVolts(1_500);
|
||||||
const SCALE_FACTOR: f32 = 100.0;
|
|
||||||
|
|
||||||
let volts = voltage.get::<volt>();
|
if voltage >= MIN_VOLTAGE && voltage <= MAX_VOLTAGE {
|
||||||
|
Ok(DeciDegreesCelsius(voltage.value()))
|
||||||
if volts >= MIN_VOLTS && volts <= MAX_VOLTS {
|
|
||||||
let celsius = volts * SCALE_FACTOR;
|
|
||||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(celsius))
|
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidValue)
|
Err(InvalidValue)
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,25 @@
|
|||||||
use libm::{log, logf};
|
use libm::{log, logf};
|
||||||
use uom::si::electrical_resistance::ohm;
|
use crate::quantity::{Kelvins, Ohms};
|
||||||
use uom::si::quantities::{ThermodynamicTemperature, ElectricalResistance};
|
|
||||||
use uom::si::thermodynamic_temperature::kelvin;
|
|
||||||
|
|
||||||
/// Convert thermistor resistance to a temperature using beta parameter equation
|
/// Convert thermistor resistance to a temperature using beta parameter equation
|
||||||
pub fn convert_beta(
|
pub fn convert_beta(
|
||||||
resistance: ElectricalResistance<f32>,
|
resistance: Ohms<f32>,
|
||||||
beta: f32,
|
beta: f32,
|
||||||
reference_temp: ThermodynamicTemperature<f32>,
|
reference_temp: Kelvins<f32>,
|
||||||
reference_resist: ElectricalResistance<f32>,
|
reference_resist: Ohms<f32>,
|
||||||
) -> ThermodynamicTemperature<f32> {
|
) -> Kelvins<f32> {
|
||||||
let ohms = resistance.get::<ohm>();
|
let kelvins = 1.0 / ((1.0 / reference_temp.0) + (1.0 / beta) * logf(resistance.0 / reference_resist.0));
|
||||||
let reference_kelvin = reference_temp.get::<kelvin>();
|
Kelvins(kelvins)
|
||||||
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
|
/// Convert thermistor resistance to a temperature using Steinhart-Hart equation
|
||||||
pub fn convert_steinhart(
|
pub fn convert_steinhart(
|
||||||
resistance: ElectricalResistance<f32>,
|
resistance: Ohms<f64>,
|
||||||
a: f64,
|
a: f64,
|
||||||
b: f64,
|
b: f64,
|
||||||
c: f64,
|
c: f64,
|
||||||
) -> ThermodynamicTemperature<f32> {
|
) -> Kelvins<f32> {
|
||||||
let ohms = resistance.get::<ohm>() as f64;
|
let log_omhs = log(resistance.0);
|
||||||
|
|
||||||
let log_omhs = log(ohms);
|
|
||||||
let kelvins = 1.0 / (a + b * log_omhs + c * log_omhs * log_omhs * log_omhs);
|
let kelvins = 1.0 / (a + b * log_omhs + c * log_omhs * log_omhs * log_omhs);
|
||||||
ThermodynamicTemperature::new::<kelvin>(kelvins as f32)
|
Kelvins(kelvins as f32)
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,12 @@
|
|||||||
|
|
||||||
use libm::pow;
|
use libm::pow;
|
||||||
use crate::error::InvalidValue;
|
use crate::error::InvalidValue;
|
||||||
use uom::si::electric_potential::millivolt;
|
use crate::quantity::{DegreesCelsius, MilliVolts, Quantity};
|
||||||
use uom::si::quantities::{ElectricPotential, ThermodynamicTemperature};
|
|
||||||
use uom::si::thermodynamic_temperature::degree_celsius;
|
|
||||||
|
|
||||||
fn _convert(
|
fn _convert(
|
||||||
voltage: ElectricPotential<f32>,
|
voltage: MilliVolts<f64>,
|
||||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
) -> Result<DegreesCelsius<f32>, InvalidValue> {
|
||||||
let mv = voltage.get::<millivolt>() as f64;
|
let mv = voltage.value();
|
||||||
let mv_pow2 = mv * mv;
|
let mv_pow2 = mv * mv;
|
||||||
let mv_pow3 = mv_pow2 * mv;
|
let mv_pow3 = mv_pow2 * mv;
|
||||||
let mv_pow4 = mv_pow3 * mv;
|
let mv_pow4 = mv_pow3 * mv;
|
||||||
@ -29,7 +27,7 @@ fn _convert(
|
|||||||
+ -1.0450598E-2 * mv_pow7
|
+ -1.0450598E-2 * mv_pow7
|
||||||
+ -5.1920577E-4 * mv_pow8;
|
+ -5.1920577E-4 * mv_pow8;
|
||||||
|
|
||||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(celsius as f32))
|
Ok(DegreesCelsius(celsius as f32))
|
||||||
} else if mv > 0.0 && mv < 20.644 {
|
} else if mv > 0.0 && mv < 20.644 {
|
||||||
let mv_pow7 = mv_pow6 * mv;
|
let mv_pow7 = mv_pow6 * mv;
|
||||||
let mv_pow8 = mv_pow7 * mv;
|
let mv_pow8 = mv_pow7 * mv;
|
||||||
@ -45,7 +43,7 @@ fn _convert(
|
|||||||
+ 1.057734E-6 * mv_pow8
|
+ 1.057734E-6 * mv_pow8
|
||||||
+ -1.052755E-8 * mv_pow9;
|
+ -1.052755E-8 * mv_pow9;
|
||||||
|
|
||||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(celsius as f32))
|
Ok(DegreesCelsius(celsius as f32))
|
||||||
} else if mv >= 20.644 && mv <= 54.886 {
|
} else if mv >= 20.644 && mv <= 54.886 {
|
||||||
let celsius = 1.318058e2
|
let celsius = 1.318058e2
|
||||||
+ 4.830222E+1 * mv
|
+ 4.830222E+1 * mv
|
||||||
@ -55,7 +53,7 @@ fn _convert(
|
|||||||
+ 8.802193E-6 * mv_pow5
|
+ 8.802193E-6 * mv_pow5
|
||||||
+ -3.110810E-8 * mv_pow6;
|
+ -3.110810E-8 * mv_pow6;
|
||||||
|
|
||||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(celsius as f32))
|
Ok(DegreesCelsius(celsius as f32))
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidValue)
|
Err(InvalidValue)
|
||||||
}
|
}
|
||||||
@ -70,13 +68,12 @@ fn _convert(
|
|||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert_direct(
|
pub fn convert_direct(
|
||||||
voltage: ElectricPotential<f32>,
|
voltage: MilliVolts<f64>,
|
||||||
r_junction: ThermodynamicTemperature<f32>,
|
r_junction: DegreesCelsius<f32>,
|
||||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
) -> Result<DegreesCelsius<f32>, InvalidValue> {
|
||||||
let base_celsius = _convert(voltage)?.get::<degree_celsius>();
|
let base_temp = _convert(voltage)?;
|
||||||
let r_junction_celsius = r_junction.get::<degree_celsius>();
|
|
||||||
|
|
||||||
Ok(ThermodynamicTemperature::new::<degree_celsius>(base_celsius + r_junction_celsius))
|
Ok(base_temp + r_junction)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
||||||
@ -87,11 +84,11 @@ pub fn convert_direct(
|
|||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert_seebeck(
|
pub fn convert_seebeck(
|
||||||
voltage: ElectricPotential<f32>,
|
voltage: MilliVolts<f64>,
|
||||||
r_junction: ThermodynamicTemperature<f32>,
|
r_junction: DegreesCelsius<f32>,
|
||||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
) -> Result<DegreesCelsius<f32>, InvalidValue> {
|
||||||
let voltage_correction = temp_to_voltage_seebeck(r_junction)?;
|
let voltage_correction = temp_to_voltage_seebeck(r_junction)?;
|
||||||
_convert(voltage + voltage_correction)
|
_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
|
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial and
|
||||||
@ -102,17 +99,17 @@ pub fn convert_seebeck(
|
|||||||
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert_polynomial(
|
pub fn convert_polynomial(
|
||||||
voltage: ElectricPotential<f32>,
|
voltage: MilliVolts<f64>,
|
||||||
r_junction: ThermodynamicTemperature<f32>,
|
r_junction: DegreesCelsius<f64>,
|
||||||
) -> Result<ThermodynamicTemperature<f32>, InvalidValue> {
|
) -> Result<DegreesCelsius<f32>, InvalidValue> {
|
||||||
let voltage_correction = temp_to_voltage_poly(r_junction)?;
|
let voltage_correction = temp_to_voltage_poly(r_junction)?;
|
||||||
_convert(voltage + voltage_correction)
|
_convert(MilliVolts(voltage.0 + voltage_correction.0 as f64))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn temp_to_voltage_poly(
|
pub fn temp_to_voltage_poly(
|
||||||
temperature: ThermodynamicTemperature<f32>,
|
temperature: DegreesCelsius<f64>,
|
||||||
) -> Result<ElectricPotential<f32>, InvalidValue> {
|
) -> Result<MilliVolts<f32>, InvalidValue> {
|
||||||
let celsius = temperature.get::<degree_celsius>() as f64;
|
let celsius = temperature.value();
|
||||||
let cel_pow2 = celsius * celsius;
|
let cel_pow2 = celsius * celsius;
|
||||||
let cel_pow3 = cel_pow2 * celsius;
|
let cel_pow3 = cel_pow2 * celsius;
|
||||||
let cel_pow4 = cel_pow3 * celsius;
|
let cel_pow4 = cel_pow3 * celsius;
|
||||||
@ -136,7 +133,7 @@ pub fn temp_to_voltage_poly(
|
|||||||
+ -0.198892668780E-19 * cel_pow9
|
+ -0.198892668780E-19 * cel_pow9
|
||||||
+ -0.163226974860E-22 * cel_pow10;
|
+ -0.163226974860E-22 * cel_pow10;
|
||||||
|
|
||||||
Ok(ElectricPotential::new::<millivolt>(mv as f32))
|
Ok(MilliVolts(mv as f32))
|
||||||
} else if celsius >= 0.0 && celsius <= 1372.0 {
|
} else if celsius >= 0.0 && celsius <= 1372.0 {
|
||||||
let base = celsius - 0.126968600000E+03;
|
let base = celsius - 0.126968600000E+03;
|
||||||
let exp = -0.118343200000E-03 * (base * base);
|
let exp = -0.118343200000E-03 * (base * base);
|
||||||
@ -154,7 +151,7 @@ pub fn temp_to_voltage_poly(
|
|||||||
+ -0.121047212750E-25 * cel_pow9
|
+ -0.121047212750E-25 * cel_pow9
|
||||||
+ addition;
|
+ addition;
|
||||||
|
|
||||||
Ok(ElectricPotential::new::<millivolt>(mv as f32))
|
Ok(MilliVolts(mv as f32))
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidValue)
|
Err(InvalidValue)
|
||||||
}
|
}
|
||||||
@ -162,12 +159,10 @@ pub fn temp_to_voltage_poly(
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn temp_to_voltage_seebeck(
|
pub fn temp_to_voltage_seebeck(
|
||||||
temperature: ThermodynamicTemperature<f32>,
|
temperature: DegreesCelsius<f32>,
|
||||||
) -> Result<ElectricPotential<f32>, InvalidValue> {
|
) -> Result<MilliVolts<f32>, InvalidValue> {
|
||||||
let celsius = temperature.get::<degree_celsius>();
|
if temperature.value() >= -2.0 && temperature.value() <= 800.0 {
|
||||||
if celsius >= -2.0 && celsius <= 800.0 {
|
Ok(MilliVolts(0.041 * temperature.value()))
|
||||||
let mv = 0.041 * celsius;
|
|
||||||
Ok(ElectricPotential::new::<millivolt>(mv))
|
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidValue)
|
Err(InvalidValue)
|
||||||
}
|
}
|
||||||
|
16
src/uom.rs
16
src/uom.rs
@ -1,16 +0,0 @@
|
|||||||
//TODO: Everything in here is implemented standalone and not integrated with uom library because it is spawned from macro
|
|
||||||
// soup + has shit documentation and I cannot figure out how to add a custom unit to SI. This should be integrated with
|
|
||||||
// UoM
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Default)]
|
|
||||||
pub struct Irradiance(f32);
|
|
||||||
|
|
||||||
pub fn watts_per_sq_meter(value: f32) -> Irradiance {
|
|
||||||
Irradiance(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Irradiance {
|
|
||||||
fn to_watts_per_sq_meter(self) -> f32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user