main: connect adc/sh/pid/dac, split out into mod channel_state

This commit is contained in:
Astro 2020-03-19 22:09:16 +01:00
parent a94650e208
commit c00c1bb081
3 changed files with 58 additions and 26 deletions

View File

@ -19,6 +19,8 @@ pub const SPI_MODE: spi::Mode = spi::Mode {
/// 2 MHz /// 2 MHz
pub const SPI_CLOCK: MegaHertz = MegaHertz(2); pub const SPI_CLOCK: MegaHertz = MegaHertz(2);
pub const MAX_VALUE: u32 = 0xFF_FFFF;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum AdcError<SPI> { pub enum AdcError<SPI> {
SPI(SPI), SPI(SPI),

40
src/channel_state.rs Normal file
View File

@ -0,0 +1,40 @@
use smoltcp::time::Instant;
use crate::{ad5680, ad7172, pid, steinhart_hart as sh};
pub struct ChannelState {
pub adc_data: Option<i32>,
pub adc_time: Instant,
pub dac_value: u32,
pub pid_enabled: bool,
pub pid: pid::Controller,
pub sh: sh::Parameters,
}
impl Default for ChannelState {
fn default() -> Self {
ChannelState {
adc_data: None,
adc_time: Instant::from_secs(0),
dac_value: 0,
pid_enabled: false,
pid: pid::Controller::new(pid::Parameters::default()),
sh: sh::Parameters::default(),
}
}
}
impl ChannelState {
/// Update PID state on ADC input, calculate new DAC output
pub fn update_adc(&mut self, now: Instant, adc_data: i32) {
self.adc_data = Some(adc_data);
self.adc_time = now;
// Update PID controller
let input = (adc_data as f64) / (ad7172::MAX_VALUE as f64);
let temperature = self.sh.get_temperature(input);
let output = self.pid.update(temperature);
self.dac_value = (output * (ad5680::MAX_VALUE as f64)) as u32;
}
}

View File

@ -44,30 +44,8 @@ use command_parser::{Command, ShowCommand, PwmPin};
mod timer; mod timer;
mod pid; mod pid;
mod steinhart_hart; mod steinhart_hart;
use steinhart_hart as sh; mod channel_state;
use channel_state::ChannelState;
struct ChannelState {
adc_data: Option<i32>,
adc_time: Instant,
dac_value: u32,
pid_enabled: bool,
pid: pid::Controller,
sh: sh::Parameters,
}
impl Default for ChannelState {
fn default() -> Self {
ChannelState {
adc_data: None,
adc_time: Instant::from_secs(0),
dac_value: 0,
pid_enabled: false,
pid: pid::Controller::new(pid::Parameters::default()),
sh: sh::Parameters::default(),
}
}
}
const HSE: MegaHertz = MegaHertz(8); const HSE: MegaHertz = MegaHertz(8);
@ -151,8 +129,20 @@ fn main() -> ! {
let data = adc.read_data().unwrap(); let data = adc.read_data().unwrap();
let state = &mut channel_states[usize::from(channel)]; let state = &mut channel_states[usize::from(channel)];
state.adc_data = Some(data); state.update_adc(instant, data);
state.adc_time = instant;
if state.pid_enabled {
// Forward PID output to i_set DAC
match channel {
0 =>
dac0.set(state.dac_value).unwrap(),
1 =>
dac1.set(state.dac_value).unwrap(),
_ =>
unreachable!(),
}
}
server.for_each(|_, session| session.set_report_pending(channel.into())); server.for_each(|_, session| session.set_report_pending(channel.into()));
}); });