diff --git a/examples/ads1256/src/bin/thermocouple.rs b/examples/ads1256/src/bin/thermocouple.rs index 4e0e8a3..250bcc0 100644 --- a/examples/ads1256/src/bin/thermocouple.rs +++ b/examples/ads1256/src/bin/thermocouple.rs @@ -91,12 +91,7 @@ async fn main(spawner: Spawner) { // Zero test let zero_voltage = f32::ElectricPotential::new::(0.0); - let zero_temperature = thermocouple_k::convert( - zero_voltage, - reference_temp, - thermocouple_k::r_junction_offset_lin, - ) - .unwrap(); + let zero_temperature = thermocouple_k::convert_direct(zero_voltage, reference_temp).unwrap(); let zero_celsius = zero_temperature.get::(); info!("Zero test: {}", zero_celsius); @@ -108,9 +103,7 @@ async fn main(spawner: Spawner) { .unwrap() .to_voltage(AUTOCAL_CONF.ad_control.gain()); let mv = voltage.get::(); - let temperature = - thermocouple_k::convert(voltage, reference_temp, thermocouple_k::r_junction_offset_lin) - .unwrap(); + let temperature = thermocouple_k::convert_direct(voltage, reference_temp).unwrap(); let celsius = temperature.get::(); info!("Temperature in degrees celsius: {}, millivolts: {}", celsius, mv); } diff --git a/src/transducer/thermocouple/type_k.rs b/src/transducer/thermocouple/type_k.rs index d95edac..44ff7da 100644 --- a/src/transducer/thermocouple/type_k.rs +++ b/src/transducer/thermocouple/type_k.rs @@ -4,19 +4,10 @@ use uom::si::electric_potential::{millivolt, volt}; use uom::si::f32; use uom::si::thermodynamic_temperature::degree_celsius; -/// Convert from a voltage produced by a type k thermocouple to a temperature using polynomial with -/// 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( +fn _convert( voltage: f32::ElectricPotential, - r_junction: f32::ThermodynamicTemperature, - r_junction_offset: fn( - r_junction: f32::ThermodynamicTemperature, - ) -> Result, ) -> Result { - let mv = voltage.get::() + r_junction_offset(r_junction)?.get::(); + let mv = voltage.get::(); let mv_pow2 = mv * mv; let mv_pow3 = mv_pow2 * 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 { + let base_celsius = _convert(voltage)?.get::(); + let r_junction_celsius = r_junction.get::(); + + Ok(f32::ThermodynamicTemperature::new::(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 { + 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 { + let voltage_correction = temp_to_voltage_poly(r_junction)?; + _convert(voltage + voltage_correction) +} + //TODO: This is not working, check libm pow. -pub fn r_junction_offset_poly( +pub fn temp_to_voltage_poly( temperature: f32::ThermodynamicTemperature, ) -> Result { let celsius = temperature.get::(); @@ -121,7 +160,7 @@ pub fn r_junction_offset_poly( } #[inline] -pub fn r_junction_offset_lin( +pub fn temp_to_voltage_seebeck( temperature: f32::ThermodynamicTemperature, ) -> Result { let celsius = temperature.get::();