From ba860e52ac04aa38936e4aaf98931d3c005493fc Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 17 May 2020 01:23:35 +0200 Subject: [PATCH] control i_set dac in volts --- src/ad5680.rs | 6 ++++-- src/channel.rs | 11 +++++++---- src/channel_state.rs | 16 ++++++++++------ src/channels.rs | 12 ++++++------ src/command_parser.rs | 14 +++++++------- src/main.rs | 29 +++++++++-------------------- src/pid.rs | 2 +- src/units.rs | 6 +++--- 8 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/ad5680.rs b/src/ad5680.rs index f550777..f8b4b77 100644 --- a/src/ad5680.rs +++ b/src/ad5680.rs @@ -6,6 +6,7 @@ use stm32f4xx_hal::{ time::MegaHertz, spi, }; +use crate::units::Volts; /// SPI Mode 1 pub const SPI_MODE: spi::Mode = spi::Mode { @@ -44,8 +45,9 @@ impl, S: OutputPin> Dac { Ok(()) } - /// value: `0..0x20_000` - pub fn set(&mut self, value: u32) -> Result<(), SPI::Error> { + pub fn set(&mut self, voltage: Volts) -> Result<(), SPI::Error> { + let value = ((voltage.0 * (MAX_VALUE as f64) / 5.0) as u32) + .min(MAX_VALUE); let buf = [ (value >> 14) as u8, (value >> 6) as u8, diff --git a/src/channel.rs b/src/channel.rs index 3b2fb31..c35d31f 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -1,6 +1,9 @@ -use crate::pins::{ChannelPins, ChannelPinSet}; -use crate::channel_state::ChannelState; -use crate::ad5680; +use crate::{ + ad5680, + channel_state::ChannelState, + pins::{ChannelPins, ChannelPinSet}, + units::Volts, +}; /// Marker type for the first channel pub struct Channel0; @@ -25,7 +28,7 @@ impl Channel { pub fn new(pins: ChannelPinSet) -> Self { let state = ChannelState::default(); let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync); - let _ = dac.set(0); + let _ = dac.set(Volts(0.0)); Channel { state, diff --git a/src/channel_state.rs b/src/channel_state.rs index cd4e5d4..78573e4 100644 --- a/src/channel_state.rs +++ b/src/channel_state.rs @@ -1,11 +1,16 @@ use smoltcp::time::Instant; -use crate::{ad5680, ad7172, pid, steinhart_hart as sh}; +use crate::{ + ad7172, + pid, + steinhart_hart as sh, + units::Volts, +}; pub struct ChannelState { pub adc_data: Option, pub adc_time: Instant, - pub dac_value: u32, + pub dac_value: Volts, pub pid_engaged: bool, pub pid: pid::Controller, pub sh: sh::Parameters, @@ -16,7 +21,7 @@ impl Default for ChannelState { ChannelState { adc_data: None, adc_time: Instant::from_secs(0), - dac_value: 0, + dac_value: Volts(0.0), pid_engaged: false, pid: pid::Controller::new(pid::Parameters::default()), sh: sh::Parameters::default(), @@ -26,14 +31,13 @@ impl Default for ChannelState { impl ChannelState { /// Update PID state on ADC input, calculate new DAC output - pub fn update_pid(&mut self, now: Instant, adc_data: u32) -> u32 { + pub fn update_pid(&mut self, now: Instant, adc_data: u32) -> f64 { 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); - (output * (ad5680::MAX_VALUE as f64)) as u32 + self.pid.update(temperature) } } diff --git a/src/channels.rs b/src/channels.rs index a21f63e..d2f1f3c 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -59,7 +59,7 @@ impl Channels { }; if let Some(dac_value) = dac_value { // Forward PID output to i_set DAC - self.set_dac(channel.into(), dac_value); + self.set_dac(channel.into(), Volts(dac_value)); } channel @@ -67,16 +67,16 @@ impl Channels { } /// i_set DAC - pub fn set_dac(&mut self, channel: usize, duty: u32) { + pub fn set_dac(&mut self, channel: usize, voltage: Volts) { match channel { 0 => { - self.channel0.dac.set(duty).unwrap(); - self.channel0.state.dac_value = duty; + self.channel0.dac.set(voltage).unwrap(); + self.channel0.state.dac_value = voltage; self.channel0.shdn.set_high().unwrap(); } 1 => { - self.channel1.dac.set(duty).unwrap(); - self.channel1.state.dac_value = duty; + self.channel1.dac.set(voltage).unwrap(); + self.channel1.state.dac_value = voltage; self.channel1.shdn.set_high().unwrap(); } _ => unreachable!(), diff --git a/src/command_parser.rs b/src/command_parser.rs index b82e54f..ee043b2 100644 --- a/src/command_parser.rs +++ b/src/command_parser.rs @@ -142,7 +142,7 @@ pub enum Command { Pwm { channel: usize, pin: PwmPin, - duty: u32, + duty: f64, }, /// Enable PID control for `i_set` PwmPid { @@ -239,9 +239,9 @@ fn report(input: &[u8]) -> IResult<&[u8], Command> { )(input) } -fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, u32), Error>> { +fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, f64), Error>> { let result_with_pin = |pin: PwmPin| - move |result: Result| + move |result: Result| result.map(|duty| (pin, duty)); alt(( @@ -250,7 +250,7 @@ fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, u32), Error>> { tag("max_i_pos"), preceded( whitespace, - unsigned + float ) ), result_with_pin(PwmPin::MaxIPos) @@ -260,7 +260,7 @@ fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, u32), Error>> { tag("max_i_neg"), preceded( whitespace, - unsigned + float ) ), result_with_pin(PwmPin::MaxINeg) @@ -270,12 +270,12 @@ fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, u32), Error>> { tag("max_v"), preceded( whitespace, - unsigned + float ) ), result_with_pin(PwmPin::MaxV) ), - map(unsigned, result_with_pin(PwmPin::ISet) + map(float, result_with_pin(PwmPin::ISet) )) )(input) } diff --git a/src/main.rs b/src/main.rs index 7e40834..b6f44f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,7 +43,7 @@ mod command_parser; use command_parser::{Command, ShowCommand, PwmPin}; mod timer; mod units; -use units::{Amps, Ohms}; +use units::{Amps, Ohms, Volts}; mod pid; mod steinhart_hart; mod channels; @@ -144,7 +144,7 @@ fn main() -> ! { for channel in 0..CHANNELS { if let Some(adc_data) = channels.channel_state(channel).adc_data { let dac_loopback = channels.read_dac_loopback(channel); - let dac_i = dac_loopback.clone() / Ohms(5.0); + let dac_i = dac_loopback / Ohms(5.0); let itec = channels.read_itec(channel); let tec_i = Amps((itec.0 - 1.5) / 8.0); @@ -194,7 +194,7 @@ fn main() -> ! { channel, if state.pid_engaged { "engaged" } else { "disengaged" } ); - let _ = writeln!(socket, "- i_set={}/{}", state.dac_value, ad5680::MAX_VALUE); + let _ = writeln!(socket, "- i_set={}", state.dac_value); fn show_pwm_channel(mut socket: S, name: &str, pin: &P) where S: core::fmt::Write, @@ -258,21 +258,16 @@ fn main() -> ! { let _ = writeln!(socket, "channel {}: PID enabled to control PWM", channel ); } - Command::Pwm { channel, pin: PwmPin::ISet, duty } if duty <= ad5680::MAX_VALUE => { + Command::Pwm { channel, pin: PwmPin::ISet, duty } => { channels.channel_state(channel).pid_engaged = false; - channels.set_dac(channel, duty); + let voltage = Volts(duty); + channels.set_dac(channel, voltage); let _ = writeln!( - socket, "channel {}: PWM duty cycle manually set to {}/{}", - channel, duty, ad5680::MAX_VALUE + socket, "channel {}: PWM duty cycle manually set to {}", + channel, voltage ); } - Command::Pwm { pin: PwmPin::ISet, duty, .. } if duty > ad5680::MAX_VALUE => { - let _ = writeln!( - socket, "error: PWM duty range must not exceed {}", - ad5680::MAX_VALUE - ); - } - Command::Pwm { channel, pin, duty } if duty <= 0xFFFF => { + Command::Pwm { channel, pin, duty } => { let duty = duty as u16; fn set_pwm_channel>(pin: &mut P, duty: u16) -> u16 { @@ -303,9 +298,6 @@ fn main() -> ! { channel, pin.name(), duty, max ); } - Command::Pwm { duty, .. } if duty > 0xFFFF => { - let _ = writeln!(socket, "error: PWM duty range must fit 16 bits"); - } Command::Pid { channel, parameter, value } => { let pid = &mut channels.channel_state(channel).pid; use command_parser::PidParameter::*; @@ -357,9 +349,6 @@ fn main() -> ! { } } } - cmd => { - let _ = writeln!(socket, "Not yet implemented: {:?}", cmd); - } } Ok(SessionOutput::Error(e)) => { let _ = writeln!(socket, "Command error: {:?}", e); diff --git a/src/pid.rs b/src/pid.rs index ebe92d7..dbf70fa 100644 --- a/src/pid.rs +++ b/src/pid.rs @@ -16,7 +16,7 @@ impl Default for Parameters { ki: 0.05, kd: 0.45, output_min: 0.0, - output_max: 1.0, + output_max: 5.0, integral_min: 0.0, integral_max: 1.0, } diff --git a/src/units.rs b/src/units.rs index b4c0d5d..86e55b8 100644 --- a/src/units.rs +++ b/src/units.rs @@ -3,7 +3,7 @@ use core::{ ops::Div, }; -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub struct Volts(pub f64); impl fmt::Display for Volts { @@ -19,7 +19,7 @@ impl Div for Volts { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub struct Amps(pub f64); impl fmt::Display for Amps { @@ -27,7 +27,7 @@ impl fmt::Display for Amps { write!(f, "{:.3}A", self.0) } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub struct Ohms(pub f64); impl fmt::Display for Ohms {