add configurable Steinhart-Hart equation
This commit is contained in:
parent
2992688184
commit
8611cc1c79
@ -69,4 +69,7 @@ The scope of this setting is per TCP session.
|
||||
| `pid <0/1> output_max <value>` | Set maximum output |
|
||||
| `pid <0/1> integral_min <value>` | Set integral lower bound |
|
||||
| `pid <0/1> integral_max <value>` | Set integral upper bound |
|
||||
| `s-h` | Show Steinhart-Hart equation parameters |
|
||||
| `s-h <0/1> <a/b/c> <value>` | Set Steinhart-Hart parameter for a channel |
|
||||
| `s-h <0/1> <parallel_resistance> <value>` | Set parallel resistance of the ADC |
|
||||
| `postfilter <0/1> rate <rate>` | Set postfilter output data rate |
|
||||
|
@ -66,6 +66,7 @@ pub enum ShowCommand {
|
||||
Reporting,
|
||||
Pwm,
|
||||
Pid,
|
||||
SteinhartHart,
|
||||
PostFilter,
|
||||
}
|
||||
|
||||
@ -81,6 +82,15 @@ pub enum PidParameter {
|
||||
IntegralMax,
|
||||
}
|
||||
|
||||
/// Steinhart-Hart equation parameter
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ShParameter {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
ParallelR,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct PwmConfig {
|
||||
pub width: u16,
|
||||
@ -115,6 +125,11 @@ pub enum Command {
|
||||
parameter: PidParameter,
|
||||
value: f32,
|
||||
},
|
||||
SteinhartHart {
|
||||
channel: usize,
|
||||
parameter: ShParameter,
|
||||
value: f32,
|
||||
},
|
||||
PostFilter {
|
||||
channel: usize,
|
||||
rate: f32,
|
||||
@ -288,7 +303,7 @@ fn pid_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
/// `pid` | pid_parameter
|
||||
/// `pid` | `pid <pid_parameter>`
|
||||
fn pid(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
let (input, _) = tag("pid")(input)?;
|
||||
alt((
|
||||
@ -300,6 +315,35 @@ fn pid(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
))(input)
|
||||
}
|
||||
|
||||
/// `s-h <0-1> <parameter> <value>`
|
||||
fn steinhart_hart_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
let (input, channel) = channel(input)?;
|
||||
let (input, _) = whitespace(input)?;
|
||||
let (input, parameter) =
|
||||
alt((value(ShParameter::A, tag("a")),
|
||||
value(ShParameter::B, tag("b")),
|
||||
value(ShParameter::C, tag("c")),
|
||||
value(ShParameter::ParallelR, tag("parallel_resistance"))
|
||||
))(input)?;
|
||||
let (input, _) = whitespace(input)?;
|
||||
let (input, value) = float(input)?;
|
||||
let result = value
|
||||
.map(|value| Command::SteinhartHart { channel, parameter, value });
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
/// `s-h` | `s-h <steinhart_hart_parameter>`
|
||||
fn steinhart_hart(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
let (input, _) = tag("s-h")(input)?;
|
||||
alt((
|
||||
preceded(
|
||||
whitespace,
|
||||
steinhart_hart_parameter
|
||||
),
|
||||
value(Ok(Command::Show(ShowCommand::SteinhartHart)), end)
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn postfilter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
let (input, _) = tag("postfilter")(input)?;
|
||||
alt((
|
||||
@ -327,6 +371,7 @@ fn command(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||
map(report, Ok),
|
||||
pwm,
|
||||
pid,
|
||||
steinhart_hart,
|
||||
postfilter,
|
||||
))(input)
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ mod ad7172;
|
||||
mod pid;
|
||||
mod tec;
|
||||
use tec::{Tec, TecPin};
|
||||
mod steinhart_hart;
|
||||
use steinhart_hart as sh;
|
||||
|
||||
pub struct UART0;
|
||||
|
||||
@ -82,6 +84,8 @@ macro_rules! create_socket {
|
||||
)
|
||||
}
|
||||
|
||||
const VCC: f32 = 3.3;
|
||||
|
||||
const DEFAULT_PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
kp: 1.0,
|
||||
ki: 1.0,
|
||||
@ -92,6 +96,13 @@ const DEFAULT_PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
integral_max: 0xffff as f32,
|
||||
};
|
||||
|
||||
const DEFAULT_SH_PARAMETERS: sh::Parameters = sh::Parameters {
|
||||
a: 0.01,
|
||||
b: 0.01,
|
||||
c: 0.01,
|
||||
parallel_r: 100.0, // TODO
|
||||
};
|
||||
|
||||
const PWM_PID_WIDTH: u16 = 0xffff;
|
||||
|
||||
// TODO: maybe rename to `TECS`?
|
||||
@ -106,6 +117,7 @@ struct ControlState {
|
||||
report: Option<(u64, u32)>,
|
||||
pid_enabled: bool,
|
||||
pid: pid::Controller,
|
||||
sh: sh::Parameters,
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
@ -183,6 +195,7 @@ fn main() -> ! {
|
||||
// Start with disengaged PID to let user setup parameters first
|
||||
pid_enabled: false,
|
||||
pid: pid::Controller::new(DEFAULT_PID_PARAMETERS.clone()),
|
||||
sh: DEFAULT_SH_PARAMETERS.clone(),
|
||||
};
|
||||
let mut states = [init_state.clone(), init_state.clone()];
|
||||
|
||||
@ -330,6 +343,18 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::Show(ShowCommand::SteinhartHart) => {
|
||||
for (channel, state) in states.iter().enumerate() {
|
||||
let _ = writeln!(
|
||||
socket, "Channel {} parameters for the Steinhart-Hart equation",
|
||||
channel,
|
||||
);
|
||||
let _ = writeln!(socket, "- a={}", state.sh.a);
|
||||
let _ = writeln!(socket, "- b={}", state.sh.b);
|
||||
let _ = writeln!(socket, "- c={}", state.sh.c);
|
||||
let _ = writeln!(socket, "- parallel_r={}", state.sh.parallel_r);
|
||||
}
|
||||
}
|
||||
Command::Show(ShowCommand::PostFilter) => {
|
||||
for (channel, _) in states.iter().enumerate() {
|
||||
match adc.get_postfilter(channel as u8).unwrap() {
|
||||
@ -411,6 +436,16 @@ fn main() -> ! {
|
||||
}
|
||||
let _ = writeln!(socket, "PID parameter updated");
|
||||
}
|
||||
Command::SteinhartHart { channel, parameter, value } => {
|
||||
let sh = &mut states[channel].sh;
|
||||
use command_parser::ShParameter::*;
|
||||
match parameter {
|
||||
A => sh.a = value,
|
||||
B => sh.b = value,
|
||||
C => sh.c = value,
|
||||
ParallelR => sh.parallel_r = value,
|
||||
}
|
||||
}
|
||||
Command::PostFilter { channel, rate } => {
|
||||
let filter = ad7172::PostFilter::closest(rate);
|
||||
match filter {
|
||||
|
28
firmware/src/steinhart_hart.rs
Normal file
28
firmware/src/steinhart_hart.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use libm::F32Ext;
|
||||
|
||||
/// Steinhart-Hart equation parameters
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Parameters {
|
||||
pub a: f32,
|
||||
pub b: f32,
|
||||
pub c: f32,
|
||||
/// Parallel resistance
|
||||
///
|
||||
/// Not truly part of the equation but required to calculate
|
||||
/// resistance from voltage.
|
||||
pub parallel_r: f32,
|
||||
}
|
||||
|
||||
impl Parameters {
|
||||
/// input: Voltage
|
||||
///
|
||||
/// Result unit: Kelvin
|
||||
pub fn get_temperature(&self, input: f32) -> f32 {
|
||||
let r = self.parallel_r * input;
|
||||
let ln_r = r.ln();
|
||||
let inv_temp = self.a +
|
||||
self.b * ln_r +
|
||||
self.c * ln_r * ln_r * ln_r;
|
||||
1.0 / inv_temp
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user