implement all the tcp commands

This commit is contained in:
Astro 2020-03-19 18:34:57 +01:00
parent cee0a1fcab
commit da4aaf4ff6
5 changed files with 310 additions and 252 deletions

View File

@ -14,6 +14,8 @@ pub const SPI_MODE: spi::Mode = spi::Mode {
/// 30 MHz /// 30 MHz
pub const SPI_CLOCK: MegaHertz = MegaHertz(30); pub const SPI_CLOCK: MegaHertz = MegaHertz(30);
pub const MAX_VALUE: u32 = 0x20000;
/// [AD5680](https://www.analog.com/media/en/technical-documentation/data-sheets/AD5680.pdf) DAC /// [AD5680](https://www.analog.com/media/en/technical-documentation/data-sheets/AD5680.pdf) DAC
pub struct Dac<SPI: Transfer<u8>, S: OutputPin> { pub struct Dac<SPI: Transfer<u8>, S: OutputPin> {
spi: SPI, spi: SPI,

View File

@ -85,30 +85,28 @@ pub enum PidParameter {
/// Steinhart-Hart equation parameter /// Steinhart-Hart equation parameter
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum ShParameter { pub enum ShParameter {
A, T0,
B, R,
C, R0,
ParallelR,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct PwmConfig { pub enum PwmPin {
pub width: u16, ISet,
pub total: u16, MaxIPos,
MaxINeg,
MaxV,
} }
#[derive(Debug, Clone, PartialEq)] impl PwmPin {
pub enum PwmMode { pub fn name(&self) -> &'static str {
Manual(PwmConfig), match self {
Pid, PwmPin::ISet => "i_set",
PwmPin::MaxIPos => "max_i_pos",
PwmPin::MaxINeg => "max_i_neg",
PwmPin::MaxV => "max_v",
}
} }
#[derive(Debug, Clone, PartialEq)]
pub enum PwmSetup {
ISet(PwmMode),
MaxIPos(PwmConfig),
MaxINeg(PwmConfig),
MaxV(PwmConfig),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -116,10 +114,17 @@ pub enum Command {
Quit, Quit,
Show(ShowCommand), Show(ShowCommand),
Reporting(bool), Reporting(bool),
/// PWM parameter setting
Pwm { Pwm {
channel: usize, channel: usize,
setup: PwmSetup, pin: PwmPin,
duty: u32,
}, },
/// Enable PID control for `i_set`
PwmPid {
channel: usize,
},
/// PID parameter setting
Pid { Pid {
channel: usize, channel: usize,
parameter: PidParameter, parameter: PidParameter,
@ -149,7 +154,7 @@ fn whitespace(input: &[u8]) -> IResult<&[u8], ()> {
fold_many1(char(' '), (), |(), _| ())(input) fold_many1(char(' '), (), |(), _| ())(input)
} }
fn unsigned(input: &[u8]) -> IResult<&[u8], Result<u16, Error>> { fn unsigned(input: &[u8]) -> IResult<&[u8], Result<u32, Error>> {
take_while1(is_digit)(input) take_while1(is_digit)(input)
.map(|(input, digits)| { .map(|(input, digits)| {
let result = lexical::parse(digits) let result = lexical::parse(digits)
@ -202,82 +207,77 @@ fn report(input: &[u8]) -> IResult<&[u8], Command> {
)(input) )(input)
} }
/// `pwm ... <width> <total>` - Set pwm duty cycle fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, u32), Error>> {
fn pwm_config(input: &[u8]) -> IResult<&[u8], Result<PwmConfig, Error>> { let result_with_pin = |pin: PwmPin|
let (input, width) = unsigned(input)?; move |result: Result<u32, Error>|
let width = match width { result.map(|duty| (pin, duty));
Ok(width) => width,
Err(e) => return Ok((input, Err(e.into()))),
};
let (input, _) = whitespace(input)?;
let (input, total) = unsigned(input)?;
let total = match total {
Ok(total) => total,
Err(e) => return Ok((input, Err(e.into()))),
};
Ok((input, Ok(PwmConfig { width, total })))
}
fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<PwmSetup, Error>> {
alt(( alt((
map( map(
preceded( preceded(
tag("max_i_pos"), tag("max_i_pos"),
preceded( preceded(
whitespace, whitespace,
pwm_config unsigned
) )
), ),
|result| result.map(PwmSetup::MaxIPos) result_with_pin(PwmPin::MaxIPos)
), ),
map( map(
preceded( preceded(
tag("max_i_neg"), tag("max_i_neg"),
preceded( preceded(
whitespace, whitespace,
pwm_config unsigned
) )
), ),
|result| result.map(PwmSetup::MaxINeg) result_with_pin(PwmPin::MaxINeg)
), ),
map( map(
preceded( preceded(
tag("max_v"), tag("max_v"),
preceded( preceded(
whitespace, whitespace,
pwm_config unsigned
) )
), ),
|result| result.map(PwmSetup::MaxV) result_with_pin(PwmPin::MaxV)
), ),
map(pwm_config, |result| result.map(|config| { map(unsigned, result_with_pin(PwmPin::ISet)
PwmSetup::ISet(PwmMode::Manual(config)) ))
})) )(input)
))(input)
} }
/// `pwm <0-1> pid` - Set PWM to be controlled by PID /// `pwm <0-1> pid` - Set PWM to be controlled by PID
fn pwm_pid(input: &[u8]) -> IResult<&[u8], Result<PwmSetup, Error>> { fn pwm_pid(input: &[u8]) -> IResult<&[u8], ()> {
value(Ok(PwmSetup::ISet(PwmMode::Pid)), tag("pid"))(input) value((), tag("pid"))(input)
} }
fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> { fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
let (input, _) = tag("pwm")(input)?; let (input, _) = tag("pwm")(input)?;
alt(( alt((
preceded( |input| {
whitespace, let (input, _) = whitespace(input)?;
map( let (input, channel) = channel(input)?;
separated_pair( let (input, _) = whitespace(input)?;
channel, let (input, result) = alt((
whitespace, |input| {
alt(( let (input, ()) = pwm_pid(input)?;
pwm_pid, Ok((input, Ok(Command::PwmPid { channel })))
pwm_setup },
)) |input| {
), let (input, config) = pwm_setup(input)?;
|(channel, setup)| setup.map(|setup| Command::Pwm { channel, setup }) match config {
) Ok((pin, duty)) =>
), Ok((input, Ok(Command::Pwm { channel, pin, duty }))),
Err(e) =>
Ok((input, Err(e))),
}
},
))(input)?;
end(input)?;
Ok((input, result))
},
value(Ok(Command::Show(ShowCommand::Pwm)), end) value(Ok(Command::Show(ShowCommand::Pwm)), end)
))(input) ))(input)
} }
@ -320,10 +320,9 @@ fn steinhart_hart_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Erro
let (input, channel) = channel(input)?; let (input, channel) = channel(input)?;
let (input, _) = whitespace(input)?; let (input, _) = whitespace(input)?;
let (input, parameter) = let (input, parameter) =
alt((value(ShParameter::A, tag("a")), alt((value(ShParameter::T0, tag("t0")),
value(ShParameter::B, tag("b")), value(ShParameter::R, tag("r")),
value(ShParameter::C, tag("c")), value(ShParameter::R0, tag("r0"))
value(ShParameter::ParallelR, tag("parallel_r"))
))(input)?; ))(input)?;
let (input, _) = whitespace(input)?; let (input, _) = whitespace(input)?;
let (input, value) = float(input)?; let (input, value) = float(input)?;
@ -426,58 +425,50 @@ mod test {
#[test] #[test]
fn parse_pwm_manual() { fn parse_pwm_manual() {
let command = Command::parse(b"pwm 1 16383 65535"); let command = Command::parse(b"pwm 1 16383");
assert_eq!(command, Ok(Command::Pwm { assert_eq!(command, Ok(Command::Pwm {
channel: 1, channel: 1,
setup: PwmSetup::ISet(PwmMode::Manual(PwmConfig { pin: PwmPin::ISet,
width: 16383, duty: 16383,
total: 65535,
})),
})); }));
} }
#[test] #[test]
fn parse_pwm_pid() { fn parse_pwm_pid() {
let command = Command::parse(b"pwm 0 pid"); let command = Command::parse(b"pwm 0 pid");
assert_eq!(command, Ok(Command::Pwm { assert_eq!(command, Ok(Command::PwmPid {
channel: 0, channel: 0,
setup: PwmSetup::ISet(PwmMode::Pid), pin: PwmPin::ISet,
})); }));
} }
#[test] #[test]
fn parse_pwm_max_i_pos() { fn parse_pwm_max_i_pos() {
let command = Command::parse(b"pwm 0 max_i_pos 7 13"); let command = Command::parse(b"pwm 0 max_i_pos 7");
assert_eq!(command, Ok(Command::Pwm { assert_eq!(command, Ok(Command::Pwm {
channel: 0, channel: 0,
setup: PwmSetup::MaxIPos(PwmConfig { pin: PwmPin::MaxIPos,
width: 7, duty: 7,
total: 13,
}),
})); }));
} }
#[test] #[test]
fn parse_pwm_max_i_neg() { fn parse_pwm_max_i_neg() {
let command = Command::parse(b"pwm 0 max_i_neg 128 65535"); let command = Command::parse(b"pwm 0 max_i_neg 128");
assert_eq!(command, Ok(Command::Pwm { assert_eq!(command, Ok(Command::Pwm {
channel: 0, channel: 0,
setup: PwmSetup::MaxINeg(PwmConfig { pin: PwmPin::MaxINeg,
width: 128, duty: 128,
total: 65535,
}),
})); }));
} }
#[test] #[test]
fn parse_pwm_max_v() { fn parse_pwm_max_v() {
let command = Command::parse(b"pwm 0 max_v 32768 65535"); let command = Command::parse(b"pwm 0 max_v 32768");
assert_eq!(command, Ok(Command::Pwm { assert_eq!(command, Ok(Command::Pwm {
channel: 0, channel: 0,
setup: PwmSetup::MaxV(PwmConfig { pin: PwmPin::MaxV,
width: 32768, duty: 32768,
total: 65535,
}),
})); }));
} }
@ -515,10 +506,10 @@ mod test {
#[test] #[test]
fn parse_steinhart_hart_parallel_r() { fn parse_steinhart_hart_parallel_r() {
let command = Command::parse(b"s-h 1 parallel_r 23.05"); let command = Command::parse(b"s-h 1 t0 23.05");
assert_eq!(command, Ok(Command::SteinhartHart { assert_eq!(command, Ok(Command::SteinhartHart {
channel: 1, channel: 1,
parameter: ShParameter::ParallelR, parameter: ShParameter::T0,
value: 23.05, value: 23.05,
})); }));
} }

View File

@ -9,11 +9,15 @@ use panic_semihosting as _;
use log::{info, warn}; use log::{info, warn};
use core::ops::DerefMut;
use core::fmt::Write; use core::fmt::Write;
use cortex_m::asm::wfi; use cortex_m::asm::wfi;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embedded_hal::watchdog::{WatchdogEnable, Watchdog};
use stm32f4xx_hal::{ use stm32f4xx_hal::{
hal::{
self,
watchdog::{WatchdogEnable, Watchdog},
},
rcc::RccExt, rcc::RccExt,
watchdog::IndependentWatchdog, watchdog::IndependentWatchdog,
time::{U32Ext, MegaHertz}, time::{U32Ext, MegaHertz},
@ -36,16 +40,20 @@ use server::Server;
mod session; mod session;
use session::{CHANNELS, Session, SessionOutput}; use session::{CHANNELS, Session, SessionOutput};
mod command_parser; mod command_parser;
use command_parser::{Command, ShowCommand, PwmSetup, PwmMode}; 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;
#[derive(Clone, Copy, Debug)]
struct ChannelState { struct ChannelState {
adc_data: Option<i32>, adc_data: Option<i32>,
adc_time: Instant, adc_time: Instant,
dac_value: u32,
pid_enabled: bool,
pid: pid::Controller,
sh: sh::Parameters,
} }
impl Default for ChannelState { impl Default for ChannelState {
@ -53,11 +61,16 @@ impl Default for ChannelState {
ChannelState { ChannelState {
adc_data: None, adc_data: None,
adc_time: Instant::from_secs(0), 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);
#[cfg(not(feature = "semihosting"))] #[cfg(not(feature = "semihosting"))]
const WATCHDOG_INTERVAL: u32 = 100; const WATCHDOG_INTERVAL: u32 = 100;
#[cfg(feature = "semihosting")] #[cfg(feature = "semihosting")]
@ -65,12 +78,9 @@ const WATCHDOG_INTERVAL: u32 = 10_000;
#[cfg(not(feature = "generate-hwaddr"))] #[cfg(not(feature = "generate-hwaddr"))]
const NET_HWADDR: [u8; 6] = [0x02, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; const NET_HWADDR: [u8; 6] = [0x02, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
const TCP_PORT: u16 = 23; const TCP_PORT: u16 = 23;
const HSE: MegaHertz = MegaHertz(8);
/// Initialization and main loop /// Initialization and main loop
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
@ -105,9 +115,10 @@ fn main() -> ! {
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap(); let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync); let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync);
dac0.set(0); dac0.set(0).unwrap();
let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync); let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync);
dac1.set(0); dac1.set(0).unwrap();
let mut pwm = pins.pwm;
timer::setup(cp.SYST, clocks); timer::setup(cp.SYST, clocks);
@ -120,7 +131,9 @@ fn main() -> ! {
}; };
info!("Net hwaddr: {}", hwaddr); info!("Net hwaddr: {}", hwaddr);
let mut channel_states = [ChannelState::default(); CHANNELS]; let mut channel_states: [ChannelState; CHANNELS] = [
ChannelState::default(), ChannelState::default()
];
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| { net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
Server::<Session>::run(iface, |server| { Server::<Session>::run(iface, |server| {
@ -167,175 +180,213 @@ fn main() -> ! {
socket, "t={} raw{}=0x{:06X}", socket, "t={} raw{}=0x{:06X}",
state.adc_time, channel, adc_data state.adc_time, channel, adc_data
); );
// TODO: show pwm status et al
} }
} }
} }
Command::Show(ShowCommand::Pid) => { Command::Show(ShowCommand::Pid) => {
// for (channel, state) in states.iter().enumerate() { for (channel, state) in channel_states.iter().enumerate() {
// let _ = writeln!(socket, "PID settings for channel {}", channel); let _ = writeln!(socket, "PID settings for channel {}", channel);
// let pid = &state.pid; let pid = &state.pid;
// let _ = writeln!(socket, "- target={:.4}", pid.get_target()); let _ = writeln!(socket, "- target={:.4}", pid.get_target());
// let p = pid.get_parameters(); let p = pid.get_parameters();
// macro_rules! out { macro_rules! out {
// ($p: tt) => { ($p: tt) => {
// let _ = writeln!(socket, "- {}={:.4}", stringify!($p), p.$p); let _ = writeln!(socket, "- {}={:.4}", stringify!($p), p.$p);
// }; };
// } }
// out!(kp); out!(kp);
// out!(ki); out!(ki);
// out!(kd); out!(kd);
// out!(output_min); out!(output_min);
// out!(output_max); out!(output_max);
// out!(integral_min); out!(integral_min);
// out!(integral_max); out!(integral_max);
// let _ = writeln!(socket, ""); let _ = writeln!(socket, "");
// } }
} }
Command::Show(ShowCommand::Pwm) => { Command::Show(ShowCommand::Pwm) => {
// for (channel, state) in states.iter().enumerate() { for (channel, state) in channel_states.iter().enumerate() {
// let _ = writeln!( let _ = writeln!(
// socket, "channel {}: PID={}", socket, "channel {}: PID={}",
// channel, channel,
// if state.pid_enabled { "engaged" } else { "disengaged" } if state.pid_enabled { "engaged" } else { "disengaged" }
// ); );
// for pin in TecPin::VALID_VALUES { let _ = writeln!(socket, "- i_set={}/{}", state.dac_value, ad5680::MAX_VALUE);
// let (width, total) = match channel { fn show_pwm_channel<S, P>(mut socket: S, name: &str, pin: &P)
// 0 => tec0.get(*pin), where
// 1 => tec1.get(*pin), S: core::fmt::Write,
// _ => unreachable!(), P: hal::PwmPin<Duty=u16>,
// }; {
// let _ = writeln!(socket, "- {}={}/{}", pin, width, total); let _ = writeln!(
// } socket,
// let _ = writeln!(socket, ""); "- {}={}/{}",
// } name, pin.get_duty(), pin.get_max_duty()
);
}
match channel {
0 => {
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v0);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos0);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg0);
}
1 => {
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v1);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos1);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg1);
}
_ => unreachable!(),
}
let _ = writeln!(socket, "");
}
} }
Command::Show(ShowCommand::SteinhartHart) => { Command::Show(ShowCommand::SteinhartHart) => {
// for (channel, state) in states.iter().enumerate() { for (channel, state) in channel_states.iter().enumerate() {
// let _ = writeln!( let _ = writeln!(
// socket, "channel {}: Steinhart-Hart equation parameters", socket, "channel {}: Steinhart-Hart equation parameters",
// channel, channel,
// ); );
// let _ = writeln!(socket, "- a={}", state.sh.a); let _ = writeln!(socket, "- t0={}", state.sh.t0);
// let _ = writeln!(socket, "- b={}", state.sh.b); let _ = writeln!(socket, "- r={}", state.sh.r);
// let _ = writeln!(socket, "- c={}", state.sh.c); let _ = writeln!(socket, "- r0={}", state.sh.r0);
// let _ = writeln!(socket, "- parallel_r={}", state.sh.parallel_r); let _ = writeln!(socket, "");
// let _ = writeln!(socket, ""); }
// }
} }
Command::Show(ShowCommand::PostFilter) => { Command::Show(ShowCommand::PostFilter) => {
// for (channel, _) in states.iter().enumerate() { for (channel, _) in channel_states.iter().enumerate() {
// match adc.get_postfilter(channel as u8).unwrap() { match adc.get_postfilter(channel as u8).unwrap() {
// Some(filter) => { Some(filter) => {
// let _ = writeln!( let _ = writeln!(
// socket, "channel {}: postfilter={:.2} SPS", socket, "channel {}: postfilter={:.2} SPS",
// channel, filter.output_rate().unwrap() channel, filter.output_rate().unwrap()
// ); );
// }
// None => {
// let _ = writeln!(
// socket, "channel {}: no postfilter",
// channel
// );
// }
// }
// }
} }
Command::Pwm { channel, setup: PwmSetup::ISet(PwmMode::Pid) } => { None => {
// states[channel].pid_enabled = true; let _ = writeln!(
// let _ = writeln!(socket, "channel {}: PID enabled to control PWM", channel socket, "channel {}: no postfilter",
// ); channel
);
} }
Command::Pwm { channel, setup: PwmSetup::ISet(PwmMode::Manual(config))} => {
// states[channel].pid_enabled = false;
// let PwmConfig { width, total } = config;
// match channel {
// 0 => tec0.set(TecPin::ISet, width, total),
// 1 => tec1.set(TecPin::ISet, width, total),
// _ => unreachable!(),
// }
// let _ = writeln!(
// socket, "channel {}: PWM duty cycle manually set to {}/{}",
// channel, config.width, config.total
// );
} }
Command::Pwm { channel, setup } => { }
// let (pin, config) = match setup { }
// PwmSetup::ISet(_) => Command::PwmPid { channel } => {
// // Handled above channel_states[channel].pid_enabled = true;
// unreachable!(), let _ = writeln!(socket, "channel {}: PID enabled to control PWM", channel
// PwmSetup::MaxIPos(config) => );
// (TecPin::MaxIPos, config), }
// PwmSetup::MaxINeg(config) => Command::Pwm { channel, pin: PwmPin::ISet, duty } if duty <= ad5680::MAX_VALUE => {
// (TecPin::MaxINeg, config), channel_states[channel].pid_enabled = false;
// PwmSetup::MaxV(config) => match channel {
// (TecPin::MaxV, config), 0 => dac0.set(duty).unwrap(),
// }; 1 => dac1.set(duty).unwrap(),
// let PwmConfig { width, total } = config; _ => unreachable!(),
// match channel { }
// 0 => tec0.set(pin, width, total), channel_states[channel].dac_value = duty;
// 1 => tec1.set(pin, width, total), let _ = writeln!(
// _ => unreachable!(), socket, "channel {}: PWM duty cycle manually set to {}/{}",
// } channel, duty, ad5680::MAX_VALUE
// let _ = writeln!( );
// socket, "channel {}: PWM {} reconfigured to {}/{}", }
// channel, pin, width, total 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 => {
let duty = duty as u16;
fn set_pwm_channel<P: hal::PwmPin<Duty=u16>>(pin: &mut P, duty: u16) -> u16 {
pin.set_duty(duty);
pin.get_max_duty()
}
let max = match (channel, pin) {
(_, PwmPin::ISet) =>
// Handled above
unreachable!(),
(0, PwmPin::MaxIPos) =>
set_pwm_channel(&mut pwm.max_i_pos0, duty),
(0, PwmPin::MaxINeg) =>
set_pwm_channel(&mut pwm.max_i_neg0, duty),
(0, PwmPin::MaxV) =>
set_pwm_channel(&mut pwm.max_v0, duty),
(1, PwmPin::MaxIPos) =>
set_pwm_channel(&mut pwm.max_i_pos1, duty),
(1, PwmPin::MaxINeg) =>
set_pwm_channel(&mut pwm.max_i_neg1, duty),
(1, PwmPin::MaxV) =>
set_pwm_channel(&mut pwm.max_v1, duty),
_ =>
unreachable!(),
};
let _ = writeln!(
socket, "channel {}: PWM {} reconfigured to {}/{}",
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 } => { Command::Pid { channel, parameter, value } => {
// let pid = &mut states[channel].pid; let pid = &mut channel_states[channel].pid;
// use command_parser::PidParameter::*; use command_parser::PidParameter::*;
// match parameter { match parameter {
// Target => Target =>
// pid.set_target(value), pid.set_target(value),
// KP => KP =>
// pid.update_parameters(|parameters| parameters.kp = value), pid.update_parameters(|parameters| parameters.kp = value),
// KI => KI =>
// pid.update_parameters(|parameters| parameters.ki = value), pid.update_parameters(|parameters| parameters.ki = value),
// KD => KD =>
// pid.update_parameters(|parameters| parameters.kd = value), pid.update_parameters(|parameters| parameters.kd = value),
// OutputMin => OutputMin =>
// pid.update_parameters(|parameters| parameters.output_min = value), pid.update_parameters(|parameters| parameters.output_min = value),
// OutputMax => OutputMax =>
// pid.update_parameters(|parameters| parameters.output_max = value), pid.update_parameters(|parameters| parameters.output_max = value),
// IntegralMin => IntegralMin =>
// pid.update_parameters(|parameters| parameters.integral_min = value), pid.update_parameters(|parameters| parameters.integral_min = value),
// IntegralMax => IntegralMax =>
// pid.update_parameters(|parameters| parameters.integral_max = value), pid.update_parameters(|parameters| parameters.integral_max = value),
// } }
// pid.reset(); pid.reset();
// let _ = writeln!(socket, "PID parameter updated"); let _ = writeln!(socket, "PID parameter updated");
} }
Command::SteinhartHart { channel, parameter, value } => { Command::SteinhartHart { channel, parameter, value } => {
// let sh = &mut states[channel].sh; let sh = &mut channel_states[channel].sh;
// use command_parser::ShParameter::*; use command_parser::ShParameter::*;
// match parameter { match parameter {
// A => sh.a = value, T0 => sh.t0 = value,
// B => sh.b = value, R => sh.r = value,
// C => sh.c = value, R0 => sh.r0 = value,
// ParallelR => sh.parallel_r = value, }
// } sh.update();
// let _ = writeln!(socket, "Steinhart-Hart equation parameter updated"); let _ = writeln!(socket, "Steinhart-Hart equation parameter updated");
} }
Command::PostFilter { channel, rate } => { Command::PostFilter { channel, rate } => {
// let filter = ad7172::PostFilter::closest(rate); let filter = ad7172::PostFilter::closest(rate);
// match filter { match filter {
// Some(filter) => { Some(filter) => {
// adc.set_postfilter(channel as u8, Some(filter)).unwrap(); adc.set_postfilter(channel as u8, Some(filter)).unwrap();
// let _ = writeln!( let _ = writeln!(
// socket, "channel {}: postfilter set to {:.2} SPS", socket, "channel {}: postfilter set to {:.2} SPS",
// channel, filter.output_rate().unwrap() channel, filter.output_rate().unwrap()
// ); );
// } }
// None => { None => {
// let _ = writeln!(socket, "Unable to choose postfilter"); let _ = writeln!(socket, "Unable to choose postfilter");
// } }
// } }
}
cmd => {
let _ = writeln!(socket, "Not yet implemented: {:?}", cmd);
} }
} }
Ok(SessionOutput::Error(e)) => { Ok(SessionOutput::Error(e)) => {
let _ = writeln!(socket, "Command error: {:?}", e); let _ = writeln!(socket, "Command error: {:?}", e);
} }
Ok(o) => {
let _ = writeln!(socket, "Not yet implemented");
}
Err(_) => Err(_) =>
socket.close(), socket.close(),
} }

View File

@ -9,6 +9,20 @@ pub struct Parameters {
pub integral_max: f64 pub integral_max: f64
} }
impl Default for Parameters {
fn default() -> Self {
Parameters {
kp: 0.5,
ki: 0.05,
kd: 0.45,
output_min: 0.0,
output_max: 1.0,
integral_min: 0.0,
integral_max: 1.0,
}
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Controller { pub struct Controller {
parameters: Parameters, parameters: Parameters,

View File

@ -171,12 +171,12 @@ impl Pins {
} }
pub struct PwmPins { pub struct PwmPins {
max_v0: PwmChannels<TIM3, pwm::C1>, pub max_v0: PwmChannels<TIM3, pwm::C1>,
max_v1: PwmChannels<TIM3, pwm::C2>, pub max_v1: PwmChannels<TIM3, pwm::C2>,
max_i_pos0: PwmChannels<TIM1, pwm::C1>, pub max_i_pos0: PwmChannels<TIM1, pwm::C1>,
max_i_pos1: PwmChannels<TIM1, pwm::C2>, pub max_i_pos1: PwmChannels<TIM1, pwm::C2>,
max_i_neg0: PwmChannels<TIM1, pwm::C3>, pub max_i_neg0: PwmChannels<TIM1, pwm::C3>,
max_i_neg1: PwmChannels<TIM1, pwm::C4>, pub max_i_neg1: PwmChannels<TIM1, pwm::C4>,
} }
impl PwmPins { impl PwmPins {