From 74ad7d08b9d421625277709b7b5b4a0c4f38e643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Fri, 9 Oct 2020 13:38:18 +0000 Subject: [PATCH] ads7924: disable scan around read, don't use manual --- ads7924/src/lib.rs | 32 ++++++++++---------------------- src/rf_channel.rs | 39 +++++++++++++++++---------------------- 2 files changed, 27 insertions(+), 44 deletions(-) diff --git a/ads7924/src/lib.rs b/ads7924/src/lib.rs index 89de5569..b7fb3693 100644 --- a/ads7924/src/lib.rs +++ b/ads7924/src/lib.rs @@ -26,6 +26,7 @@ where #[derive(Copy, Clone, PartialEq)] #[doc(hidden)] +#[allow(dead_code)] enum OperationMode { Active = 0b100000, ManualSingle = 0b110000, @@ -102,6 +103,10 @@ where ads7924.reset(delay)?; + // Bring the ADC from idle to awake mode unconditionally. + let mode_control = *0u8.set_bits(2..8, OperationMode::Active as u8); + ads7924.write(Register::ModeCntrl, &[mode_control])?; + // Configure the interrupt pin to operate in alarm mode when thresholds are exceeded once. let interrupt_config = *0u8.set_bits(5..8, 0b1); ads7924.write(Register::IntConfig, &[interrupt_config])?; @@ -272,36 +277,19 @@ where Channel::Two => Register::Data2Upper, Channel::Three => Register::Data3Upper, }; + // First, disable Autoscan mode. + self.set_mode(OperationMode::Active, None)?; let mut voltage_register: [u8; 2] = [0; 2]; self.read(upper_data_register, &mut voltage_register)?; + // Reenable Autoscan. + self.set_mode(OperationMode::AutoscanWithSleep, None)?; + // Convert the voltage register to an ADC code. The code is stored MSB-aligned, so we need // to shift it back into alignment. let code = u16::from_be_bytes(voltage_register) >> 4; Ok(code as f32 * self.volts_per_lsb) } - - /// Get an up-to-date analog voltage of a channel. - /// - /// # Note - /// This function will force the ADC to perform a new analog conversion, so results will be as - /// up-to-date as possible. - /// - /// # Args - /// * `channel` - The channel to get the voltage of. - /// - /// # Returns - /// The analog measurement of the specified channel in volts. - pub fn measure_voltage(&mut self, channel: Channel) -> Result { - // First, update the mode to be manual-single. - self.set_mode(OperationMode::ManualSingle, Some(channel))?; - - let voltage = self.get_voltage(channel)?; - - self.set_mode(OperationMode::AutoscanWithSleep, None)?; - - Ok(voltage) - } } diff --git a/src/rf_channel.rs b/src/rf_channel.rs index 425fbb5c..941511ed 100644 --- a/src/rf_channel.rs +++ b/src/rf_channel.rs @@ -840,7 +840,7 @@ impl RfChannel { .unwrap(); let v_p5v0mp = p5v_voltage * 2.5; - let i_p28v0ch = self.measure_p28v_current(false); + let i_p28v0ch = self.get_p28v_current(); // The P5V current is sensed across a 100mOhm resistor with 100 Ohm input resistance. The // output resistance on the current sensor is 6.2K Ohm. @@ -870,7 +870,7 @@ impl RfChannel { } } - fn measure_p28v_current(&mut self, force_update: bool) -> f32 { + fn get_p28v_current(&mut self) -> f32 { // The 28V current is sensed across a 100mOhm resistor with 100 Ohm input resistance. The // output resistance on the current sensor is 4.3K Ohm. // @@ -886,19 +886,12 @@ impl RfChannel { // Vout = Isns * Rsns * Rout / Rin // Isns = (Vout * Rin) / Rsns / Rout - let p28v_rail_current_sense = if force_update { - // Force the power monitor to make a new reading. - self.i2c_devices - .power_monitor - .measure_voltage(ads7924::Channel::Zero) - .unwrap() - } else { - // Read the cached (scanned) ADC measurement from the monitor. - self.i2c_devices - .power_monitor - .get_voltage(ads7924::Channel::Zero) - .unwrap() - }; + // Read the cached (scanned) ADC measurement from the monitor. + let p28v_rail_current_sense = self + .i2c_devices + .power_monitor + .get_voltage(ads7924::Channel::Zero) + .unwrap(); p28v_rail_current_sense * (100.0 / 0.100 / 4300.0) } @@ -1010,8 +1003,8 @@ impl RfChannel { let mut bias_voltage = -3.2; self.set_bias(bias_voltage).unwrap(); // Settle the bias - delay.delay_us(1000_u16); - let mut last_current = self.measure_p28v_current(true); + delay.delay_us(12000); + let mut last_current = self.get_p28v_current(); // First, increase the bias voltage until we overshoot the desired set current by a small // margin. @@ -1024,10 +1017,10 @@ impl RfChannel { } self.set_bias(bias_voltage).unwrap(); - delay.delay_us(1000_u16); + delay.delay_us(12000); // Re-measure the drain current. - let new_current = self.measure_p28v_current(true); + let new_current = self.get_p28v_current(); // Check that the LDO did not enter fold-back. When the LDO enters fold-back, the // current should begin to drop dramatically. For now, a 20mA threshold is used to @@ -1038,18 +1031,20 @@ impl RfChannel { last_current = new_current; } + let high_voltage = bias_voltage; + // Next, decrease the bias voltage until we drop back below the desired set point. while last_current > desired_current { // Decrease the bias voltage in 1mV steps to decrease the drain current marginally. bias_voltage = bias_voltage - 0.001; - if bias_voltage <= -3.2 { + if bias_voltage <= -3.2 || bias_voltage < high_voltage - 0.040 { return Err(Error::Invalid); } // Set the new bias and re-measure the drain current. self.set_bias(bias_voltage).unwrap(); - delay.delay_us(1000_u16); - last_current = self.measure_p28v_current(true); + delay.delay_us(12000); + last_current = self.get_p28v_current(); } // Note that we're returning the actual bias voltage as calculated by the DAC as opposed to