forked from M-Labs/thermostat
add Channels::calibrate_dac_value()
This commit is contained in:
parent
70127491f6
commit
e6e150dac3
@ -6,7 +6,6 @@ use stm32f4xx_hal::{
|
|||||||
time::MegaHertz,
|
time::MegaHertz,
|
||||||
spi,
|
spi,
|
||||||
};
|
};
|
||||||
use crate::units::Volts;
|
|
||||||
|
|
||||||
/// SPI Mode 1
|
/// SPI Mode 1
|
||||||
pub const SPI_MODE: spi::Mode = spi::Mode {
|
pub const SPI_MODE: spi::Mode = spi::Mode {
|
||||||
@ -45,9 +44,7 @@ impl<SPI: Transfer<u8>, S: OutputPin> Dac<SPI, S> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, voltage: Volts) -> Result<(), SPI::Error> {
|
pub fn set(&mut self, value: u32) -> Result<(), SPI::Error> {
|
||||||
let value = ((voltage.0 * (MAX_VALUE as f64) / 5.0) as u32)
|
|
||||||
.min(MAX_VALUE);
|
|
||||||
let buf = [
|
let buf = [
|
||||||
(value >> 14) as u8,
|
(value >> 14) as u8,
|
||||||
(value >> 6) as u8,
|
(value >> 6) as u8,
|
||||||
|
@ -2,7 +2,6 @@ use crate::{
|
|||||||
ad5680,
|
ad5680,
|
||||||
channel_state::ChannelState,
|
channel_state::ChannelState,
|
||||||
pins::{ChannelPins, ChannelPinSet},
|
pins::{ChannelPins, ChannelPinSet},
|
||||||
units::Volts,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Marker type for the first channel
|
/// Marker type for the first channel
|
||||||
@ -16,6 +15,8 @@ pub struct Channel<C: ChannelPins> {
|
|||||||
pub state: ChannelState,
|
pub state: ChannelState,
|
||||||
/// for `i_set`
|
/// for `i_set`
|
||||||
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
||||||
|
/// 1 / Volts
|
||||||
|
pub dac_factor: f64,
|
||||||
pub shdn: C::Shdn,
|
pub shdn: C::Shdn,
|
||||||
/// stm32f4 integrated adc
|
/// stm32f4 integrated adc
|
||||||
pub adc: C::Adc,
|
pub adc: C::Adc,
|
||||||
@ -30,11 +31,13 @@ impl<C: ChannelPins> Channel<C> {
|
|||||||
pub fn new(pins: ChannelPinSet<C>) -> Self {
|
pub fn new(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(Volts(0.0));
|
let _ = dac.set(0);
|
||||||
|
// sensible dummy preset. calibrate_i_set() must be used.
|
||||||
|
let dac_factor = ad5680::MAX_VALUE as f64 / 5.0;
|
||||||
|
|
||||||
Channel {
|
Channel {
|
||||||
state,
|
state,
|
||||||
dac,
|
dac, dac_factor,
|
||||||
shdn: pins.shdn,
|
shdn: pins.shdn,
|
||||||
adc: pins.adc,
|
adc: pins.adc,
|
||||||
vref_pin: pins.vref_pin,
|
vref_pin: pins.vref_pin,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
|
use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ad5680,
|
||||||
ad7172,
|
ad7172,
|
||||||
channel::{Channel, Channel0, Channel1},
|
channel::{Channel, Channel0, Channel1},
|
||||||
channel_state::ChannelState,
|
channel_state::ChannelState,
|
||||||
@ -83,14 +85,21 @@ impl Channels {
|
|||||||
|
|
||||||
/// i_set DAC
|
/// i_set DAC
|
||||||
pub fn set_dac(&mut self, channel: usize, voltage: Volts) {
|
pub fn set_dac(&mut self, channel: usize, voltage: Volts) {
|
||||||
|
let dac_factor = match channel.into() {
|
||||||
|
0 => self.channel0.dac_factor,
|
||||||
|
1 => self.channel1.dac_factor,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let value = (voltage.0 * dac_factor) as u32;
|
||||||
|
info!("set_dac {} {}", voltage, value);
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
self.channel0.dac.set(voltage).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();
|
self.channel0.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
self.channel1.dac.set(voltage).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();
|
self.channel1.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
@ -142,6 +151,7 @@ impl Channels {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// should be 1.5V
|
||||||
pub fn read_vref(&mut self, channel: usize) -> Volts {
|
pub fn read_vref(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
@ -185,4 +195,44 @@ impl Channels {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// for i_set
|
||||||
|
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
||||||
|
let vref = self.read_vref(channel);
|
||||||
|
let mut best_value = 0;
|
||||||
|
let mut best_error = Volts(100.0);
|
||||||
|
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 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 {
|
||||||
|
0 => self.channel0.dac_factor = dac_factor,
|
||||||
|
1 => self.channel1.dac_factor = dac_factor,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,8 @@ fn main() -> ! {
|
|||||||
dp.ADC1, dp.ADC2, dp.ADC3,
|
dp.ADC1, dp.ADC2, dp.ADC3,
|
||||||
);
|
);
|
||||||
let mut channels = Channels::new(pins);
|
let mut channels = Channels::new(pins);
|
||||||
|
channels.calibrate_dac_value(0);
|
||||||
|
|
||||||
timer::setup(cp.SYST, clocks);
|
timer::setup(cp.SYST, clocks);
|
||||||
|
|
||||||
#[cfg(not(feature = "generate-hwaddr"))]
|
#[cfg(not(feature = "generate-hwaddr"))]
|
||||||
|
Loading…
Reference in New Issue
Block a user