Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check threshold accuracy #97

Closed
jordens opened this issue Oct 13, 2020 · 21 comments
Closed

check threshold accuracy #97

jordens opened this issue Oct 13, 2020 · 21 comments

Comments

@jordens
Copy link
Member

jordens commented Oct 13, 2020

It seemed to me that while the power measurements are accurate, the thresholds are wrong (too sensitive). Need to gather some data on that.

@hartytp
Copy link

hartytp commented Dec 21, 2020

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.025e1,"p28v_current":7.057981e-2,"p5v_current":2.3447564e-1,"p5v_voltage":5.0323696e0,"input_power":-2.0138462e1,"reflected_power":1.1000009e0,"output_power":2.0505919e1,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":2.7995234e1,"bias_voltage":-1.4526123e0,"state":"Enabled"}

Increase input power by 1dB

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.05e1,"p28v_current":7.54541e-2,"p5v_current":2.3447564e-1,"p5v_voltage":5.0281773e0,"input_power":-1.9215385e1,"reflected_power":2.3000011e0,"output_power":2.1456856e1,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":2.7995234e1,"bias_voltage":-1.4526123e0,"state":"Enabled"}

another 1dB

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.025e1,"p28v_current":5.1472567e-2,"p5v_current":2.3461087e-1,"p5v_voltage":5.0323696e0,"input_power":-1.8015385e1,"reflected_power":-4.4285707e0,"output_power":-4.6218066e0,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":2.7995234e1,"bias_voltage":-1.4526123e0,"state":"Tripped(Output)"}

So the output power has tripped at <=22.5dBm despite the threshold being set at 28dBm. That's a pretty big error. The nominal detector slope after the OpAmp is 55mV/dB so 5.5dB is 300mV which is pretty large so probably not an analogue offset unless there is something really wrong.

image

Ideas @ryan-summers

@hartytp
Copy link

hartytp commented Dec 21, 2020

@ryan-summers this is the most critical issue for us since the interlock is a key part of Booster's functionality.

@hartytp
Copy link

hartytp commented Dec 22, 2020

The interlock DAC is an AD5627R (internal reference). Full-scale error is about 1% so 25mV, so way too low to explain this offset.

image

The [comparators] are also accurate to a handful of mV so we should certainly be sub-dB accurate in this part of the circuit.

@hartytp
Copy link

hartytp commented Dec 30, 2020

Per discussion with @jordens I'll review the relevant code at

booster/ad5627/src/lib.rs

Lines 105 to 128 in 1a8e9eb

pub fn set_voltage(&mut self, voltage: f32, dac: Dac) -> Result<f32, Error<I2C::Error>> {
// Assuming a 1.25V internal reference with a 2x output stage gain, our full scale range is
// 2.5V.
if voltage > 2.5 || voltage < 0.0 {
return Err(Error::Range);
}
// The DAC has a 12-bit DAC output. Full scale is 0xFFF.
let code = ((voltage / 2.5) * (0x1000 as f32)) as u16;
// Check that the DAC code has not overflown.
if code > 0xFFF {
return Err(Error::Range);
}
// The 12-bit code must be stored MSB-aligned.
let code = code << 4;
// Write the dac level to the output.
self.write(Command::WriteInput, dac, code.to_be_bytes())?;
let programmed_voltage = ((code >> 4) as f32) / (0x1000 as f32) * 2.5;
Ok(programmed_voltage)
}

// When operating at 100MHz, the power detectors specify the following output
// characteristics for -10 dBm to 10 dBm (the equation uses slightly different coefficients
// for different power levels and frequencies):
//
// dBm = V(Vout) / .035 V/dB - 35.6 dBm
//
// All of the power meters are preceded by attenuators which are incorporated in
// the offset.
output_power_transform: LinearTransformation::new(1.0 / 0.035, -35.6 + 19.8 + 10.0),
// The input power and reflected power detectors are then passed through an
// op-amp with gain 1.5x - this modifies the slope from 35mV/dB to 52.5mV/dB
reflected_power_transform: LinearTransformation::new(
1.0 / 1.5 / 0.035,
-35.6 + 19.8 + 10.0,
),
input_power_transform: LinearTransformation::new(1.0 / 1.5 / 0.035, -35.6 + 8.9),

booster/src/rf_channel.rs

Lines 896 to 940 in 862ce55

/// Get the current input power measurement.
///
/// # Returns
/// The input power in dBm.
pub fn get_input_power(&mut self) -> f32 {
let voltage = self.i2c_devices.input_power_adc.get_voltage().unwrap();
self.settings.data.input_power_transform.map(voltage)
}
/// Get the current reflected power measurement.
///
/// # Args
/// * `adc` - The ADC to use for performing the measurement.
///
/// # Returns
/// The reflected power in dBm.
pub fn get_reflected_power(&mut self, adc: &mut hal::adc::Adc<hal::stm32::ADC3>) -> f32 {
let sample = self
.pins
.adc_pins
.reflected_power
.convert(adc, SampleTime::Cycles_480);
let voltage = adc.sample_to_millivolts(sample) as f32 / 1000.0;
self.settings.data.reflected_power_transform.map(voltage)
}
/// Get the current output power measurement.
///
/// # Args
/// * `adc` - The ADC to use for performing the measurement.
///
/// # Returns
/// The output power in dBm.
pub fn get_output_power(&mut self, adc: &mut hal::adc::Adc<hal::stm32::ADC3>) -> f32 {
let sample = self
.pins
.adc_pins
.tx_power
.convert(adc, SampleTime::Cycles_480);
let voltage = adc.sample_to_millivolts(sample) as f32 / 1000.0;
self.settings.data.output_power_transform.map(voltage)
}

booster/src/main.rs

Lines 296 to 298 in 862ce55

let config = hal::adc::config::AdcConfig::default().reference_voltage(2500);
let adc = hal::adc::Adc::adc3(c.device.ADC3, true, config);

From a quick skim this all looks correct, but I'll have a careful look shortly.

@jordens
Copy link
Member Author

jordens commented Jan 4, 2021

n.b. this (top post) was after 8f0686f

@hartytp
Copy link

hartytp commented Jan 5, 2021

Using latest development branch commit. I'm driving Booster form a synth. Increasing the synth in 1dB steps and seeing where the interlock trips:

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.225e1,"p28v_current":1.1366858e-1,"p5v_current":2.3434043e-1,"p5v_voltage":5.0281773e0,"input_power":-1.416923e1,"reflected_power":8.985715e0,"output_power":2.6067446e1,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":3.2990227e1,"bias_voltage":-1.4526123e0,"state":"Enabled"}
booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.225e1,"p28v_current":4.8937935e-2,"p5v_current":2.3488131e-1,"p5v_voltage":5.0323696e0,"input_power":-1.2876923e1,"reflected_power":-4.5999994e0,"output_power":-4.4200935e0,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":3.2990227e1,"bias_voltage":-1.4526123e0,"state":"Tripped(Output)"}

Comments

  • the input power reading agrees with the synth setting (assuming 1.1dB of cable loss) and with an external power detector check
  • the output power agreed with a power detector check and is pretty consistent with the expected 40dB gain at this frequency (100MHz)
  • output is 50Ohm terminated via a 30dB power attenuator + external power detector (V3500A)
  • output threshold is set to 33dBm
  • it trips consistently at a power of ~27dBm as measured by both the internal / external power detector (6dB difference)
  • from the (correct AFAICT) formula above dBm = V(Vout) / .035 V/dB - 35.6 dBm we should have the following comparator voltage: V = (33 + 35.6) * .035 = 2.401V. 27dBm would correspond to a comparator voltage of 2.191V (a 200mV difference).

Given that the output detector calibration seems to be pretty (~0.5dB) accurate my guess is that the transforms + ADC parts of the code are all fine (and, indeed, they look correct)

@hartytp
Copy link

hartytp commented Jan 5, 2021

Relevant part of the circuit is
image

@hartytp
Copy link

hartytp commented Jan 5, 2021

The DAC accuracy should be 1% FS max so 25mV
image

@hartytp
Copy link

hartytp commented Jan 5, 2021

@jordens in terms of reviewing the code sections you referenced #97 (comment)

  • power transform (power <-> voltage mapping) specifically for the output detector: it looks correct based on my understanding of the parts and seems to give accurate agreement with the numbers I calibrated
  • the ADC config/conversion bit you posted looks correct in so far as there is a nominally 2.5V reference (but I haven't looked into the hal or understood what config the ADC needs to work accurately) and, again, seems to give good agreement with my calibration
  • the DAC code also looks about correct: it's a 1.25V internal reference with a x2 output gain for 2V5 nominal span (and powered from a 3V3 rail with plenty of headroom)

@ryan-summers strictly I guess this let code = ((voltage / 2.5) * (0x1000 as f32)) as u16; should be 4095 not 4096 but that won't make a practical difference.

@hartytp
Copy link

hartytp commented Jan 5, 2021

Out of curiosity, decreasing the output threshold by 10dB to +23dBm:

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.075e1,"p28v_current":5.8101613e-2,"p5v_current":2.3447564e-1,"p5v_voltage":5.0323696e0,"input_power":-2.3892307e1,"reflected_power":-2.1999993e0,"output_power":1.5981775e1,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":2.298265e1,"bias_voltage":-1.4526123e0,"state":"Enabled"}
booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.075e1,"p28v_current":5.2057482e-2,"p5v_current":2.3461087e-1,"p5v_voltage":5.0323696e0,"input_power":-2.3061539e1,"reflected_power":-4.471428e0,"output_power":-4.794704e0,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":2.298265e1,"bias_voltage":-1.4526123e0,"state":"Tripped(Output)"}

So this time it trips at an output power of +17dBm, which is again 6dB below the set-point. 23dBm corresponds to 2.051V while 17dBm is 1.84B

Reducing the threshold another 10dB to 13dBm, we get

booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.125e1,"p28v_current":5.2447427e-2,"p5v_current":2.3461087e-1,"p5v_voltage":5.0323696e0,"input_power":-2.7076923e1,"reflected_power":-4.471428e0,"output_power":5.8672895e0,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":1.2992659e1,"bias_voltage":-1.4526123e0,"state":"Enabled"}
booster0/ch0 {"reflected_overdrive":false,"output_overdrive":false,"alert":false,"temperature":3.1e1,"p28v_current":5.2057482e-2,"p5v_current":2.3461087e-1,"p5v_voltage":5.0323696e0,"input_power":-2.7061539e1,"reflected_power":-4.257142e0,"output_power":-4.996417e0,"reflected_overdrive_threshold":3.2992203e1,"output_overdrive_threshold":1.2992659e1,"bias_voltage":-1.4526123e0,"state":"Tripped(Output)"}

So it still trips at around 6dB below the set point (to within the measurement accuracy here)...

At 13dBm, the comparator set point voltage should be 1.701V.

One question: is this an offset-type effect or a gain-type effect? If it were a gain effect then we'd expect the error to be roughly 2.191V/2.401V which is roughly 10%.

At 13dBm set point, that would be 1.701*.9=1.552V. Translating back into dB that gives 8.75dBm as the expected tripping point. These measurements aren't accurate enough to 100% rule that out, but if I had to guess I'd say that the difference between set point and actual tripping point didn't change by that much.

@hartytp
Copy link

hartytp commented Jan 5, 2021

@ryan-summers do you have a Booster accessible? I think the next step is for someone to probe the DAC + comparator pins. Once we have that we should know where the issue is and whether it's hw or sw so we can decide on an appropriate remedy.

@ryan-summers
Copy link
Member

ryan-summers commented Jan 5, 2021

@ryan-summers do you have a Booster accessible?

Yes, I have one at my desk for development purposes.

I think the next step is for someone to probe the DAC + comparator pins. Once we have that we should know where the issue is and whether it's hw or sw so we can decide on an appropriate remedy.

The RF channel modules have safety seals on them, so probing internal signals is not possible without breaking the seal (which I have not yet done). cc @jordens

@hartytp
Copy link

hartytp commented Jan 5, 2021

okay, I've had a look. Measuring FR_VREF on the exposed connector pins on the supplemental control PCB.

set threshold | RF_VREF | expected
33dBm | 1.369 V | 1.371V
23dBm | 1.021V | 1.024V
13dBm | 0.675V | 0.677V

expected numbers here are based on this calibration: P(dBm) = V(V) * 28.816 V/dBm - 6.495 dBm

NB all of the maths I posted above was off by a constant voltage because I neglected the various coupler efficiencies etc. (i.e. I was referring to dBm at the detector, not dBm at the amp output). Not that it changes any conclusions, but it is a little confusing.

So it looks like this part of the code works / hw works well (no unexpected offsets/etc). Errors here are pretty negligible as expected. Which raises the question of why the circuit doesn't work...transients? comparator oscillations? time to reach for the scope

@hartytp
Copy link

hartytp commented Jan 5, 2021

Set the threshold to 33dBm to avoid tripping, set the RF output to 23dBm as measured by the internal detector. Measuring with a DMM: Vref =1.368, Vout=1.020

So the conclusion here is that there is not a firmware issue here.

So, I think the conclusion here has to be that either there is a hardware issue (comparator instabilities or whatever) or there are large transients on my signal source.

@hartytp
Copy link

hartytp commented Jan 5, 2021

Quick test for source transients:

  • using a 100MHz rigol scope (a little slower than I'd like but still way faster than the interlock) set scope to single shot
  • set to single shot mode
  • set trigger threshold to reliably trigger at -11dBm but not at -12dBm (powers as read out from display)
  • play around changing the amplitude for powers >=12dBm in different step sizes. Was not able to get a single trigger

At least for the powers I looked at there are no glitches that could explain this (recall that we're looking for 6dB so a factor of 2 in voltage which would stick out like a sore thumb)

@hartytp
Copy link

hartytp commented Jan 5, 2021

hmm...not quite:

  • P synth: -12dBm. This was chosen by finding the point where the interlock trips and backing off 1dB
  • Set interlock threshold: 33dBm
  • Vref (measured): 1.368V (measured on scope with ~5mV pk pk noise)
  • Vdet (measured): 1.132V
  • Output power measured by Booster: 26.1dBm

So the voltages all seem correct.

@hartytp
Copy link

hartytp commented Jan 5, 2021

Okay, this definitely seems like an odd hw issue. I'll post some photos tomorrow, but the short summary is this:

  • If I probe the detector voltage on the supplemental control board while toggling the synth between two powers I don't see any glitches (single shot it and move the threshold up by 100mV to be safe)
  • now change the interlock threshold so that it's ~6dB above the higher power and I now see a glitch on the detector voltage. That spike is what's causing the interlock to trigger. Other than that everything works exactly as expected.

The most likely explanation is some kind of oscillation involving the comparator. I'll close this issue now and open on on the hw thread.

@hartytp
Copy link

hartytp commented Jan 5, 2021

aargh, I don't have permission to close here.

@jordens
Copy link
Member Author

jordens commented Jan 5, 2021

Assuming it's a hw issue it seems out of scope here and probably should be done over at sinara-hw/booster.

@jordens jordens closed this as completed Jan 5, 2021
@jordens
Copy link
Member Author

jordens commented Jan 6, 2021

@ryan-summers strictly I guess this let code = ((voltage / 2.5) * (0x1000 as f32)) as u16; should be 4095 not 4096 but that won't make a practical difference.

No. It should be 0x1000 and 4095 is wrong (see datasheet). I haven't seen a ADC/DAC that behaves differently.

@hartytp
Copy link

hartytp commented Jan 6, 2021

No. It should be 0x1000 and 4095 is wrong (see datasheet). I haven't seen a ADC/DAC that behaves differently.

Yes, sorry, my mistake.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants