Thermocouple type k conversion updates.

This commit is contained in:
Zachary Sunforge
2023-07-14 22:45:59 -07:00
parent abde12a8ba
commit 45bc1707e9
2 changed files with 54 additions and 22 deletions

View File

@ -91,12 +91,7 @@ async fn main(spawner: Spawner) {
// Zero test // Zero test
let zero_voltage = f32::ElectricPotential::new::<millivolt>(0.0); let zero_voltage = f32::ElectricPotential::new::<millivolt>(0.0);
let zero_temperature = thermocouple_k::convert( let zero_temperature = thermocouple_k::convert_direct(zero_voltage, reference_temp).unwrap();
zero_voltage,
reference_temp,
thermocouple_k::r_junction_offset_lin,
)
.unwrap();
let zero_celsius = zero_temperature.get::<degree_celsius>(); let zero_celsius = zero_temperature.get::<degree_celsius>();
info!("Zero test: {}", zero_celsius); info!("Zero test: {}", zero_celsius);
@ -108,9 +103,7 @@ async fn main(spawner: Spawner) {
.unwrap() .unwrap()
.to_voltage(AUTOCAL_CONF.ad_control.gain()); .to_voltage(AUTOCAL_CONF.ad_control.gain());
let mv = voltage.get::<millivolt>(); let mv = voltage.get::<millivolt>();
let temperature = let temperature = thermocouple_k::convert_direct(voltage, reference_temp).unwrap();
thermocouple_k::convert(voltage, reference_temp, thermocouple_k::r_junction_offset_lin)
.unwrap();
let celsius = temperature.get::<degree_celsius>(); let celsius = temperature.get::<degree_celsius>();
info!("Temperature in degrees celsius: {}, millivolts: {}", celsius, mv); info!("Temperature in degrees celsius: {}, millivolts: {}", celsius, mv);
} }

View File

@ -4,19 +4,10 @@ use uom::si::electric_potential::{millivolt, volt};
use uom::si::f32; use uom::si::f32;
use uom::si::thermodynamic_temperature::degree_celsius; use uom::si::thermodynamic_temperature::degree_celsius;
/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial with fn _convert(
/// NIST coefficients, this method has a maximum error of 0.06°C in addition to the underlying
/// thermocouple inaccuracy.
///
/// This function uses the [NIST type K thermocouple linearisation polynomial](https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html).
pub fn convert(
voltage: f32::ElectricPotential, voltage: f32::ElectricPotential,
r_junction: f32::ThermodynamicTemperature,
r_junction_offset: fn(
r_junction: f32::ThermodynamicTemperature,
) -> Result<f32::ElectricPotential, InvalidValue>,
) -> Result<f32::ThermodynamicTemperature, InvalidValue> { ) -> Result<f32::ThermodynamicTemperature, InvalidValue> {
let mv = voltage.get::<millivolt>() + r_junction_offset(r_junction)?.get::<millivolt>(); let mv = voltage.get::<millivolt>();
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;
@ -68,8 +59,56 @@ pub fn convert(
} }
} }
/// 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: f32::ElectricPotential,
r_junction: f32::ThermodynamicTemperature,
) -> Result<f32::ThermodynamicTemperature, InvalidValue> {
let base_celsius = _convert(voltage)?.get::<degree_celsius>();
let r_junction_celsius = r_junction.get::<degree_celsius>();
Ok(f32::ThermodynamicTemperature::new::<degree_celsius>(base_celsius + r_junction_celsius))
}
/// 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: f32::ElectricPotential,
r_junction: f32::ThermodynamicTemperature,
) -> Result<f32::ThermodynamicTemperature, InvalidValue> {
let voltage_correction = temp_to_voltage_seebeck(r_junction)?;
_convert(voltage + voltage_correction)
}
/// 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: f32::ElectricPotential,
r_junction: f32::ThermodynamicTemperature,
) -> Result<f32::ThermodynamicTemperature, InvalidValue> {
let voltage_correction = temp_to_voltage_poly(r_junction)?;
_convert(voltage + voltage_correction)
}
//TODO: This is not working, check libm pow. //TODO: This is not working, check libm pow.
pub fn r_junction_offset_poly( pub fn temp_to_voltage_poly(
temperature: f32::ThermodynamicTemperature, temperature: f32::ThermodynamicTemperature,
) -> Result<f32::ElectricPotential, InvalidValue> { ) -> Result<f32::ElectricPotential, InvalidValue> {
let celsius = temperature.get::<degree_celsius>(); let celsius = temperature.get::<degree_celsius>();
@ -121,7 +160,7 @@ pub fn r_junction_offset_poly(
} }
#[inline] #[inline]
pub fn r_junction_offset_lin( pub fn temp_to_voltage_seebeck(
temperature: f32::ThermodynamicTemperature, temperature: f32::ThermodynamicTemperature,
) -> Result<f32::ElectricPotential, InvalidValue> { ) -> Result<f32::ElectricPotential, InvalidValue> {
let celsius = temperature.get::<degree_celsius>(); let celsius = temperature.get::<degree_celsius>();