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 walkthroughsave_cal(slot)/recall_cal(slot)— flash slotsiter_segments(start, stop, seg_points)— span > 401 points across segmentsset_marker_index(marker, point_index)— direct index addressingraw_power_index(0..3)— coarse hardware power indexraw(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; useaverage_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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cb7cd920d25c0948b6ed988341a1d9dfc6e2d0ca1bccc5ab60c42c9fcbccf48
|
|
| MD5 |
2cb310507d4fa96ebcea639b305b4b6c
|
|
| BLAKE2b-256 |
fdc6441efd0f0a9a9d30dfb947d56d33184fa6952ef3f32b155580c30466a5ff
|
File details
Details for the file rf_bench_drivers_nanovna-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rf_bench_drivers_nanovna-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71e42f06a4a963897e70f3b0ac519a6a8e328b8c15313ea4455b3f71261b29c6
|
|
| MD5 |
7c5fcf96fcb2b2d99f72902eef0b83a0
|
|
| BLAKE2b-256 |
dfc22a9bf7ace0a83d17b7f97f1ab99cd8ed7b8d7cbbdf6de91b08fdbf65a291
|