Calibration Interpolation
Calibration is performed at specific frequency points, but you might want to measure at different frequencies later. The NanoVNA-H firmware uses linear interpolation to estimate calibration data between stored points, allowing you to change your sweep range without full recalibration.
When Interpolation is Used
Section titled “When Interpolation is Used”The firmware sets the interpolation flag when your current sweep does not exactly match the calibration:
static bool needInterpolate(freq_t start, freq_t stop, uint16_t points) { return start != cal_frequency0 || stop != cal_frequency1 || points != cal_sweep_points;}Interpolation is triggered when any of these differ from calibration:
- Start frequency
- Stop frequency
- Number of sweep points
The Interpolation Algorithm
Section titled “The Interpolation Algorithm”For each measurement frequency, the firmware finds the two nearest calibration points and linearly interpolates between them.
Step 1: Locate Position
Section titled “Step 1: Locate Position”Given a measurement frequency f, find where it falls in the calibration range:
static void cal_interpolate(int idx, freq_t f, float data[CAL_TYPE_COUNT][2]) { int eterm; uint16_t src_points = cal_sweep_points - 1;
// Direct copy if index provided (no interpolation needed) if (idx >= 0) goto copy_point;
// Boundary cases: use first or last point if (f <= cal_frequency0) { idx = 0; goto copy_point; } if (f >= cal_frequency1) { idx = src_points; goto copy_point; }Step 2: Calculate Interpolation Factor
Section titled “Step 2: Calculate Interpolation Factor”The firmware calculates which calibration points bracket the measurement frequency and the interpolation factor k:
// Calculate position in calibration span freq_t span = cal_frequency1 - cal_frequency0; idx = (uint64_t)(f - cal_frequency0) * (uint64_t)src_points / span;
// Calculate exact frequencies of bracketing calibration points uint64_t v = (uint64_t)span * idx + src_points/2; freq_t src_f0 = cal_frequency0 + (v ) / src_points; freq_t src_f1 = cal_frequency0 + (v + span) / src_points;
freq_t delta = src_f1 - src_f0;
// If exactly on a calibration point, no interpolation needed if (f == src_f0) goto copy_point;
// Calculate interpolation factor (0.0 to 1.0) float k = (delta == 0) ? 0.0f : (float)(f - src_f0) / delta;Step 3: Handle Harmonic Boundaries
Section titled “Step 3: Handle Harmonic Boundaries”A critical detail: the NanoVNA switches between direct output and harmonic modes at certain frequencies. Interpolating across this boundary causes errors because the error terms change discontinuously.
// Avoid glitch between frequencies in different harmonic modes uint32_t hf0 = si5351_get_harmonic_lvl(src_f0); if (hf0 != si5351_get_harmonic_lvl(src_f1)) { // f is in prev harmonic, need extrapolate from prev 2 points if (hf0 == si5351_get_harmonic_lvl(f)) { if (idx < 1) goto copy_point; // Use two points from same harmonic region // ... extrapolation code ... } // f is in next harmonic, extrapolate from next 2 points else { if (idx >= src_points - 1) goto copy_point; // ... extrapolation code ... } }Step 4: Perform Interpolation
Section titled “Step 4: Perform Interpolation”Finally, linear interpolation is applied to each error term:
// Linear interpolation for each error term for (eterm = 0; eterm < CAL_TYPE_COUNT; eterm++) { // Get calibration values at bracketing points float r0 = cal_data[eterm][idx][0]; // Real part at point idx float i0 = cal_data[eterm][idx][1]; // Imag part at point idx float r1 = cal_data[eterm][idx+1][0]; // Real part at point idx+1 float i1 = cal_data[eterm][idx+1][1]; // Imag part at point idx+1
// Interpolate: value = v0 + k * (v1 - v0) data[eterm][0] = r0 + k * (r1 - r0); data[eterm][1] = i0 + k * (i1 - i0); }Interpolation Accuracy
Section titled “Interpolation Accuracy”Linear interpolation introduces error, especially where calibration data changes rapidly.
Best Case: Smooth Calibration Data
Section titled “Best Case: Smooth Calibration Data”When error terms vary smoothly with frequency (typical at HF):
- Interpolation error is small
- Even 10:1 interpolation ratios work well
- Results nearly as good as direct calibration
Worst Case: Rapidly Changing Data
Section titled “Worst Case: Rapidly Changing Data”When error terms change quickly (near resonances, harmonic transitions):
- Interpolation error can be significant
- Points near transitions may be inaccurate
- Consider recalibrating for critical measurements
Quantifying the Error
Section titled “Quantifying the Error”For linear interpolation, the maximum error depends on the second derivative of the calibration data:
Error_max <= (delta_f)^2 / 8 * |d^2(cal_data)/df^2|In practice:
- At HF (< 30 MHz): Negligible error
- At VHF (30-300 MHz): Small error
- Near 290 MHz boundary: Potentially significant error
- At UHF (> 300 MHz): Moderate error, especially if few cal points
Optimization: Direct Index
Section titled “Optimization: Direct Index”When your sweep exactly matches calibration, the firmware skips interpolation entirely by passing the point index directly:
// In sweep loopinterpolation_idx = mask & SWEEP_USE_INTERPOLATION ? -1 : p_sweep;
// Laterif (mask & SWEEP_APPLY_CALIBRATION) cal_interpolate(interpolation_idx, frequency, c_data);If interpolation_idx >= 0, the function directly copies calibration data without any calculation:
copy_point: for (eterm = 0; eterm < CAL_TYPE_COUNT; eterm++) { data[eterm][0] = cal_data[eterm][idx][0]; data[eterm][1] = cal_data[eterm][idx][1]; }Best Practices
Section titled “Best Practices”For Maximum Accuracy
Section titled “For Maximum Accuracy”- Calibrate at your measurement frequencies: Match start, stop, and points exactly
- Use more calibration points: More points means shorter interpolation distances
- Avoid sweeping across 290 MHz: Or calibrate specifically for that range
For Convenience
Section titled “For Convenience”- Calibrate wide, measure narrow: Calibrate 50 kHz to 900 MHz, then zoom in as needed
- Accept interpolation at HF: The error is usually negligible
- Recalibrate for critical UHF work: Especially near the harmonic threshold
Summary
Section titled “Summary”| Condition | Interpolation | Accuracy |
|---|---|---|
| Sweep matches calibration | None needed | Best |
| Sweep subset of calibration | Linear interpolation | Very good |
| Sweep wider than calibration | Edge extrapolation | Degraded at edges |
| Sweep crosses harmonic boundary | Special handling | Acceptable |
| Very few calibration points | Long-range interpolation | May be poor |
Next Steps
Section titled “Next Steps”Now that you understand calibration, explore the Architecture section to see how the hardware implements these measurements.