Compare commits
3 Commits
e6e150dac3
...
35af543e33
Author | SHA1 | Date |
---|---|---|
Astro | 35af543e33 | |
Astro | cca0a77657 | |
Astro | d326517453 |
|
@ -1,3 +1,4 @@
|
||||||
|
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
||||||
use crate::{
|
use crate::{
|
||||||
ad5680,
|
ad5680,
|
||||||
channel_state::ChannelState,
|
channel_state::ChannelState,
|
||||||
|
@ -28,10 +29,12 @@ pub struct Channel<C: ChannelPins> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ChannelPins> Channel<C> {
|
impl<C: ChannelPins> Channel<C> {
|
||||||
pub fn new(pins: ChannelPinSet<C>) -> Self {
|
pub fn new(mut pins: ChannelPinSet<C>) -> Self {
|
||||||
let state = ChannelState::default();
|
let state = ChannelState::default();
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use log::info;
|
use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -14,10 +13,10 @@ pub const CHANNELS: usize = 2;
|
||||||
|
|
||||||
// TODO: -pub
|
// TODO: -pub
|
||||||
pub struct Channels {
|
pub struct Channels {
|
||||||
pub channel0: Channel<Channel0>,
|
channel0: Channel<Channel0>,
|
||||||
pub channel1: Channel<Channel1>,
|
channel1: Channel<Channel1>,
|
||||||
pub adc: ad7172::Adc<pins::AdcSpi, pins::AdcNss>,
|
pub adc: ad7172::Adc<pins::AdcSpi, pins::AdcNss>,
|
||||||
pub tec_u_meas_adc: pins::TecUMeasAdc,
|
tec_u_meas_adc: pins::TecUMeasAdc,
|
||||||
pub pwm: pins::PwmPins,
|
pub pwm: pins::PwmPins,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,17 +90,14 @@ impl Channels {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let value = (voltage.0 * dac_factor) as u32;
|
let value = (voltage.0 * dac_factor) as u32;
|
||||||
info!("set_dac {} {}", voltage, value);
|
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
self.channel0.dac.set(value).unwrap();
|
self.channel0.dac.set(value).unwrap();
|
||||||
self.channel0.state.dac_value = voltage;
|
self.channel0.state.dac_value = voltage;
|
||||||
self.channel0.shdn.set_high().unwrap();
|
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
self.channel1.dac.set(value).unwrap();
|
self.channel1.dac.set(value).unwrap();
|
||||||
self.channel1.state.dac_value = voltage;
|
self.channel1.state.dac_value = voltage;
|
||||||
self.channel1.shdn.set_high().unwrap();
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -129,6 +125,18 @@ impl Channels {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_dac_feedback_until_stable(&mut self, channel: usize, tolerance: f64) -> Volts {
|
||||||
|
let mut prev = self.read_dac_feedback(channel);
|
||||||
|
loop {
|
||||||
|
let current = self.read_dac_feedback(channel);
|
||||||
|
use num_traits::float::Float;
|
||||||
|
if (current - prev).0.abs() < tolerance {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
prev = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_itec(&mut self, channel: usize) -> Volts {
|
pub fn read_itec(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -199,40 +207,47 @@ impl Channels {
|
||||||
/// for i_set
|
/// for i_set
|
||||||
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
||||||
let vref = self.read_vref(channel);
|
let vref = self.read_vref(channel);
|
||||||
let mut best_value = 0;
|
let value = self.calibrate_dac_value_for_voltage(channel, vref);
|
||||||
let mut best_error = Volts(100.0);
|
info!("best dac value for {}: {}", vref, value);
|
||||||
for value in 1..=ad5680::MAX_VALUE {
|
|
||||||
match channel {
|
|
||||||
0 => {
|
|
||||||
self.channel0.dac.set(value).unwrap();
|
|
||||||
self.channel0.shdn.set_high().unwrap();
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
self.channel1.dac.set(value).unwrap();
|
|
||||||
self.channel1.shdn.set_high().unwrap();
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
let dac_feedback = self.read_dac_feedback(channel);
|
let dac_factor = value as f64 / vref.0;
|
||||||
let error = vref - dac_feedback;
|
|
||||||
if error < Volts(0.0) {
|
|
||||||
info!("calibration done at {} > {}", dac_feedback, vref);
|
|
||||||
break;
|
|
||||||
} else if error < best_error {
|
|
||||||
best_value = value;
|
|
||||||
best_error = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.set_dac(channel, Volts(0.0));
|
|
||||||
info!("best dac value for {}: {}, itec={}", vref, best_value, self.read_itec(channel));
|
|
||||||
|
|
||||||
let dac_factor = best_value as f64 / vref.0;
|
|
||||||
match channel {
|
match channel {
|
||||||
0 => self.channel0.dac_factor = dac_factor,
|
0 => self.channel0.dac_factor = dac_factor,
|
||||||
1 => self.channel1.dac_factor = dac_factor,
|
1 => self.channel1.dac_factor = dac_factor,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calibrate_dac_value_for_voltage(&mut self, channel: usize, voltage: Volts) -> u32 {
|
||||||
|
let mut best_value = 0;
|
||||||
|
let mut best_error = Volts(100.0);
|
||||||
|
|
||||||
|
for step in (1..=12).rev() {
|
||||||
|
for value in (best_value..=ad5680::MAX_VALUE).step_by(2usize.pow(step)) {
|
||||||
|
match channel {
|
||||||
|
0 => {
|
||||||
|
self.channel0.dac.set(value).unwrap();
|
||||||
|
// self.channel0.shdn.set_high().unwrap();
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
self.channel1.dac.set(value).unwrap();
|
||||||
|
// self.channel1.shdn.set_high().unwrap();
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let dac_feedback = self.read_dac_feedback_until_stable(channel, 0.001);
|
||||||
|
let error = voltage - dac_feedback;
|
||||||
|
if error < Volts(0.0) {
|
||||||
|
break;
|
||||||
|
} else if error < best_error {
|
||||||
|
best_value = value;
|
||||||
|
best_error = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set_dac(channel, Volts(0.0));
|
||||||
|
best_value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ 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")]
|
||||||
const WATCHDOG_INTERVAL: u32 = 10_000;
|
const WATCHDOG_INTERVAL: u32 = 30_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];
|
||||||
|
|
Loading…
Reference in New Issue