nanovna-v2 / NanoVNA2-firmware

Firmware for NanoVNA V2
https://nanorfe.com/nanovna-v2.html
215 stars 85 forks source link

Group Delay Calculation Does Not Unwrap Phase #76

Open roseengineering opened 3 years ago

roseengineering commented 3 years ago

https://github.com/nanovna-v2/NanoVNA2-firmware/blob/097bc9037183c47389621cdeddfc8f37e8ff2c59/plot.cpp#L435

https://github.com/ttrftech/NanoVNA/blob/d02db797a7032822137882f8f8a6c4ec21f064cd/plot.c#L449

To properly calculate the group delay, -dphi / (2 pi df), the phase must be "unwrapped". Otherwise for large phase shifts (<180 deg) across measurement points, the group delay calculation will be in error. For a non-dispersive DUT like a coaxial cable, high accuracy group delay measurements require such a large frequency "aperture". A df of .3 / delay is recommended. Unfortunately because of this issue my measurements were wrong.
See https://twitter.com/gmagiros/status/1396204275089477636?s=20

This issue also exists in the nanovna and nanovna-saver code.

The python code below demonstrates two ways to calculate group delay.

My method:

for n in range(1, len(ph)):
    dphi = ph[n] - ph[n-1]
    if dphi <= -np.pi: dphi += 2 * np.pi
    if dphi >= np.pi: dphi -= 2 * np.pi
    df = f[n] - f[n-1]
    g[n][0] = -dphi / (2 * np.pi * df)

Or using the scikit-rf method:

for n in range(1, len(ph)):
    while ph[n] - ph[n-1] < -np.pi: ph[n] += 2 * np.pi
    while ph[n] - ph[n-1] >= np.pi: ph[n] -= 2 * np.pi

for n in range(0, len(ph)):
    n1 = max(n - 1, 0)
    n2 = min(n + 1, len(ph) - 1)
    dphi = ph[n2] - ph[n1]
    df = f[n2] - f[n1]
    g[n][0] = -dphi / (df * 2 * np.pi)