adc: don't calibrate but convert using ChannelCalibration

This commit is contained in:
Astro 2020-09-09 23:10:33 +02:00
parent 2617895460
commit c11b71cc0d
3 changed files with 47 additions and 39 deletions

View File

@ -114,27 +114,11 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
Ok(()) Ok(())
} }
/// Calibrates offset registers pub fn get_calibration(&mut self, index: u8) -> Result<ChannelCalibration, SPI::Error> {
pub fn calibrate(&mut self) -> Result<(), SPI::Error> { let offset = self.read_reg(&regs::Offset { index })?.offset();
// internal offset calibration let gain = self.read_reg(&regs::Gain { index })?.gain();
self.update_reg(&regs::AdcMode, |adc_mode| { let bipolar = self.read_reg(&regs::SetupCon { index })?.bipolar();
adc_mode.set_mode(Mode::InternalOffsetCalibration); Ok(ChannelCalibration { offset, gain, bipolar })
})?;
while ! self.read_reg(&regs::Status)?.ready() {}
// system offset calibration
self.update_reg(&regs::AdcMode, |adc_mode| {
adc_mode.set_mode(Mode::SystemOffsetCalibration);
})?;
while ! self.read_reg(&regs::Status)?.ready() {}
// system gain calibration
self.update_reg(&regs::AdcMode, |adc_mode| {
adc_mode.set_mode(Mode::SystemGainCalibration);
})?;
while ! self.read_reg(&regs::Status)?.ready() {}
Ok(())
} }
pub fn start_continuous_conversion(&mut self) -> Result<(), SPI::Error> { pub fn start_continuous_conversion(&mut self) -> Result<(), SPI::Error> {
@ -279,3 +263,26 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
result result
} }
} }
#[derive(Debug, Clone)]
pub struct ChannelCalibration {
offset: u32,
gain: u32,
bipolar: bool,
}
impl ChannelCalibration {
pub fn convert_data(&self, data: u32) -> f64 {
let data = if self.bipolar {
(data as i32 - 0x80_0000) as f64
} else {
data as f64 / 2.0
};
let data = data / (self.gain as f64 / (0x40_0000 as f64));
let data = data + (self.offset as i32 - 0x80_0000) as f64;
let data = data / (2 << 23) as f64;
const V_REF: f64 = 3.0;
data * V_REF / 0.75
}
}

View File

@ -32,23 +32,16 @@ impl Channels {
// Feature not used // Feature not used
adc.set_sync_enable(false).unwrap(); adc.set_sync_enable(false).unwrap();
// Calibrate ADC channels individually
adc.disable_all_channels().unwrap();
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
adc.calibrate().unwrap();
adc.disable_channel(0).unwrap();
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
adc.calibrate().unwrap();
adc.disable_channel(1).unwrap();
// Setup channels and start ADC // Setup channels and start ADC
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap(); adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap(); adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
adc.start_continuous_conversion().unwrap(); adc.start_continuous_conversion().unwrap();
Channels { channel0, channel1, adc, pins_adc, pwm } let mut channels = Channels { channel0, channel1, adc, pins_adc, pwm };
for channel in 0..CHANNELS {
channels.calibrate_dac_value(channel);
}
channels
} }
pub fn channel_state<I: Into<usize>>(&mut self, channel: I) -> &mut ChannelState { pub fn channel_state<I: Into<usize>>(&mut self, channel: I) -> &mut ChannelState {

View File

@ -102,8 +102,10 @@ fn main() -> ! {
leds.g4.off(); leds.g4.off();
let mut channels = Channels::new(pins); let mut channels = Channels::new(pins);
channels.calibrate_dac_value(0); let adc_calibration = [
channels.calibrate_dac_value(1); channels.adc.get_calibration(0).unwrap(),
channels.adc.get_calibration(1).unwrap(),
];
#[cfg(not(feature = "generate-hwaddr"))] #[cfg(not(feature = "generate-hwaddr"))]
let hwaddr = EthernetAddress(NET_HWADDR); let hwaddr = EthernetAddress(NET_HWADDR);
@ -162,12 +164,16 @@ fn main() -> ! {
let state = channels.channel_state(channel); let state = channels.channel_state(channel);
let _ = writeln!( let _ = writeln!(
socket, "t={} adc_raw{}=0x{:06X} vref={} dac_feedback={} itec={} tec={} tec_u_meas={}", socket, "channel {}: t={} adc_raw{}=0x{:06X} adc{}={:.3}V vref={} dac_feedback={} itec={} tec={} tec_u_meas={}",
channel,
state.adc_time, channel, adc_data, state.adc_time, channel, adc_data,
channel, adc_calibration[channel].convert_data(adc_data),
vref, dac_feedback, vref, dac_feedback,
itec, tec_i, itec, tec_i,
tec_u_meas, tec_u_meas,
); );
} else {
let _ = writeln!(socket, "channel {}: no adc input", channel);
} }
} }
} }
@ -373,9 +379,11 @@ fn main() -> ! {
} else if socket.can_send() && socket.send_capacity() - socket.send_queue() > 256 { } else if socket.can_send() && socket.send_capacity() - socket.send_queue() > 256 {
while let Some(channel) = session.is_report_pending() { while let Some(channel) = session.is_report_pending() {
let state = &mut channels.channel_state(usize::from(channel)); let state = &mut channels.channel_state(usize::from(channel));
let adc_data = state.adc_data.unwrap_or(0);
let _ = writeln!( let _ = writeln!(
socket, "t={} raw{}=0x{:06X}", socket, "t={} raw{}=0x{:06X} value={:.3}V",
state.adc_time, channel, state.adc_data.unwrap_or(0) state.adc_time, channel, adc_data,
adc_calibration[channel].convert_data(adc_data),
).map(|_| { ).map(|_| {
session.mark_report_sent(channel); session.mark_report_sent(channel);
}); });