Open hartytp opened 3 years ago
Note to self: the term "transforms" is not intuitively obvious to me. AFAICT it refers to the linear-in-dB mapping from input/output power in dBm (x) to detector reading in V (or LSB?) (y). We thus have y=ax+b
.
Since the firmware does not expose the detector voltage to the user (wouldn't it be useful to expose this?), only the inferred powers, we need to begin by reading out the current values of the coefficients a
and b
, from which we can back out the detector voltage. Solving, we find that if input/output powers x0
and x1
are applied, resulting in the firmware reading out powers of p0
and p1
, the new coefficients a_f
and b_f
are related to the old coefficients a_i
and b_i
by: a_f = a_i *(p0-p1)/(x0-x1)
and similarly for the b
coefficients (offsets).
AFACIT, the calibration tool doesn't currently do any of that maths for the user. If a new "transform" (consisting of a slope + offset in units of V/dBm and V respectively?) is not specified, it prints out the current coefficients, otherwise it writes new ones.
This is all sufficiently non-obvious that it needs proper documentation. However, it might be easier to make the tool itself a little more user-friendly (e.g. take in x0, P0 and x1, P1 instead).
We should also make recommendations for sensible values of x0 and x1 (and should ask TS/CTI to use those same values for consistency).
NB the expression I get for the slope looks non-equivalent to the one @jordens posted here but I may just be misunderstanding his terminology (or making a silly maths slip...) Either way, it will hopefully become obvious once I run the cal.
For completeness I have:
y0 = aP0 + b = a`x0+b`
y1 = aP1 + b = a`x1 + b`
aP0 + b - a`x0 = b = aP1 + b - a`x1
(aP0 + b) - (aP1 + b) = a`(x0-x1)
a` = a(P0-P1)/(x0-x1)
For the offset I get
y0 = aP0 + b = a`x0+b`
y1 = aP1 + b = a`x1 + b`
(aP0+b-b')/x0 = a' = (aP1+b-b')/x1
x1*(aP0+b-b') = x0*(aP1+b-b')
x1*(aP0+b) - x1b' = x0*(aP1+b)-x0*b'
a*(x0*P1 - x1*P0) + b*(x0-x1) = b'*(x0-x1)
a*(x0*P1 - x1*P0)/(x0-x1) + b = b'
The defaults seem to be:
Channel 7: InputPowerTransform slope = 42.857143, offset = -26.699999
Channel 0: OutputPowerTransform slope = 28.571428, offset = -5.799999
Channel 0: ReflectedPowerTransform slope = 42.857143, offset = -5.799999
Where did these come from? Were they calculated on the basis of nominal circuit values to give something sensible?
What's the recommended procedure for calibrating the reflected power. IIRC we're really not aiming for something accurate here so just a rough calibration for safety purposes. Are the default values expected to be good enough for that?
Let's have a go then...
input power is -20dBm (-18.9dBm on a synth at 100MHz, expect ~+20dBm output given the 40dB gain) gives: input_power:-1.0368036e1
, output_power = 2.1114285e1
. Measured output power is -9.35dBm + 30dBm = +20.65dBm (G=40.65dB)
input power is -10dBm (-8.9dBm synth) gives: input_power:1.207546e1
,output_power:3.0285713e1
. Measured output power is -0.11dBm + 30dBm = +29.9dBm (G=39.9dB)
Looks like the default for the output power is pretty sensible but the input is quite far off.
For ~1W output, the reflected power is coming out as reflected_power:1.5542858e1
(i.e. +15dBm) so ~-30dBc output. That's not obviously implausible...
Edit: this is just a sanity check on the default (uncalibrated) value being something sensible.
Okay, the equations I posted above give garbage, but the ones @jordens posted in that issue seem to give sensible results, so I guess I haven't understood how these transforms are intended to functions. Nonetheless, I think I can now get on with calibrating the device.
NB
Channel 0: InputPowerTransform slope = 19.09557361295228, offset = -27.276924682322218
compared with the default of Channel 0: InputPowerTransform slope = 42.857143, offset = -26.699999
. Might be worth looking at the default value for the input detector slope.Here is the hacky code I used to calculate the calibration data to save. NB I didn't bother with the reflected power yet. Hopefully the default values will be accurate enough for my purposes (the output detector looked pretty good without calibration on the one channel I looked at); next time I'm testing Booster I'll use a 3dB attenuator or so to create some VSWR to check.
# Input power
old_slope = 42.857143 # V/dB?
old_offset = -26.699999 # V?
x0 = -20 # dBm
x1 = -10 # dBm
p0 = -2.0046154e1
p1 = -9.753845e0
new_slope = old_slope*(x0 - x1)/(p0 - p1)
new_offset = (x0 + x1 - new_slope/old_slope*(p0 + p1 - 2*old_offset))/2
print("input power:", new_slope, new_offset)
# Output power
old_slope = 28.571428 # V/dB?
old_offset = -5.799999 # V?
x0 = +20.65 # dBm
x1 = +29.9 # dBm
p0 = 2.1114285e1
p1 = 3.0285713e1
new_slope = old_slope*(x0 - x1)/(p0 - p1)
new_offset = (x0 + x1 - new_slope/old_slope*(p0 + p1 - 2*old_offset))/2
print("output power:", new_slope, new_offset)
Channel 0: OutputPowerTransform slope = 28.571428, offset = -5.799999
So the expected transformation is: P_out[dBm] = 28.6dBm/V * V_adc - 5.8dB
.
My calibration gave: P_out = 28.8dBm/V * V_adc -6.494859775380661dB
. So, by way of example. if we actually have P_out=33dBm
then V_adc = (33dBm + 6.5dB)/28.8dBm/V=1.37V
. The nominal calibration would then give 33.4dBm
so within 0.5dB. That feels well within spec for the various parts.
For the input, the nominal is P_in[dBm] = 42.857143 dBm/V * V_adc - 26.699999 dB
@ryan-summers is there an operator precedence issue here? We want 1/(1.5*0.035V/dB) = 19dB/V
but we seem to be getting 42.86dB/V = 1.5/0.035V/dBm
.
Nope, not that, just an out of date release... https://github.com/quartiq/booster/blob/df89069a61faa4c8e78a248ec4fd217bd9995606/src/settings/channel_settings.rs#L46
@ryan-summers please do flag if releases are way out of date before I spend time debugging issues....
This may also explain the issue I saw with the interlock thresholds.
Summary AFAICT: Setting and getting the transforms is documented as are the transforms themselves. Computing new calibrated transforms for the user or aiding them in choosing test values isn't.
Summary AFAICT: Setting and getting the transforms is documented as are the transforms themselves
Where are the transforms documented? Do you mean the inline comments, or did I miss something?
Computing new calibrated transforms for the user or aiding them in choosing test values isn't.
Yep.
The help of booster_calibrate_power.py
and the API in booster.py
. We should add the actual transform expression power_dbm = slope*input_volt + offset
to that help string.
Computing new calibrated transforms for the user or aiding them in choosing test values isn't.
Yep.
To be clear: I don't consider that critical. But as always PRs welcome.
To be clear: I don't consider that critical. But as always PRs welcome.
Nope, not that, just an out of date release...
@ryan-summers please do flag if releases are way out of date before I spend time debugging issues....
Sorry for this - that was one of the few bugs that was patched after v0.1.0 was generated and has not yet made it into a new release. You can view the changelog from the current mainline to a release by clicking on the "X commits to develop
since this release" under the Releases page: https://github.com/quartiq/booster/releases
Unfortunately, this change appears to be listed at the very bottom of the change set.
Don't worry about it. Rust makes building from source so easy that I should probably have just built my own binary rather than using the release anyway.
@hartytp Hi, I appreciate that you shared your notes on the calibration procedures.
I noted that you did not calibrate the reflected power transform. If my understanding is right, when we apply some high-power 50 ohm load plus a short cable at the output, in practice there should still be power reflected back to the transmitter, but the amount should be at minimal.
If we remove the load and cable, using the uncalibrated reflected power readings before and after unplugging the load, can we actually infer the calibrated reflected power with open-circuit load, without the need to probe the output at all? I am taking that forward_power = reflected_power + output_power
with closed-circuit load, and forward_power = reflected_power
with open-circuit load.
Or alternatively, can we still consider the calibration valid if we assume output_power
in presence of the 50 ohm load (and probe) equals reflected_power
in open-circuit? In that case, we can simply unplug everything from the RF output, and then take the uncalibrated reflected power readings (as x0
, x1
), and plug the target output power value (p0
, `p1) in the equations to find the new slope and offset.
In any case, I get that the output has better not be probed without a high-power load.
No, sorry I made a wrong statement. The output_power
value actually corresponds to the forward power (as the ADL5904 RF detector takes the RF signal from the "CPL F" pin of the SYDC-20-62HP+ coupler and reports its Vrms level).
So, when we probe the output with a dummy load and take the measurement as output_power
, we have already assumed reflected_power = 0
, and thus the forward power equals the measured output_power
. When we disconnect everything from the output SMA, all the forward power is reflected, so we can use the output_power
value as reflected_power
and recalculate the reflected power transform. In the end, we should expect that, given open-circuit load, the calibrated output_power
should be equal or close to the calibrated reflected_power
.
If there's some flaw in my logic, I'm all ears. Thanks!
So, when we probe the output with a dummy load and take the measurement as output_power, we have already assumed reflected_power = 0, and thus the forward power equals the measured output_power. When we disconnect everything from the output SMA, all the forward power is reflected, so we can use the output_power value as reflected_power and recalculate the reflected power transform. In the end, we should expect that, given open-circuit load, the calibrated output_power should be equal or close to the calibrated reflected_power.
Roughly.
This is all from memory and I haven't played with Booster for a while so I might be wrong (others should feel free to comment), but IIRC...
The calibration script doesn't have enough documentation to be used as is. I think I can figure it out from the issues (see conversation from https://github.com/quartiq/booster/issues/104#issuecomment-747569176) but a few sentences to describe the process would make life much easier.