From 3ba8b99084a0f5fbac07cb9a6b6b822228dcfb39 Mon Sep 17 00:00:00 2001 From: linuswck Date: Wed, 7 Aug 2024 17:22:30 +0800 Subject: [PATCH] Use degree celsius as temperature base unit - Breaking: Erase settings before flashing - except beta in Steinhart-Hart equation - to keep the temperature value set consistent with the value returned - f32 floating point calculation is inaccurate --- src/net/cmd_handler.rs | 11 +++++----- src/thermostat/pid_state.rs | 19 ++++++++-------- src/thermostat/steinhart_hart.rs | 19 ++++++++-------- src/thermostat/temp_mon.rs | 33 ++++++++++++++-------------- src/thermostat/thermostat.rs | 37 +++++++++++++++----------------- 5 files changed, 56 insertions(+), 63 deletions(-) diff --git a/src/net/cmd_handler.rs b/src/net/cmd_handler.rs index 0523aab..080e453 100644 --- a/src/net/cmd_handler.rs +++ b/src/net/cmd_handler.rs @@ -8,8 +8,7 @@ use uom::si::{electric_current::{ampere, ElectricCurrent}, electric_potential::{volt, ElectricPotential}, electrical_conductance::{siemens, ElectricalConductance}, electrical_resistance::{ohm, ElectricalResistance}, - power::{watt, Power}, - thermodynamic_temperature::{degree_celsius, ThermodynamicTemperature}}; + power::{watt, Power}}; use crate::{device::{dfu, sys_timer}, laser_diode::{laser_diode::{LdDrive, LdSettingsSummary, StatusReport as LdStatusReport}, @@ -558,7 +557,7 @@ pub fn execute_cmd( Some(ThermostatCmdEnum::SetTemperatureSetpoint) => match cmd.json.data_f32 { Some(val) => { send_response(buffer, ResponseEnum::Acknowledge, None, socket); - thermostat.set_temperature_setpoint(ThermodynamicTemperature::new::(val)); + thermostat.set_temperature_setpoint(val); } None => { send_response( @@ -722,7 +721,7 @@ pub fn execute_cmd( Some(ThermostatCmdEnum::SetTempMonUpperLimit) => match cmd.json.data_f32 { Some(val) => { send_response(buffer, ResponseEnum::Acknowledge, None, socket); - thermostat.set_temp_mon_upper_limit(ThermodynamicTemperature::new::(val)); + thermostat.set_temp_mon_upper_limit(val); } None => { send_response( @@ -736,7 +735,7 @@ pub fn execute_cmd( Some(ThermostatCmdEnum::SetTempMonLowerLimit) => match cmd.json.data_f32 { Some(val) => { send_response(buffer, ResponseEnum::Acknowledge, None, socket); - thermostat.set_temp_mon_lower_limit(ThermodynamicTemperature::new::(val)); + thermostat.set_temp_mon_lower_limit(val); } None => { send_response( @@ -754,7 +753,7 @@ pub fn execute_cmd( Some(ThermostatCmdEnum::SetShT0) => match cmd.json.data_f32 { Some(val) => { send_response(buffer, ResponseEnum::Acknowledge, None, socket); - thermostat.set_sh_t0(ThermodynamicTemperature::new::(val)); + thermostat.set_sh_t0(val); } None => { send_response( diff --git a/src/thermostat/pid_state.rs b/src/thermostat/pid_state.rs index 99c41a0..cc4f4b9 100644 --- a/src/thermostat/pid_state.rs +++ b/src/thermostat/pid_state.rs @@ -2,8 +2,7 @@ use miniconf::Tree; use serde::{Deserialize, Serialize}; use uom::si::{electric_potential::volt, electrical_resistance::ohm, - f32::{ElectricPotential, ElectricalResistance, ThermodynamicTemperature}, - thermodynamic_temperature::degree_celsius}; + f32::{ElectricPotential, ElectricalResistance}}; use crate::thermostat::{ad7172, steinhart_hart as sh}; const R_INNER: f32 = 2.0 * 5100.0; @@ -48,7 +47,7 @@ pub struct PidState { adc_data: Option, adc_calibration: ad7172::ChannelCalibration, pid_engaged: bool, - set_point: ThermodynamicTemperature, + set_point: f32, sh: sh::Parameters, controller: Controller, } @@ -59,7 +58,7 @@ impl Default for PidState { adc_data: None, adc_calibration: ad7172::ChannelCalibration::default(), pid_engaged: false, - set_point: ThermodynamicTemperature::new::(0.0), + set_point: 0.0, sh: sh::Parameters::default(), controller: Controller { parameters: Parameters::default(), @@ -98,8 +97,8 @@ impl PidState { // + x2 * kd // y0 = clip(y0', ymin, ymax) pub fn update_pid(&mut self) -> Option { - let input = self.get_temperature()?.get::(); - let setpoint = self.set_point.get::(); + let input = self.get_temperature()?; + let setpoint = self.set_point; let mut output: f64 = self.controller.y1 - setpoint as f64 * f64::from(self.controller.parameters.ki) + input as f64 * f64::from( @@ -133,7 +132,7 @@ impl PidState { Some(r) } - pub fn get_temperature(&self) -> Option { + pub fn get_temperature(&self) -> Option { let r = self.get_sens()?; let temperature = self.sh.get_temperature(r); Some(temperature) @@ -170,15 +169,15 @@ impl PidState { self.controller.y1 = 0.0; } - pub fn set_pid_setpoint(&mut self, temperature: ThermodynamicTemperature) { + pub fn set_pid_setpoint(&mut self, temperature: f32) { self.set_point = temperature; } - pub fn get_pid_setpoint(&mut self) -> ThermodynamicTemperature { + pub fn get_pid_setpoint(&mut self) -> f32 { self.set_point } - pub fn set_sh_t0(&mut self, t0: ThermodynamicTemperature) { + pub fn set_sh_t0(&mut self, t0: f32) { self.sh.t0 = t0 } diff --git a/src/thermostat/steinhart_hart.rs b/src/thermostat/steinhart_hart.rs index 60d6a9d..2cb6b50 100644 --- a/src/thermostat/steinhart_hart.rs +++ b/src/thermostat/steinhart_hart.rs @@ -2,33 +2,32 @@ use miniconf::Tree; use num_traits::float::Float; use serde::{Deserialize, Serialize}; use uom::si::{electrical_resistance::ohm, - f32::{ElectricalResistance, ThermodynamicTemperature}, - ratio::ratio, - thermodynamic_temperature::{degree_celsius, kelvin}}; + f32::ElectricalResistance, + ratio::ratio}; /// Steinhart-Hart equation parameters #[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)] pub struct Parameters { - /// Base temperature - pub t0: ThermodynamicTemperature, + /// Base temperature (Degree Celsius) + pub t0: f32, /// Base resistance pub r0: ElectricalResistance, - /// Beta + /// Beta (Kelvin) pub b: f32, } impl Parameters { /// Perform the voltage to temperature conversion. - pub fn get_temperature(&self, r: ElectricalResistance) -> ThermodynamicTemperature { - let inv_temp = 1.0 / self.t0.get::() + (r / self.r0).get::().ln() / self.b; - ThermodynamicTemperature::new::(1.0 / inv_temp) + pub fn get_temperature(&self, r: ElectricalResistance) -> f32 { + let inv_temp = 1.0 / (self.t0 + 273.15) + (r / self.r0).get::().ln() / self.b; + 1.0 / inv_temp - 273.15 } } impl Default for Parameters { fn default() -> Self { Parameters { - t0: ThermodynamicTemperature::new::(25.0), + t0: 25.0, r0: ElectricalResistance::new::(10_000.0), b: 3800.0, } diff --git a/src/thermostat/temp_mon.rs b/src/thermostat/temp_mon.rs index 7a335e8..5e1e508 100644 --- a/src/thermostat/temp_mon.rs +++ b/src/thermostat/temp_mon.rs @@ -1,7 +1,6 @@ use miniconf::Tree; use num_traits::Float; use serde::{Deserialize, Serialize}; -use uom::si::{f32::ThermodynamicTemperature, thermodynamic_temperature::degree_celsius}; #[derive(PartialEq, Deserialize, Serialize, Copy, Clone, Default, Debug)] pub enum TempStatusEnum { #[default] @@ -25,9 +24,9 @@ pub struct TempMonSettings { } pub struct TempMon { - pub upper_limit: ThermodynamicTemperature, - pub lower_limit: ThermodynamicTemperature, - pub set_point: ThermodynamicTemperature, + pub upper_limit: f32, + pub lower_limit: f32, + pub set_point: f32, pub status: TempStatus, state: State, count: u32, @@ -38,9 +37,9 @@ pub struct TempMon { impl Default for TempMon { fn default() -> Self { Self { - upper_limit: ThermodynamicTemperature::new::(45.0), - lower_limit: ThermodynamicTemperature::new::(0.0), - set_point: ThermodynamicTemperature::new::(0.0), + upper_limit: 45.0, + lower_limit: 0.0, + set_point: 0.0, status: TempStatus { status: TempStatusEnum::Off, over_temp_alarm: false, @@ -68,25 +67,25 @@ impl TempMon { const OVER_TEMP_COUNT_LIMIT: u32 = 25; const TEMP_STABLE_COUNT_LIMIT: u32 = 100; - pub fn set_upper_limit(&mut self, upper_limit: ThermodynamicTemperature) { + pub fn set_upper_limit(&mut self, upper_limit: f32) { self.upper_limit = upper_limit; self.is_limit_changed = true; } - pub fn get_upper_limit(&mut self) -> ThermodynamicTemperature { + pub fn get_upper_limit(&mut self) -> f32 { self.upper_limit } - pub fn set_lower_limit(&mut self, lower_limit: ThermodynamicTemperature) { + pub fn set_lower_limit(&mut self, lower_limit: f32) { self.lower_limit = lower_limit; self.is_limit_changed = true; } - pub fn get_lower_limit(&mut self) -> ThermodynamicTemperature { + pub fn get_lower_limit(&mut self) -> f32 { self.lower_limit } - pub fn set_setpoint(&mut self, set_point: ThermodynamicTemperature) { + pub fn set_setpoint(&mut self, set_point: f32) { if self.set_point != set_point { self.is_set_point_changed = true; self.count = 0; @@ -99,7 +98,7 @@ impl TempMon { self.state = State::default(); } - pub fn update_status(&mut self, pid_engaged: bool, pwr_on: bool, temp: ThermodynamicTemperature) { + pub fn update_status(&mut self, pid_engaged: bool, pwr_on: bool, temp: f32) { match self.state { State::PwrOff => { self.is_set_point_changed = false; @@ -135,10 +134,10 @@ impl TempMon { State::PidStartUp | State::PidStable => { let mut is_over_temp = temp > self.upper_limit || temp < self.lower_limit; if self.state != State::PidStartUp { - is_over_temp = is_over_temp || (temp.value - self.set_point.value).abs() > 0.5; + is_over_temp = is_over_temp || (temp - self.set_point).abs() > 0.5; } - let is_within_spec: bool = (temp.value - self.set_point.value).abs() < 0.001; + let is_within_spec: bool = (temp - self.set_point).abs() < 0.001; if is_over_temp { if self.count > TempMon::OVER_TEMP_COUNT_LIMIT { self.status.status = TempStatusEnum::OverTemp; @@ -191,8 +190,8 @@ impl TempMon { pub fn get_settings(&mut self) -> TempMonSettings { TempMonSettings { - upper_limit: self.upper_limit.get::(), - lower_limit: self.lower_limit.get::(), + upper_limit: self.upper_limit, + lower_limit: self.lower_limit, } } } diff --git a/src/thermostat/thermostat.rs b/src/thermostat/thermostat.rs index 03d6bc2..ea37d8f 100644 --- a/src/thermostat/thermostat.rs +++ b/src/thermostat/thermostat.rs @@ -6,9 +6,8 @@ use serde::{Deserialize, Serialize}; use uom::si::{electric_current::ampere, electric_potential::volt, electrical_resistance::ohm, - f32::{ElectricCurrent, ElectricPotential, ElectricalResistance, ThermodynamicTemperature}, - ratio::ratio, - thermodynamic_temperature::degree_celsius}; + f32::{ElectricCurrent, ElectricPotential, ElectricalResistance}, + ratio::ratio}; use crate::{sys_timer, thermostat::{ad5680, @@ -185,7 +184,7 @@ impl Thermostat { self.temp_mon .update_status(pid_engaged, self.max1968.is_powered_on(), temp); debug!("state.get_pid_engaged(): {:?}", pid_engaged); - debug!("Temperature: {:?} degree", temp.get::()); + debug!("Temperature: {:?} degree", temp); data_rdy = true; }); data_rdy @@ -200,7 +199,7 @@ impl Thermostat { self.set_i(ElectricCurrent::new::(pid_output as f32)); debug!( "Temperature Set Point: {:?} degree", - self.pid_ctrl_ch0.get_pid_setpoint().get::() + self.pid_ctrl_ch0.get_pid_setpoint() ); } None => {} @@ -357,7 +356,7 @@ impl Thermostat { let temperature: Option; match self.pid_ctrl_ch0.get_temperature() { - Some(val) => temperature = Some(val.get::()), + Some(val) => temperature = Some(val), None => { temperature = None; } @@ -374,10 +373,10 @@ impl Thermostat { } } - pub fn get_temperature(&mut self) -> ThermodynamicTemperature { + pub fn get_temperature(&mut self) -> f32 { match self.pid_ctrl_ch0.get_temperature() { Some(val) => val, - None => ThermodynamicTemperature::new::(NAN), + None => NAN, } } @@ -388,7 +387,7 @@ impl Thermostat { fn get_steinhart_hart(&mut self) -> ThermistorParams { let sh = self.pid_ctrl_ch0.get_sh(); ThermistorParams { - t0: sh.t0.get::(), + t0: sh.t0, r0: sh.r0, b: sh.b, } @@ -396,7 +395,7 @@ impl Thermostat { fn apply_steinhart_hart(&mut self, sh: ThermistorParams) { self.pid_ctrl_ch0.apply_sh(Sh_Params { - t0: ThermodynamicTemperature::new::(sh.t0), + t0: sh.t0, r0: sh.r0, b: sh.b, }) @@ -439,11 +438,11 @@ impl Thermostat { self.pid_ctrl_ch0.set_sh_r0(r0); } - pub fn set_sh_t0(&mut self, t0: ThermodynamicTemperature) { + pub fn set_sh_t0(&mut self, t0: f32) { self.pid_ctrl_ch0.set_sh_t0(t0); } - pub fn set_temperature_setpoint(&mut self, t: ThermodynamicTemperature) { + pub fn set_temperature_setpoint(&mut self, t: f32) { let t = t .min(self.temp_mon.get_upper_limit()) .max(self.temp_mon.get_lower_limit()); @@ -453,16 +452,16 @@ impl Thermostat { pub fn apply_temp_mon_settings(&mut self, settings: TempMonSettings) { self.temp_mon - .set_upper_limit(ThermodynamicTemperature::new::(settings.upper_limit)); + .set_upper_limit(settings.upper_limit); self.temp_mon - .set_lower_limit(ThermodynamicTemperature::new::(settings.lower_limit)); + .set_lower_limit(settings.lower_limit); } - pub fn set_temp_mon_upper_limit(&mut self, t: ThermodynamicTemperature) { + pub fn set_temp_mon_upper_limit(&mut self, t: f32) { self.temp_mon.set_upper_limit(t); } - pub fn set_temp_mon_lower_limit(&mut self, t: ThermodynamicTemperature) { + pub fn set_temp_mon_lower_limit(&mut self, t: f32) { self.temp_mon.set_lower_limit(t); } @@ -508,7 +507,7 @@ impl Thermostat { ThermostatSettingsSummary { default_pwr_on: self.tec_settings.default_pwr_on, pid_engaged: self.get_pid_engaged(), - temperature_setpoint: self.pid_ctrl_ch0.get_pid_setpoint().get::(), + temperature_setpoint: self.pid_ctrl_ch0.get_pid_setpoint(), tec_settings: self.get_tec_settings(), pid_params: self.get_pid_settings(), temp_adc_settings: TempAdcFilter { @@ -549,9 +548,7 @@ impl Thermostat { self.set_pid_engaged(settings.pid_engaged); self.pid_ctrl_ch0.apply_pid_params(settings.pid_params); - self.set_temperature_setpoint(ThermodynamicTemperature::new::( - settings.temperature_setpoint, - )); + self.set_temperature_setpoint(settings.temperature_setpoint); if !settings.pid_engaged { self.set_i(settings.tec_settings.i_set.value); }