thermostat/src/config.rs

159 lines
4.2 KiB
Rust
Raw Normal View History

2020-09-24 07:18:33 +08:00
use serde::{Serialize, Deserialize};
2020-09-24 15:49:13 +08:00
use postcard::{from_bytes, to_slice};
2020-09-25 03:10:27 +08:00
use uom::si::{
electric_potential::volt,
electric_current::ampere,
electrical_resistance::ohm,
thermodynamic_temperature::degree_celsius,
2020-09-25 03:10:27 +08:00
};
2020-09-24 07:18:33 +08:00
use crate::{
channels::{CHANNELS, Channels},
command_parser::CenterPoint,
pid,
steinhart_hart,
};
/// Just for encoding/decoding, actual state resides in ChannelState
2020-09-25 03:35:15 +08:00
#[derive(Debug, PartialEq, Serialize, Deserialize)]
2020-09-24 07:18:33 +08:00
pub struct Config {
channels: [ChannelConfig; CHANNELS],
}
impl Config {
pub fn new(channels: &mut Channels) -> Self {
Config {
channels: [
2020-09-25 03:10:27 +08:00
ChannelConfig::new(channels, 0),
ChannelConfig::new(channels, 1),
2020-09-24 07:18:33 +08:00
],
}
}
2020-09-24 08:06:53 +08:00
pub fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], postcard::Error> {
to_slice(self, buffer)
}
pub fn decode(buffer: &[u8]) -> Result<Self, postcard::Error> {
from_bytes(buffer)
2020-09-24 07:18:33 +08:00
}
}
2020-09-25 03:35:15 +08:00
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2020-09-24 07:18:33 +08:00
pub struct ChannelConfig {
center: CenterPoint,
pid: pid::Parameters,
pid_target: f32,
sh: SteinhartHartConfig,
2020-09-25 03:10:27 +08:00
pwm: PwmLimits,
2020-09-24 07:18:33 +08:00
}
impl ChannelConfig {
2020-09-25 03:10:27 +08:00
pub fn new(channels: &mut Channels, channel: usize) -> Self {
let pwm = PwmLimits::new(channels, channel);
let state = channels.channel_state(channel);
2020-09-24 07:18:33 +08:00
ChannelConfig {
center: state.center.clone(),
pid: state.pid.parameters.clone(),
pid_target: state.pid.target as f32,
sh: (&state.sh).into(),
2020-09-25 03:10:27 +08:00
pwm,
2020-09-24 07:18:33 +08:00
}
}
}
2020-09-25 02:59:04 +08:00
2020-09-25 03:35:15 +08:00
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct SteinhartHartConfig {
t0: f32,
r0: f32,
b: f32,
}
impl From<&steinhart_hart::Parameters> for SteinhartHartConfig {
fn from(sh: &steinhart_hart::Parameters) -> Self {
SteinhartHartConfig {
t0: sh.t0.get::<degree_celsius>() as f32,
r0: sh.r0.get::<ohm>() as f32,
b: sh.b as f32,
}
}
}
2020-09-25 03:35:15 +08:00
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2020-09-25 03:10:27 +08:00
struct PwmLimits {
max_v: f32,
max_i_pos: f32,
max_i_neg: f32,
}
impl PwmLimits {
pub fn new(channels: &mut Channels, channel: usize) -> Self {
let (max_v, _) = channels.get_max_v(channel);
let (max_i_pos, _) = channels.get_max_i_pos(channel);
let (max_i_neg, _) = channels.get_max_i_neg(channel);
PwmLimits {
max_v: max_v.get::<volt>() as f32,
max_i_pos: max_i_pos.get::<ampere>() as f32,
max_i_neg: max_i_neg.get::<ampere>() as f32,
}
}
}
2020-09-25 02:59:04 +08:00
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_fit_eeprom() {
let channel_config = ChannelConfig {
center: CenterPoint::Override(1.5),
pid: pid::Parameters::default(),
pid_target: 93.7,
sh: (&steinhart_hart::Parameters::default()).into(),
2020-09-25 03:10:27 +08:00
pwm: PwmLimits {
max_v: 1.65,
max_i_pos: 2.1,
max_i_neg: 2.25,
},
2020-09-25 02:59:04 +08:00
};
let config = Config {
channels: [
channel_config.clone(),
channel_config.clone(),
],
};
const EEPROM_SIZE: usize = 0x80;
let mut buffer = [0; EEPROM_SIZE];
let buffer = config.encode(&mut buffer).unwrap();
assert!(buffer.len() <= EEPROM_SIZE);
}
2020-09-25 03:35:15 +08:00
#[test]
fn test_encode_decode() {
let channel_config = ChannelConfig {
center: CenterPoint::Override(1.5),
pid: pid::Parameters::default(),
pid_target: 93.7,
sh: (&steinhart_hart::Parameters::default()).into(),
pwm: PwmLimits {
max_v: 1.65,
max_i_pos: 2.1,
max_i_neg: 2.25,
},
};
let config = Config {
channels: [
channel_config.clone(),
channel_config.clone(),
],
};
const EEPROM_SIZE: usize = 0x80;
let mut buffer = [0; EEPROM_SIZE];
config.encode(&mut buffer).unwrap();
let decoded = Config::decode(&buffer).unwrap();
assert_eq!(decoded, config);
}
2020-09-25 02:59:04 +08:00
}