Compare commits

...

2 Commits

5 changed files with 44 additions and 7 deletions

View File

@ -19,6 +19,8 @@ pub const SPI_MODE: spi::Mode = spi::Mode {
/// 2 MHz /// 2 MHz
pub const SPI_CLOCK: MegaHertz = MegaHertz(2); pub const SPI_CLOCK: MegaHertz = MegaHertz(2);
pub const MAX_VALUE: u32 = 0xFF_FFFF;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[repr(u8)] #[repr(u8)]

View File

@ -28,12 +28,10 @@ pub struct Channel<C: ChannelPins> {
} }
impl<C: ChannelPins> Channel<C> { impl<C: ChannelPins> Channel<C> {
pub fn new(mut pins: ChannelPinSet<C>, adc_calibration: ad7172::ChannelCalibration) -> Self { pub fn new(pins: ChannelPinSet<C>, adc_calibration: ad7172::ChannelCalibration) -> Self {
let state = ChannelState::new(adc_calibration); let state = ChannelState::new(adc_calibration);
let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync); let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
let _ = dac.set(0); let _ = dac.set(0);
// power up TEC
let _ = pins.shdn.set_high();
// sensible dummy preset. calibrate_i_set() must be used. // sensible dummy preset. calibrate_i_set() must be used.
let dac_factor = ad5680::MAX_VALUE as f64 / 5.0; let dac_factor = ad5680::MAX_VALUE as f64 / 5.0;
@ -47,4 +45,14 @@ impl<C: ChannelPins> Channel<C> {
tec_u_meas_pin: pins.tec_u_meas_pin, tec_u_meas_pin: pins.tec_u_meas_pin,
} }
} }
// power up TEC
pub fn power_up(&mut self) {
let _ = self.shdn.set_high();
}
// power down TEC
pub fn power_down(&mut self) {
let _ = self.shdn.set_low();
}
} }

View File

@ -50,7 +50,12 @@ impl ChannelState {
} }
pub fn update(&mut self, now: Instant, adc_data: u32) { pub fn update(&mut self, now: Instant, adc_data: u32) {
self.adc_data = Some(adc_data); self.adc_data = if adc_data == ad7172::MAX_VALUE {
// this means there is no thermistor plugged into the ADC.
None
} else {
Some(adc_data)
};
self.adc_time = now; self.adc_time = now;
} }

View File

@ -70,13 +70,16 @@ impl Channels {
let data = self.adc.read_data().unwrap(); let data = self.adc.read_data().unwrap();
let state = self.channel_state(channel); let state = self.channel_state(channel);
state.update(instant, data); state.update(instant, data);
match state.update_pid() { match state.update_pid() {
Some(pid_output) if state.pid_engaged => { Some(pid_output) if state.pid_engaged => {
log::info!("PID: {:.3} A", pid_output); log::info!("PID: {:.3} A", pid_output);
// Forward PID output to i_set DAC // Forward PID output to i_set DAC
self.set_i(channel.into(), ElectricCurrent::new::<ampere>(pid_output)); self.set_i(channel.into(), ElectricCurrent::new::<ampere>(pid_output));
self.power_up(channel);
}
None if state.pid_engaged => {
self.power_down(channel);
} }
_ => {} _ => {}
} }
@ -293,6 +296,24 @@ impl Channels {
self.set_dac(channel, ElectricPotential::new::<volt>(0.0)); self.set_dac(channel, ElectricPotential::new::<volt>(0.0));
} }
// power up TEC
pub fn power_up<I: Into<usize>>(&mut self, channel: I) {
match channel.into() {
0 => self.channel0.power_up(),
1 => self.channel1.power_up(),
_ => unreachable!(),
}
}
// power down TEC
pub fn power_down<I: Into<usize>>(&mut self, channel: I) {
match channel.into() {
0 => self.channel0.power_down(),
1 => self.channel1.power_down(),
_ => unreachable!(),
}
}
fn get_pwm(&self, channel: usize, pin: PwmPin) -> f64 { fn get_pwm(&self, channel: usize, pin: PwmPin) -> f64 {
fn get<P: hal::PwmPin<Duty=u16>>(pin: &P) -> f64 { fn get<P: hal::PwmPin<Duty=u16>>(pin: &P) -> f64 {
let duty = pin.get_duty(); let duty = pin.get_duty();

View File

@ -182,10 +182,10 @@ fn main() -> ! {
let state = channels.channel_state(channel); let state = channels.channel_state(channel);
let _ = writeln!( let _ = writeln!(
socket, "channel {}: t={:.0} adc{}={:.3} adc_r={:.3} vref={:.3} dac_feedback={:.3} itec={:.3} tec={:.3} tec_u_meas={:.3} r={:.3}", socket, "channel {}: t={:.0} adc{}={:.3} adc_r={:?} vref={:.3} dac_feedback={:.3} itec={:.3} tec={:.3} tec_u_meas={:.3} r={:.3}",
channel, state.adc_time, channel, state.adc_time,
channel, adc_input.into_format_args(volt, Abbreviation), channel, adc_input.into_format_args(volt, Abbreviation),
state.get_sens().unwrap().into_format_args(ohm, Abbreviation), state.get_sens().map(|sens| sens.into_format_args(ohm, Abbreviation)),
vref.into_format_args(volt, Abbreviation), dac_feedback.into_format_args(volt, Abbreviation), vref.into_format_args(volt, Abbreviation), dac_feedback.into_format_args(volt, Abbreviation),
itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, Abbreviation), itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, Abbreviation),
tec_u_meas.into_format_args(volt, Abbreviation), tec_u_meas.into_format_args(volt, Abbreviation),
@ -328,6 +328,7 @@ fn main() -> ! {
leds.g3.off(); leds.g3.off();
let current = ElectricCurrent::new::<ampere>(value); let current = ElectricCurrent::new::<ampere>(value);
let (current, max) = channels.set_i(channel, current); let (current, max) = channels.set_i(channel, current);
channels.power_up(channel);
let _ = writeln!( let _ = writeln!(
socket, "channel {}: i_set DAC output set to {:.3} / {:.3}", socket, "channel {}: i_set DAC output set to {:.3} / {:.3}",
channel, channel,