Compare commits
5 Commits
83589610b5
...
aea306cf17
Author | SHA1 | Date |
---|---|---|
Astro | aea306cf17 | |
Astro | 97a09e422b | |
Astro | 61d2cd6ecf | |
Astro | f3ec96f425 | |
Astro | 9f70ef2e0a |
|
@ -70,6 +70,8 @@ The scope of this setting is per TCP session.
|
||||||
| `pid <0/1> integral_max <value>` | Set integral upper bound |
|
| `pid <0/1> integral_max <value>` | Set integral upper bound |
|
||||||
| `s-h` | Show Steinhart-Hart equation parameters |
|
| `s-h` | Show Steinhart-Hart equation parameters |
|
||||||
| `s-h <0/1> <t/b/r0> <value>` | Set Steinhart-Hart parameter for a channel |
|
| `s-h <0/1> <t/b/r0> <value>` | Set Steinhart-Hart parameter for a channel |
|
||||||
|
| `postfilter` | Show postfilter settings |
|
||||||
|
| `postfilter <0/1> off` | Disable postfilter |
|
||||||
| `postfilter <0/1> rate <rate>` | Set postfilter output data rate |
|
| `postfilter <0/1> rate <rate>` | Set postfilter output data rate |
|
||||||
| `load` | Restore configuration from EEPROM |
|
| `load` | Restore configuration from EEPROM |
|
||||||
| `save` | Save configuration to EEPROM |
|
| `save` | Save configuration to EEPROM |
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
time::MegaHertz,
|
time::MegaHertz,
|
||||||
spi,
|
spi,
|
||||||
|
@ -144,7 +145,7 @@ impl fmt::Display for RefSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PostFilter {
|
pub enum PostFilter {
|
||||||
/// 27 SPS, 47 dB rejection, 36.7 ms settling
|
/// 27 SPS, 47 dB rejection, 36.7 ms settling
|
||||||
|
|
|
@ -52,6 +52,7 @@ impl Channels {
|
||||||
for channel in 0..CHANNELS {
|
for channel in 0..CHANNELS {
|
||||||
channels.channel_state(channel).vref = channels.read_vref(channel);
|
channels.channel_state(channel).vref = channels.read_vref(channel);
|
||||||
channels.calibrate_dac_value(channel);
|
channels.calibrate_dac_value(channel);
|
||||||
|
channels.set_i(channel, ElectricCurrent::new::<ampere>(0.0));
|
||||||
}
|
}
|
||||||
channels
|
channels
|
||||||
}
|
}
|
||||||
|
@ -252,7 +253,7 @@ impl Channels {
|
||||||
|
|
||||||
/// Calibrate the I_SET DAC using the DAC_FB ADC pin.
|
/// Calibrate the I_SET DAC using the DAC_FB ADC pin.
|
||||||
///
|
///
|
||||||
/// These loops perform a width-first search for the DAC setting
|
/// These loops perform a breadth-first search for the DAC setting
|
||||||
/// that will produce a `target_voltage`.
|
/// that will produce a `target_voltage`.
|
||||||
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
||||||
let target_voltage = ElectricPotential::new::<volt>(2.5);
|
let target_voltage = ElectricPotential::new::<volt>(2.5);
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub enum Command {
|
||||||
},
|
},
|
||||||
PostFilter {
|
PostFilter {
|
||||||
channel: usize,
|
channel: usize,
|
||||||
rate: f32,
|
rate: Option<f32>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,15 +392,23 @@ fn postfilter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
||||||
|input| {
|
|input| {
|
||||||
let (input, channel) = channel(input)?;
|
let (input, channel) = channel(input)?;
|
||||||
let (input, _) = whitespace(input)?;
|
let (input, _) = whitespace(input)?;
|
||||||
let (input, _) = tag("rate")(input)?;
|
alt((
|
||||||
let (input, _) = whitespace(input)?;
|
value(Ok(Command::PostFilter {
|
||||||
let (input, rate) = float(input)?;
|
|
||||||
let result = rate
|
|
||||||
.map(|rate| Command::PostFilter {
|
|
||||||
channel,
|
channel,
|
||||||
rate: rate as f32,
|
rate: None,
|
||||||
});
|
}), tag("off")),
|
||||||
Ok((input, result))
|
move |input| {
|
||||||
|
let (input, _) = tag("rate")(input)?;
|
||||||
|
let (input, _) = whitespace(input)?;
|
||||||
|
let (input, rate) = float(input)?;
|
||||||
|
let result = rate
|
||||||
|
.map(|rate| Command::PostFilter {
|
||||||
|
channel,
|
||||||
|
rate: Some(rate as f32),
|
||||||
|
});
|
||||||
|
Ok((input, result))
|
||||||
|
}
|
||||||
|
))(input)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
value(Ok(Command::Show(ShowCommand::PostFilter)), end)
|
value(Ok(Command::Show(ShowCommand::PostFilter)), end)
|
||||||
|
@ -570,12 +578,27 @@ mod test {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_postfilter() {
|
||||||
|
let command = Command::parse(b"postfilter");
|
||||||
|
assert_eq!(command, Ok(Command::Show(ShowCommand::PostFilter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_postfilter_off() {
|
||||||
|
let command = Command::parse(b"postfilter 1 off");
|
||||||
|
assert_eq!(command, Ok(Command::PostFilter {
|
||||||
|
channel: 1,
|
||||||
|
rate: None,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_postfilter_rate() {
|
fn parse_postfilter_rate() {
|
||||||
let command = Command::parse(b"postfilter 0 rate 21");
|
let command = Command::parse(b"postfilter 0 rate 21");
|
||||||
assert_eq!(command, Ok(Command::PostFilter {
|
assert_eq!(command, Ok(Command::PostFilter {
|
||||||
channel: 0,
|
channel: 0,
|
||||||
rate: 21.0,
|
rate: Some(21.0),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use uom::si::{
|
||||||
thermodynamic_temperature::degree_celsius,
|
thermodynamic_temperature::degree_celsius,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ad7172::PostFilter,
|
||||||
channels::{CHANNELS, Channels},
|
channels::{CHANNELS, Channels},
|
||||||
command_parser::CenterPoint,
|
command_parser::CenterPoint,
|
||||||
EEPROM_SIZE, EEPROM_PAGE_SIZE,
|
EEPROM_SIZE, EEPROM_PAGE_SIZE,
|
||||||
|
@ -94,11 +95,18 @@ pub struct ChannelConfig {
|
||||||
pid_target: f32,
|
pid_target: f32,
|
||||||
sh: SteinhartHartConfig,
|
sh: SteinhartHartConfig,
|
||||||
pwm: PwmLimits,
|
pwm: PwmLimits,
|
||||||
|
/// uses variant `PostFilter::Invalid` instead of `None` to save space
|
||||||
|
adc_postfilter: PostFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelConfig {
|
impl ChannelConfig {
|
||||||
pub fn new(channels: &mut Channels, channel: usize) -> Self {
|
pub fn new(channels: &mut Channels, channel: usize) -> Self {
|
||||||
let pwm = PwmLimits::new(channels, channel);
|
let pwm = PwmLimits::new(channels, channel);
|
||||||
|
|
||||||
|
let adc_postfilter = channels.adc.get_postfilter(channel as u8)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap_or(PostFilter::Invalid);
|
||||||
|
|
||||||
let state = channels.channel_state(channel);
|
let state = channels.channel_state(channel);
|
||||||
ChannelConfig {
|
ChannelConfig {
|
||||||
center: state.center.clone(),
|
center: state.center.clone(),
|
||||||
|
@ -106,6 +114,7 @@ impl ChannelConfig {
|
||||||
pid_target: state.pid.target as f32,
|
pid_target: state.pid.target as f32,
|
||||||
sh: (&state.sh).into(),
|
sh: (&state.sh).into(),
|
||||||
pwm,
|
pwm,
|
||||||
|
adc_postfilter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +124,14 @@ impl ChannelConfig {
|
||||||
state.pid.parameters = self.pid.clone();
|
state.pid.parameters = self.pid.clone();
|
||||||
state.pid.target = self.pid_target.into();
|
state.pid.target = self.pid_target.into();
|
||||||
state.sh = (&self.sh).into();
|
state.sh = (&self.sh).into();
|
||||||
|
|
||||||
self.pwm.apply(channels, channel);
|
self.pwm.apply(channels, channel);
|
||||||
|
|
||||||
|
let adc_postfilter = match self.adc_postfilter {
|
||||||
|
PostFilter::Invalid => None,
|
||||||
|
adc_postfilter => Some(adc_postfilter),
|
||||||
|
};
|
||||||
|
let _ = channels.adc.set_postfilter(channel as u8, adc_postfilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +204,7 @@ mod test {
|
||||||
max_i_pos: 2.1,
|
max_i_pos: 2.1,
|
||||||
max_i_neg: 2.25,
|
max_i_neg: 2.25,
|
||||||
},
|
},
|
||||||
|
adc_postfilter: PostFilter::F21SPS,
|
||||||
};
|
};
|
||||||
let config = Config {
|
let config = Config {
|
||||||
channels: [
|
channels: [
|
||||||
|
@ -213,6 +230,7 @@ mod test {
|
||||||
max_i_pos: 2.1,
|
max_i_pos: 2.1,
|
||||||
max_i_neg: 2.25,
|
max_i_neg: 2.25,
|
||||||
},
|
},
|
||||||
|
adc_postfilter: PostFilter::F21SPS,
|
||||||
};
|
};
|
||||||
let config = Config {
|
let config = Config {
|
||||||
channels: [
|
channels: [
|
||||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -308,7 +308,7 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "channel {}: no postfilter",
|
socket, "channel {}: postfilter disabled",
|
||||||
channel
|
channel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -421,7 +421,14 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
let _ = writeln!(socket, "Steinhart-Hart equation parameter updated");
|
let _ = writeln!(socket, "Steinhart-Hart equation parameter updated");
|
||||||
}
|
}
|
||||||
Command::PostFilter { channel, rate } => {
|
Command::PostFilter { channel, rate: None } => {
|
||||||
|
channels.adc.set_postfilter(channel as u8, None).unwrap();
|
||||||
|
let _ = writeln!(
|
||||||
|
socket, "channel {}: postfilter disabled",
|
||||||
|
channel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Command::PostFilter { channel, rate: Some(rate) } => {
|
||||||
let filter = ad7172::PostFilter::closest(rate);
|
let filter = ad7172::PostFilter::closest(rate);
|
||||||
match filter {
|
match filter {
|
||||||
Some(filter) => {
|
Some(filter) => {
|
||||||
|
@ -459,6 +466,10 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Reset => {
|
Command::Reset => {
|
||||||
|
for i in 0..CHANNELS {
|
||||||
|
channels.power_down(i);
|
||||||
|
}
|
||||||
|
|
||||||
SCB::sys_reset();
|
SCB::sys_reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue