Skip to main content

NanoVNA / NanoVNA-H / NanoVNA-H4 driver for Python bench automation — ASCII shell over USB CDC

Project description

rf-bench-drivers-nanovna

Python driver for the NanoVNA family of low-cost vector network analyzers — the original edy555 NanoVNA, hugen79 NanoVNA-H / NanoVNA-H4, DiSlord NanoVNA-H4 builds, and the Deepelec NanoVNA-F (verified 2026-06-30 against an F-series HW2.3/HW3.1 running firmware 0.2.1).

Speaks the ASCII shell protocol over the on-board USB CDC serial port (no NanoVNA-Saver / nanovna-python dependency). Returns numpy arrays.

Status

🧪 First release. Verified against the user's NanoVNA-F: identify, setup_sweep, get_frequencies, get_s11, get_s21, get_trace_db, get_trace_phase, set_parameter, set_marker, is_correction_on, average_s_data, single_sweep, pause, resume, get_trace_db_at, refusal of S12/S22 and set_power(dbm). Calibration flow (cal_open/short/load/isoln/thru/done/save) is wired but has not been exercised end-to-end with the user's cal kit.

Not yet supported:

  • NanoVNA-V2 / S-A-A-2 (binary protocol — a different driver class).
  • LiteVNA / NanoVNA-F V2 (also binary protocol).

Supported hardware

Variant Protocol Tested?
NanoVNA (edy555 original) ASCII shell over CDC ✅ same protocol family
NanoVNA-H / H4 (hugen79) ASCII shell over CDC ✅ same protocol family
NanoVNA-H4 (DiSlord) ASCII shell over CDC (superset) ✅ extras via .raw()
NanoVNA-F (Deepelec) ASCII shell over CDC ✅ tested 2026-06-30
NanoVNA-V2 / S-A-A-2 binary protocol ❌ not supported
LiteVNA binary protocol ❌ not supported

Install

pip install rf-bench-drivers-nanovna

or development:

cd drivers/nanovna
pip install -e . --break-system-packages

Requires pyserial>=3.5 and numpy>=1.20.

Quick start

from rf_bench.nanovna import NanoVNA
import numpy as np

with NanoVNA("/dev/ttyACM1") as vna:        # autodetect: NanoVNA()
    print(vna.identify())
    vna.setup_sweep(start_hz=1e6, stop_hz=900e6, points=101)
    freqs, s11, s21 = vna.get_s_data_full() # all three at once
    print(f"S11 dB: {20*np.log10(np.abs(s11)+1e-30).min():.1f}")

Swappable API with HP 8712B

This driver implements the same core method names as rf_bench.hp.HP8712B, so projects can switch between them by changing only the construction call:

def run(vna):
    vna.setup_sweep(1e6, 900e6, points=101)
    vna.set_parameter("S11")
    vna.single_sweep()
    freqs = vna.get_frequencies()
    s_data = vna.get_s_data()
    db = vna.get_trace_db()
    phase = vna.get_trace_phase()
    return freqs, s_data, db, phase

# Works with either driver:
from rf_bench.nanovna import NanoVNA
from rf_bench.hp import HP8712B
run(NanoVNA())
run(HP8712B("10.1.1.70"))

Methods available on both drivers:

Method NanoVNA HP 8712B
identify() -> str
setup_sweep(start, stop, points)
set_parameter("S11" | "S21" | "S12" | "S22") ✅ (S11/S21 only)
get_parameter() -> str
set_format("MLOG" | "PHAS" | ...)
single_sweep() -> bool
pause() / resume() / hold() / continuous()
get_frequencies() -> ndarray
get_s_data() -> ndarray (complex) ✅ (selected param) ✅ (selected param)
get_trace_db() -> ndarray
get_trace_phase() -> ndarray
get_trace_db_at(freq_hz) -> float
get_s11() -> ndarray
get_s21() -> ndarray
set_marker(freq_hz, marker=1)
get_marker_value(marker=1) -> float
marker_off(marker=1)
correction_on() / correction_off() / cal_on() / cal_off()
is_correction_on() -> bool
average_s_data(n) -> ndarray
close() / context manager

Methods NanoVNA-only (HP raises AttributeError):

  • get_s_data_full() -> (freqs, s11, s21) — exploits the NanoVNA's simultaneous S11+S21 measurement (HP must re-sweep per parameter)
  • cal_reset/open/short/load/isoln/thru/done — SOLT walkthrough
  • save_cal(slot) / recall_cal(slot) — flash slots
  • iter_segments(start, stop, seg_points) — span > 401 points across segments
  • set_marker_index(marker, point_index) — direct index addressing
  • raw_power_index(0..3) — coarse hardware power index
  • raw(cmd) -> str — escape hatch to the shell

Methods HP-only (NanoVNA raises NotImplementedError):

  • set_power(dbm) — NanoVNA exposes only a coarse index (raw_power_index)
  • set_averaging(count) — NanoVNA firmware has no host-side averaging control; use average_s_data(n) for software averaging

S-parameter scope: NanoVNA hardware is forward-only (1.5-port VNA). set_parameter("S12") / set_parameter("S22") raise NotImplementedError. To measure S22 / S12 on a DUT, reverse it physically and re-measure as S11 / S21 from the new orientation.

Calibration

SOLT walkthrough for the standard 12-term error model:

with NanoVNA() as vna:
    vna.setup_sweep(1e6, 900e6, points=101)
    vna.cal_reset()
    input("Attach OPEN to port 0,  press Enter…"); vna.cal_open()
    input("Attach SHORT to port 0, press Enter…"); vna.cal_short()
    input("Attach LOAD  to port 0, press Enter…"); vna.cal_load()
    input("Attach LOAD  to port 1, press Enter…"); vna.cal_isoln()
    input("Connect THRU port 0→1,   press Enter…"); vna.cal_thru()
    vna.cal_done()
    vna.save_cal(0)            # save to flash slot 0

To recall later:

with NanoVNA() as vna:
    vna.setup_sweep(1e6, 900e6, points=101)
    vna.recall_cal(0)

Calibration applies only over the swept range it was measured at. Change the sweep, recalibrate.

Building & publishing

cd drivers/nanovna
python -m build
twine upload dist/* --skip-existing

License

GPL-3.0-or-later

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rf_bench_drivers_nanovna-0.1.0.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rf_bench_drivers_nanovna-0.1.0-py3-none-any.whl (27.8 kB view details)

Uploaded Python 3

File details

Details for the file rf_bench_drivers_nanovna-0.1.0.tar.gz.

File metadata

  • Download URL: rf_bench_drivers_nanovna-0.1.0.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for rf_bench_drivers_nanovna-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5cb7cd920d25c0948b6ed988341a1d9dfc6e2d0ca1bccc5ab60c42c9fcbccf48
MD5 2cb310507d4fa96ebcea639b305b4b6c
BLAKE2b-256 fdc6441efd0f0a9a9d30dfb947d56d33184fa6952ef3f32b155580c30466a5ff

See more details on using hashes here.

File details

Details for the file rf_bench_drivers_nanovna-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rf_bench_drivers_nanovna-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71e42f06a4a963897e70f3b0ac519a6a8e328b8c15313ea4455b3f71261b29c6
MD5 7c5fcf96fcb2b2d99f72902eef0b83a0
BLAKE2b-256 dfc22a9bf7ace0a83d17b7f97f1ab99cd8ed7b8d7cbbdf6de91b08fdbf65a291

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page