From c00c1bb08176d61390ab7c225729d06f1ba44e27 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 19 Mar 2020 22:09:16 +0100 Subject: [PATCH] main: connect adc/sh/pid/dac, split out into mod channel_state --- src/ad7172/mod.rs | 2 ++ src/channel_state.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/main.rs | 42 ++++++++++++++++-------------------------- 3 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 src/channel_state.rs diff --git a/src/ad7172/mod.rs b/src/ad7172/mod.rs index 9068cda..bfbaeab 100644 --- a/src/ad7172/mod.rs +++ b/src/ad7172/mod.rs @@ -19,6 +19,8 @@ pub const SPI_MODE: spi::Mode = spi::Mode { /// 2 MHz pub const SPI_CLOCK: MegaHertz = MegaHertz(2); +pub const MAX_VALUE: u32 = 0xFF_FFFF; + #[derive(Clone, Debug, PartialEq)] pub enum AdcError { SPI(SPI), diff --git a/src/channel_state.rs b/src/channel_state.rs new file mode 100644 index 0000000..9bd1f56 --- /dev/null +++ b/src/channel_state.rs @@ -0,0 +1,40 @@ +use smoltcp::time::Instant; +use crate::{ad5680, ad7172, pid, steinhart_hart as sh}; + + +pub struct ChannelState { + pub adc_data: Option, + 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; + } +} + diff --git a/src/main.rs b/src/main.rs index 09e732e..f065896 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,30 +44,8 @@ use command_parser::{Command, ShowCommand, PwmPin}; mod timer; mod pid; mod steinhart_hart; -use steinhart_hart as sh; - - -struct ChannelState { - adc_data: Option, - 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(), - } - } -} +mod channel_state; +use channel_state::ChannelState; const HSE: MegaHertz = MegaHertz(8); @@ -151,8 +129,20 @@ fn main() -> ! { let data = adc.read_data().unwrap(); let state = &mut channel_states[usize::from(channel)]; - state.adc_data = Some(data); - state.adc_time = instant; + state.update_adc(instant, data); + + 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())); });