From c11b71cc0d8b77dd4d3e78adb5521e05e23b12ba Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 9 Sep 2020 23:10:33 +0200 Subject: [PATCH] adc: don't calibrate but convert using ChannelCalibration --- src/ad7172/adc.rs | 51 +++++++++++++++++++++++++++-------------------- src/channels.rs | 17 +++++----------- src/main.rs | 18 ++++++++++++----- 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/ad7172/adc.rs b/src/ad7172/adc.rs index ace673e..c7d6646 100644 --- a/src/ad7172/adc.rs +++ b/src/ad7172/adc.rs @@ -114,27 +114,11 @@ impl, NSS: OutputPin, E: fmt::Debug> Adc Ok(()) } - /// Calibrates offset registers - pub fn calibrate(&mut self) -> Result<(), SPI::Error> { - // internal offset calibration - self.update_reg(®s::AdcMode, |adc_mode| { - adc_mode.set_mode(Mode::InternalOffsetCalibration); - })?; - while ! self.read_reg(®s::Status)?.ready() {} - - // system offset calibration - self.update_reg(®s::AdcMode, |adc_mode| { - adc_mode.set_mode(Mode::SystemOffsetCalibration); - })?; - while ! self.read_reg(®s::Status)?.ready() {} - - // system gain calibration - self.update_reg(®s::AdcMode, |adc_mode| { - adc_mode.set_mode(Mode::SystemGainCalibration); - })?; - while ! self.read_reg(®s::Status)?.ready() {} - - Ok(()) + pub fn get_calibration(&mut self, index: u8) -> Result { + let offset = self.read_reg(®s::Offset { index })?.offset(); + let gain = self.read_reg(®s::Gain { index })?.gain(); + let bipolar = self.read_reg(®s::SetupCon { index })?.bipolar(); + Ok(ChannelCalibration { offset, gain, bipolar }) } pub fn start_continuous_conversion(&mut self) -> Result<(), SPI::Error> { @@ -262,7 +246,7 @@ impl, NSS: OutputPin, E: fmt::Debug> Adc Err(e) => Err(e), }; let result = match (result, checksum) { - (Ok(_),None) => + (Ok(_), None) => Ok(None), (Ok(_), Some(checksum_out)) => { let mut checksum_buf = [checksum_out; 1]; @@ -279,3 +263,26 @@ impl, NSS: OutputPin, E: fmt::Debug> Adc 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 + } +} diff --git a/src/channels.rs b/src/channels.rs index 00a15d7..8602e00 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -32,23 +32,16 @@ impl Channels { // Feature not used 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 adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap(); adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).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>(&mut self, channel: I) -> &mut ChannelState { diff --git a/src/main.rs b/src/main.rs index c5157a3..c649f59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,8 +102,10 @@ fn main() -> ! { leds.g4.off(); let mut channels = Channels::new(pins); - channels.calibrate_dac_value(0); - channels.calibrate_dac_value(1); + let adc_calibration = [ + channels.adc.get_calibration(0).unwrap(), + channels.adc.get_calibration(1).unwrap(), + ]; #[cfg(not(feature = "generate-hwaddr"))] let hwaddr = EthernetAddress(NET_HWADDR); @@ -162,12 +164,16 @@ fn main() -> ! { let state = channels.channel_state(channel); 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, + channel, adc_calibration[channel].convert_data(adc_data), vref, dac_feedback, itec, tec_i, 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 { while let Some(channel) = session.is_report_pending() { let state = &mut channels.channel_state(usize::from(channel)); + let adc_data = state.adc_data.unwrap_or(0); let _ = writeln!( - socket, "t={} raw{}=0x{:06X}", - state.adc_time, channel, state.adc_data.unwrap_or(0) + socket, "t={} raw{}=0x{:06X} value={:.3}V", + state.adc_time, channel, adc_data, + adc_calibration[channel].convert_data(adc_data), ).map(|_| { session.mark_report_sent(channel); });