Skip to content

Commit

Permalink
ads7924: disable scan around read, don't use manual
Browse files Browse the repository at this point in the history
  • Loading branch information
jordens committed Oct 9, 2020
1 parent df89069 commit 74ad7d0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 44 deletions.
32 changes: 10 additions & 22 deletions ads7924/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ where

#[derive(Copy, Clone, PartialEq)]
#[doc(hidden)]
#[allow(dead_code)]
enum OperationMode {
Active = 0b100000,
ManualSingle = 0b110000,
Expand Down Expand Up @@ -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])?;
Expand Down Expand Up @@ -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<f32, Error> {
// 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)
}
}
39 changes: 17 additions & 22 deletions src/rf_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
//
Expand All @@ -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)
}
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 74ad7d0

Please sign in to comment.