1
0
forked from M-Labs/kirdy

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
This commit is contained in:
linuswck 2024-08-07 17:22:30 +08:00
parent af73ac8127
commit 3ba8b99084
5 changed files with 56 additions and 63 deletions

View File

@ -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::<degree_celsius>(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::<degree_celsius>(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::<degree_celsius>(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::<degree_celsius>(val));
thermostat.set_sh_t0(val);
}
None => {
send_response(

View File

@ -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<u32>,
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::<degree_celsius>(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<f64> {
let input = self.get_temperature()?.get::<degree_celsius>();
let setpoint = self.set_point.get::<degree_celsius>();
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<ThermodynamicTemperature> {
pub fn get_temperature(&self) -> Option<f32> {
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
}

View File

@ -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::<kelvin>() + (r / self.r0).get::<ratio>().ln() / self.b;
ThermodynamicTemperature::new::<kelvin>(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::<ratio>().ln() / self.b;
1.0 / inv_temp - 273.15
}
}
impl Default for Parameters {
fn default() -> Self {
Parameters {
t0: ThermodynamicTemperature::new::<degree_celsius>(25.0),
t0: 25.0,
r0: ElectricalResistance::new::<ohm>(10_000.0),
b: 3800.0,
}

View File

@ -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::<degree_celsius>(45.0),
lower_limit: ThermodynamicTemperature::new::<degree_celsius>(0.0),
set_point: ThermodynamicTemperature::new::<degree_celsius>(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::<degree_celsius>(),
lower_limit: self.lower_limit.get::<degree_celsius>(),
upper_limit: self.upper_limit,
lower_limit: self.lower_limit,
}
}
}

View File

@ -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::<degree_celsius>());
debug!("Temperature: {:?} degree", temp);
data_rdy = true;
});
data_rdy
@ -200,7 +199,7 @@ impl Thermostat {
self.set_i(ElectricCurrent::new::<ampere>(pid_output as f32));
debug!(
"Temperature Set Point: {:?} degree",
self.pid_ctrl_ch0.get_pid_setpoint().get::<degree_celsius>()
self.pid_ctrl_ch0.get_pid_setpoint()
);
}
None => {}
@ -357,7 +356,7 @@ impl Thermostat {
let temperature: Option<f32>;
match self.pid_ctrl_ch0.get_temperature() {
Some(val) => temperature = Some(val.get::<degree_celsius>()),
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::<degree_celsius>(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::<degree_celsius>(),
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::<degree_celsius>(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::<degree_celsius>(settings.upper_limit));
.set_upper_limit(settings.upper_limit);
self.temp_mon
.set_lower_limit(ThermodynamicTemperature::new::<degree_celsius>(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::<degree_celsius>(),
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::<degree_celsius>(
settings.temperature_setpoint,
));
self.set_temperature_setpoint(settings.temperature_setpoint);
if !settings.pid_engaged {
self.set_i(settings.tec_settings.i_set.value);
}