Compare commits

..

2 Commits

Author SHA1 Message Date
Astro eb9aeb160a add Channels::read_ref_adc() 2020-05-13 00:15:29 +02:00
Astro 3d1740b23b refactor into Channels::poll_adc() 2020-05-13 00:04:55 +02:00
4 changed files with 92 additions and 55 deletions

View File

@ -6,7 +6,7 @@ pub struct ChannelState {
pub adc_data: Option<u32>,
pub adc_time: Instant,
pub dac_value: u32,
pub pid_enabled: bool,
pub pid_engaged: bool,
pub pid: pid::Controller,
pub sh: sh::Parameters,
}
@ -17,7 +17,7 @@ impl Default for ChannelState {
adc_data: None,
adc_time: Instant::from_secs(0),
dac_value: 0,
pid_enabled: false,
pid_engaged: false,
pid: pid::Controller::new(pid::Parameters::default()),
sh: sh::Parameters::default(),
}
@ -26,7 +26,7 @@ impl Default for ChannelState {
impl ChannelState {
/// Update PID state on ADC input, calculate new DAC output
pub fn update_adc(&mut self, now: Instant, adc_data: u32) {
pub fn update_pid(&mut self, now: Instant, adc_data: u32) {
self.adc_data = Some(adc_data);
self.adc_time = now;

View File

@ -1,9 +1,14 @@
use stm32f4xx_hal::hal::digital::v2::OutputPin;
use smoltcp::time::Instant;
use crate::{
ad7172,
channel::{Channel, Channel0, Channel1},
channel_state::ChannelState,
pins,
};
pub const CHANNELS: usize = 2;
pub struct Channels {
pub channel0: Channel<Channel0>,
pub channel1: Channel<Channel1>,
@ -27,4 +32,61 @@ impl Channels {
Channels { channel0, channel1, adc, pwm }
}
pub fn channel_state<I: Into<usize>>(&mut self, channel: I) -> &mut ChannelState {
match channel.into() {
0 => &mut self.channel0.state,
1 => &mut self.channel1.state,
_ => unreachable!(),
}
}
/// ADC input + PID processing
pub fn poll_adc(&mut self, instant: Instant) -> Option<u8> {
self.adc.data_ready().unwrap().map(|channel| {
let data = self.adc.read_data().unwrap();
let dac_value = {
let state = self.channel_state(channel);
state.update_pid(instant, data);
if state.pid_engaged {
Some(state.dac_value)
} else {
None
}
};
if let Some(dac_value) = dac_value {
// Forward PID output to i_set DAC
match channel {
0 => {
self.channel0.dac.set(dac_value).unwrap();
self.channel0.shdn.set_high().unwrap();
}
1 => {
self.channel1.dac.set(dac_value).unwrap();
self.channel1.shdn.set_high().unwrap();
}
_ =>
unreachable!(),
}
}
channel
})
}
pub fn read_ref_adc(&mut self, channel: usize) -> u16 {
match channel {
0 => self.channel0.ref_adc.convert(
&self.channel0.ref_pin,
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
),
1 => self.channel1.ref_adc.convert(
&self.channel1.ref_pin,
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
),
_ => unreachable!(),
}
}
}

View File

@ -39,17 +39,16 @@ mod net;
mod server;
use server::Server;
mod session;
use session::{CHANNELS, Session, SessionOutput};
use session::{Session, SessionOutput};
mod command_parser;
use command_parser::{Command, ShowCommand, PwmPin};
mod timer;
mod pid;
mod steinhart_hart;
mod channels;
use channels::Channels;
use channels::{CHANNELS, Channels};
mod channel;
mod channel_state;
use channel_state::ChannelState;
const HSE: MegaHertz = MegaHertz(8);
@ -96,9 +95,6 @@ fn main() -> ! {
dp.ADC1, dp.ADC2,
);
let mut channels = Channels::new(pins);
let mut channel_states: [ChannelState; CHANNELS] = [
ChannelState::default(), ChannelState::default()
];
timer::setup(cp.SYST, clocks);
#[cfg(not(feature = "generate-hwaddr"))]
@ -114,31 +110,10 @@ fn main() -> ! {
Server::<Session>::run(iface, |server| {
loop {
let instant = Instant::from_millis(i64::from(timer::now()));
// ADC input
channels.adc.data_ready().unwrap().map(|channel| {
let data = channels.adc.read_data().unwrap();
let state = &mut channel_states[usize::from(channel)];
state.update_adc(instant, data);
if state.pid_enabled {
// Forward PID output to i_set DAC
match channel {
0 => {
channels.channel0.dac.set(state.dac_value).unwrap();
channels.channel0.shdn.set_high().unwrap();
}
1 => {
channels.channel1.dac.set(state.dac_value).unwrap();
channels.channel1.shdn.set_high().unwrap();
}
_ =>
unreachable!(),
}
}
let updated_channel = channels.poll_adc(instant);
if let Some(channel) = updated_channel {
server.for_each(|_, session| session.set_report_pending(channel.into()));
});
}
let instant = Instant::from_millis(i64::from(timer::now()));
cortex_m::interrupt::free(net::clear_pending);
@ -165,22 +140,21 @@ fn main() -> ! {
let _ = writeln!(socket, "report={}", if session.reporting() { "on" } else { "off" });
}
Command::Show(ShowCommand::Input) => {
for (channel, state) in channel_states.iter().enumerate() {
if let Some(adc_data) = state.adc_data {
for channel in 0..CHANNELS {
if let Some(adc_data) = channels.channel_state(channel).adc_data {
let ref_adc_data = channels.read_ref_adc(channel);
let state = channels.channel_state(channel);
let _ = writeln!(
socket, "t={} raw{}=0x{:06X}",
state.adc_time, channel, adc_data
socket, "t={} raw{}=0x{:06X} ref_adc={}",
state.adc_time, channel, adc_data,
ref_adc_data
);
}
}
let ref0 = channels.channel0.ref_adc.convert(
&channels.channel0.ref_pin, stm32f4xx_hal::adc::config::SampleTime::Cycles_480
);
let _ = writeln!(socket, "ref0={}", ref0);
}
Command::Show(ShowCommand::Pid) => {
for (channel, state) in channel_states.iter().enumerate() {
for channel in 0..CHANNELS {
let state = channels.channel_state(channel);
let _ = writeln!(socket, "PID settings for channel {}", channel);
let pid = &state.pid;
let _ = writeln!(socket, "- target={:.4}", pid.target);
@ -206,11 +180,12 @@ fn main() -> ! {
}
}
Command::Show(ShowCommand::Pwm) => {
for (channel, state) in channel_states.iter().enumerate() {
for channel in 0..CHANNELS {
let state = channels.channel_state(channel);
let _ = writeln!(
socket, "channel {}: PID={}",
channel,
if state.pid_enabled { "engaged" } else { "disengaged" }
if state.pid_engaged { "engaged" } else { "disengaged" }
);
let _ = writeln!(socket, "- i_set={}/{}", state.dac_value, ad5680::MAX_VALUE);
fn show_pwm_channel<S, P>(mut socket: S, name: &str, pin: &P)
@ -241,7 +216,8 @@ fn main() -> ! {
}
}
Command::Show(ShowCommand::SteinhartHart) => {
for (channel, state) in channel_states.iter().enumerate() {
for channel in 0..CHANNELS {
let state = channels.channel_state(channel);
let _ = writeln!(
socket, "channel {}: Steinhart-Hart equation parameters",
channel,
@ -253,7 +229,7 @@ fn main() -> ! {
}
}
Command::Show(ShowCommand::PostFilter) => {
for (channel, _) in channel_states.iter().enumerate() {
for channel in 0..CHANNELS {
match channels.adc.get_postfilter(channel as u8).unwrap() {
Some(filter) => {
let _ = writeln!(
@ -271,12 +247,12 @@ fn main() -> ! {
}
}
Command::PwmPid { channel } => {
channel_states[channel].pid_enabled = true;
channels.channel_state(channel).pid_engaged = true;
let _ = writeln!(socket, "channel {}: PID enabled to control PWM", channel
);
}
Command::Pwm { channel, pin: PwmPin::ISet, duty } if duty <= ad5680::MAX_VALUE => {
channel_states[channel].pid_enabled = false;
channels.channel_state(channel).pid_engaged = false;
match channel {
0 => {
channels.channel0.dac.set(duty).unwrap();
@ -288,7 +264,7 @@ fn main() -> ! {
}
_ => unreachable!(),
}
channel_states[channel].dac_value = duty;
channels.channel_state(channel).dac_value = duty;
let _ = writeln!(
socket, "channel {}: PWM duty cycle manually set to {}/{}",
channel, duty, ad5680::MAX_VALUE
@ -335,7 +311,7 @@ fn main() -> ! {
let _ = writeln!(socket, "error: PWM duty range must fit 16 bits");
}
Command::Pid { channel, parameter, value } => {
let pid = &mut channel_states[channel].pid;
let pid = &mut channels.channel_state(channel).pid;
use command_parser::PidParameter::*;
match parameter {
Target =>
@ -361,7 +337,7 @@ fn main() -> ! {
let _ = writeln!(socket, "PID parameter updated");
}
Command::SteinhartHart { channel, parameter, value } => {
let sh = &mut channel_states[channel].sh;
let sh = &mut channels.channel_state(channel).sh;
use command_parser::ShParameter::*;
match parameter {
T0 => sh.t0 = value,
@ -397,7 +373,7 @@ fn main() -> ! {
}
} else if socket.can_send() && socket.send_capacity() - socket.send_queue() > 256 {
while let Some(channel) = session.is_report_pending() {
let state = &mut channel_states[usize::from(channel)];
let state = &mut channels.channel_state(usize::from(channel));
let _ = writeln!(
socket, "t={} raw{}=0x{:06X}",
state.adc_time, channel, state.adc_data.unwrap_or(0)

View File

@ -1,4 +1,5 @@
use super::command_parser::{Command, Error as ParserError};
use super::channels::CHANNELS;
const MAX_LINE_LEN: usize = 64;
@ -50,8 +51,6 @@ impl From<Result<Command, ParserError>> for SessionOutput {
}
}
pub const CHANNELS: usize = 2;
pub struct Session {
reader: LineReader,
reporting: bool,