Skip to content
 
 

Latest commit

 

History

1,276 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NanoVNA - Very tiny handheld Vector Network Analyzer

About

NanoVNA-H and NanoVNA-H4 are very tiny handheld Vector Network Analyzers (VNA). They are standalone portable devices with LCD and battery. This project aims to provide improved firmware for this useful instrument for enthusiast.

This repository contains the source code of the improved NanoVNA-H and NanoVNA-H4 firmware.

The documentation describes the build and flash process on a MacOS or a Linux (Debian or Ubuntu) system, other Linux (or even BSD) systems may behave similar.

About this fork

This is StephenGenusa/NanoVNA-D, a fork of DiSlord/NanoVNA-D carrying fixes and features for open upstream issues. I am new to the NanoVNA and this is my experimental fork.

  • Ham band indicators with a region setting (DISPLAY→SCALE→HAM BANDS): band edges drawn on the frequency axis for IARU R1/R2/R3, USA, Canada, UK, Germany, Japan, or Australia (upstream #103/#104). On the H4 the bar is additionally colored by sub-band: CW (orange), narrow digital (blue), phone (green), per the IARU regional band plans.
  • SD folder browsing (two levels on the H4, e.g. CAL/HF/): folders show as /NAME in the file browser, .. goes up a level, the browser's NEW button creates a folder, and SAVE writes into the folder the browser last showed — browse into a folder, press X, then save; the save box shows the full path (manual chapter 7) (#76). Always on for the H4; opt-in for the H (__SD_BROWSER_FOLDERS__ in nanovna.h, one level, flash headroom).
  • SWR ANT trace format (DISPLAY→FORMAT→SWR ANT→SWR ANT) — the SWR at the far end of the feedline, de-embedded from the measured S11 using the one-way cable loss you enter in DISPLAY→FORMAT→SWR ANT→CABLE LOSS (dB, matched loss at the band in use; from the cable's data sheet or a MEASURE→CABLE run). Feedline loss attenuates the reflected wave twice, so a lossy coax always reads a better SWR than the antenna has: |Γ_ant| = |Γ_meas|·10^(L/10). Run SWR and SWR ANT as two traces to see the difference. The trace is blank and the marker reads set CABLE LOSS until a loss is entered; the value is not saved across power cycles because it is cable- and band-specific. Accuracy is set by how well you know L: ±0.2 dB moves a true 2:1 by ±0.07, a 3:1 by ±0.2, and a 10:1 by several units — the reading is reliable below about 5:1. Use a common-mode choke at the feedpoint; without one the coax shield is part of the antenna being measured. Console: trace 0 swrant.
  • Coax presets for SWR ANT (H4 only): DISPLAY→FORMAT→SWR ANT→CABLE TYPE cycles MANUAL / LMR‑400 / RG‑213 / RG‑8X / RG‑58 / RG‑174‑316; with a type selected and CABLE LENGTH (metres) entered, the loss is computed per sweep point from ARRL Antenna Book Vol. 3 Table 23.4 (interpolated on √f), so it follows band changes without re-entry; the CABLE LOSS button shows the value at sweep centre, and typing a loss there returns to MANUAL. The table is for new, dry, name-brand cable — old, wet or off-brand coax can be markedly worse; measure it (MEASURE→CABLE, antenna disconnected) when in doubt. Host test: gcc -Wall -Wextra -Werror -o /tmp/test_coax tests/test_coax.c -lm && /tmp/test_coax.
  • SWR BW measure (MEASURE→SWR BW (S11)) — bandwidth and Q of an SWR dip. Walks from the active marker to the nearest minimum (deepest dip in the sweep if no marker is active), reports f₀ and minimum SWR, the 2:1 and 3:1 edge frequencies and bandwidths (an edge outside the sweep is flagged, so widen the sweep), and the bandwidth quality factor Q. A narrow, deep dip is a high-Q, low-loss antenna; a broad, shallow one means something in the system is dissipating — loss makes an antenna easier to match, so a good SWR curve is not by itself a good antenna. Q follows Yaghjian & Best (fractional VSWR-s bandwidth = 2√β/Q, β = (s−1)²/4s), generalized to use the measured R at the dip rather than assuming a 50 Ω match, which makes it exact for a series-RLC dip at any minimum SWR; 2:1 and 3:1 give the same Q when the dip is RLC-like. Always on for the H4; opt-in for the H (__S11_SWR_BW_MEASURE__ in nanovna.h, ~1.4 KB, which consumes essentially all of the H's remaining flash). Host test: gcc -Wall -Wextra -Werror -o /tmp/test_swr_bw tests/test_swr_bw.c -lm && /tmp/test_swr_bw.
  • Workflows (experimental)
    • TUNE (S11) measure and a stored reference sweep (MEASURE→TUNE (S11); H4 only): a target-frequency workflow for trimming an antenna. Enter TARGET and, optionally, cycle ANTENNA (UNKNOWN / DIPOLE / VERTICAL / EFHW); the panel reports an ADD/REMOVE verdict and how much, from the antenna's own 468/f or 234/f model until something better is available. STORE REF saves the current sweep (also usable from MEASURE→RESONANCE (S11), which gets the same STORE REF / CLEAR REF / REPEAT CHECK and a reference Δf0 row); fold the wire rather than cut it, re-sweep, and enter what changed under WIRE CHANGE (metres, per leg on a dipole) — the verdict then switches to the antenna's own measured sensitivity, tagged [measured] (or [loaded?] when it implies a loading coil or trap: more than 3× the full-size Hz/m for that frequency). The reference is invalidated by value — sweep points, span, calibration status, or processing (S21 offset, electrical delay, smoothing) — so a stale comparison is always flagged (stale (points|span|cal|proc)), never silently wrong. REPEAT CHECK reports the sweep-to-sweep noise floor (max |ΔΓ| against the reference) in a message box, for judging whether a small measured change is real. See the on-device ant-tune-workflow guide (below) for the full fold-before-you-cut procedure and a calculated kHz/cm sensitivity table. Host test: python3 -m unittest tests.test_workflow.
    • CHOKE (S21) measure and a fixture null (MEASURE→MORE (S21)→CHOKE (S21); H4 only): a series-through per-band test for a common-mode choke, since reflection measurements are poor in the 1–10 kΩ range a good choke sits in. Build a jig with the choke in series between the ports, THRU-calibrate the span, pick a region under DISPLAY→SCALE→HAM BANDS, then sweep the jig OPEN and STORE FIXTURE before inserting the choke — every reading has that open sweep's admittance subtracted first, so the jig's own stray capacitance is not counted as choke resistance. Each band reports its worst-point series resistance R_S and a verdict (POOR / WEAK / MARGINAL / GOOD / MEETS / HIGH PWR against a typed target, 5 kΩ by default, 2 kΩ to 100 kΩ) — X is shown but never judged, since a choke's reactance can cancel other reactance in the common-mode circuit rather than help it, while R_S only ever adds loss. A JIG reading marks a band where the fixture, not the choke, is the limiting factor. The ohms printed on such a row are the jig's un-nulled ceiling, 1/(4πfC); the verdict itself is taken against a limit some twenty times higher, because de-embedding subtracts the jig's susceptance instead of enduring it and only the repeatability of the null (taken as 5 %) leaks back into R_S — which is what lets a clip-lead jig grade a multi-kΩ choke across the whole HF range instead of only the lowest bands. STORE REF keeps the corrected impedance of the worst band to compare across a rewind (REF: 20m R 3.90kΩ → 6.10kΩ), sharing its storage with TUNE/RESONANCE's reference but as a different, mutually invisible kind. See the on-device choke-measure and choke-recipe guides (below) for the fixture, pass criteria and turns tables.
  • On-device guides (SD CARD→LOAD→GUIDE, H4; opt-in for the H): the device shows short reference pages from the card's GUIDES folder — plain markdown with headings, emphasis and auto-laid-out tables, paged with the wheel or a tap. The repository's GUIDES/ pack has 29 of them: antenna tuning and radials, POTA/SOTA rules and field safety, the K9YC choke recipe and how to measure a choke with the S21 series-through formats, coax loss, SWR and formula cards, propagation, and the instrument's own formats, panels, commands and menus. Write your own with any editor; tools/manual/guide.py check tells you what the screen would clip and guide.py render shows each page pixel for pixel from your PC.
    GUIDES/ant-radials.md, page 2, as the NanoVNA-H4 draws it
  • PNG screenshots on the H4 (SD CARD→IMAGE FORMAT cycles BMP / TIFF / PNG): indexed 8-bit, compressed PNG that opens anywhere: a busy sweep screen is 24 KB as PNG against 307 KB as BMP and 55 KB as TIFF. BMP and TIFF are unchanged on both devices (the H keeps BMP / TIFF), and a saved configuration with TIFF selected keeps saving TIFF. LOAD SCREENSHOT lists all three types. The on-device viewer opens PNGs the device wrote; PNGs made on a PC generally use compression features it does not implement and are rejected with "Unsupported PNG".
  • .nvs accepted for command scripts alongside .cmd, which mail/AV filters block (#97).
  • *IDN? console command (SCPI-style identify) for VISA/pyvisa/LabVIEW use (#98).
  • ZERO marker search alongside MAXIMUM/MINIMUM — finds the trace value closest to zero, e.g. reactance zero crossings (#107).
  • Raw S21 phase corrected (hardware THRU polarity inversion undone in firmware, #81). Note: re-do your THRU calibration after flashing — thru data saved by older firmware carries the old sign and would show S21 phase off by 180°. Verified on two NanoVNA‑H4 units (raw S21 phase reads ≈180° on stock firmware, ≈0° with this fix; calibrated results are identical). The NanoVNA‑H has not been checked.
  • Optional output mute on pause (STIMULUS→MUTE OUTPUT ON PAUSE, default off): finishes the current scan, then disables the Si5351 outputs while paused (#50).
  • Touch double-tap filter — accidental rapid re-taps ignored (100 ms window, #109).
  • Consistent stored-file viewing: changing the stimulus while displaying an .s1p/.s2p loaded from SD resumes live sweep instead of desyncing axes and markers (#101).
  • Fix sweep hang after ~12 h uptime (32-bit system-time wrap, #110).
  • CLOCK_GEN build option for boards with an MS5351/SWC5351 clock chip (see Build below, #54).

Workflows (experimental)

A workflow is a MEASURE panel that turns a sweep into a verdict for one job, instead of leaving the numbers to be read off a trace: it tells you what to do next (add or remove wire, which band your choke is weakest on) and keeps a stored reference so the next sweep can be compared with the last one. Two exist so far, both on the NanoVNA‑H4 only:

  • TUNE (S11) — trim a wire antenna to a target frequency. Enter the target, read the ADD/REMOVE verdict, store a reference, fold some wire, re-sweep, enter the change, and the verdict switches from a textbook model to the antenna's own measured sensitivity.
  • CHOKE (S21) — grade a common-mode choke band by band from a series-through sweep, after nulling the test jig so its stray capacitance is not mistaken for choke resistance.

They are more involved than the other panels — the choke workflow needs a jig, a THRU calibration, a stored fixture sweep and a region setting before it prints a single verdict — and the manual (chapter 5) and the on-device guides walk through each step. They are also new and experimental: the arithmetic is host-tested and the code has been reviewed, but bench time on real antennas and chokes is still limited, and bug fixes should be expected. Treat a verdict as a well-informed suggestion, not an instruction: check that the numbers make physical sense before you cut wire or accept a choke, and if the panel and your own judgment disagree, trust your judgment and report the case.

User manual

Read it here: PDF · single-file HTML (both attached to the v1.2.58-sg release).

A manual written from the firmware source lives in docs/manual/: every menu, trace format, console command and status letter is taken from the code that implements it and footnoted to it, with the original NanoVNA guide's procedures checked against the code and reworded. Start at 00-front.md. Chapters: orientation (screen, status letters, wheel, touch), trace formats, calibration, markers, MEASURE panels, fork features, SD card, console commands, menu map with a mockup of every menu on both devices, and firmware update. GUIDES/ is a pack of 29 reference pages for the SD card — antenna tuning and radials, POTA/SOTA field rules and safety, choke recipe and measurement, coax loss, SWR and formula cards, the device's own formats and commands — that the H4 shows on screen via SD CARD → LOAD → GUIDE. They are plain markdown you can extend (manual chapter 7). Sweep screens in the chapters are rendered from modelled circuits by tools/manual/screen.py, which reproduces the firmware's drawing code pixel for pixel and is regression-tested against real H4 screenshots.

The menu map, console reference and trace-format table are generated by the scripts in tools/manual/ (make -C docs/manual all) and checked against the source by python3 -m unittest tests.test_manual_gen, so they cannot drift from the firmware. make -C docs/manual dist builds the PDF and HTML (pandoc + XeLaTeX).

References for the antenna-measurement features:

  • A. D. Yaghjian and S. R. Best, "Impedance, Bandwidth, and Q of Antennas," IEEE Trans. Antennas Propag., vol. 53, no. 4, pp. 1298–1324, Apr. 2005.
  • A. D. Yaghjian, "Fundamentals of Antenna Bandwidth and Quality Factor," arXiv:2501.03146 (2025), eq. 7, 12, 21 — open-access restatement of the above.
  • M. W. Maxwell, W2DU, Reflections III: Transmission Lines and Antennas, Appendix 6 — the SWR-through-line-loss relation used by SWR ANT (3:1 through 0.5 dB reads 2.61:1).
  • ARRL Antenna Book, Vol. 1, "Q of Antennas" — the 2:1 SWR bandwidth convention.
  • ARRL Antenna Book, Vol. 3, Table 23.4, "Cable Attenuation (dB per 100 feet)" — the coax preset figures (stored converted to dB per 100 m).

Prebuilt Firmware

binaries/ holds the current release builds with SHA-256 checksums:

binaries/NanoVNA-H_1.2.58-sg.bin    NanoVNA-H  (STM32F072)
binaries/NanoVNA-H4_1.2.58-sg.bin   NanoVNA-H4 (STM32F303)

.hex versions are alongside for tools that want them. Flash the .bin with dfu-util at 0x08000000 (see Flash Firmware below, or ./2_prog.sh). Releases on GitHub carry the same files as assets. Re-do calibration after flashing (see the S21 note above).

Prepare ARM Cross Tools

UPDATE: Recent gcc version works to build NanoVNA, no need to use old version.

MacOSX

Install cross tools and firmware updating tool.

brew tap px4/px4
brew install gcc-arm-none-eabi-80
brew install dfu-util

Linux (ubuntu)

Download arm cross tools from here.

wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2018q4/gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2
sudo tar xfj gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2 -C /usr/local
PATH=/usr/local/gcc-arm-none-eabi-8-2018-q4-major/bin:$PATH
sudo apt install -y dfu-util

Debian

sudo apt install gcc-arm-none-eabi
sudo apt install -y dfu-util

Fetch Source Code

Do this once to initialize your local clone from GitHub (ChibiOS and FatFS are vendored in-tree — no submodules to fetch):

git clone https://github.com/StephenGenusa/NanoVNA-D.git
cd NanoVNA-D

Update Source Code

To get updates from the GitHub repository, go to your NanoVNA-D directory and type:

git pull

Build the NanoVNA-H Firmware

Go to your NanoVNA-D directory and type:

export TARGET=F072
make clean
make

Build the NanoVNA-H4 Firmware

Go to your NanoVNA-D directory and type:

export TARGET=F303
make clean
make

For boards populated with an MS5351 or SWC5351 clock generator (e.g. HW version 4.3_MS), bake in the matching default (also switchable at runtime via CONFIG→MODE):

make TARGET=F303 CLOCK_GEN=MS5351

Helper Scripts

Three scripts in the repository root wrap the common workflow:

./0_backup_firmware.sh   # back up the attached device's flash over DFU
./1_build.sh             # clean build -> build/H4.bin or build/H.bin  (default F303; or pass F072)
./2_prog.sh              # flash the built firmware via dfu-util

The two DFU scripts detect which device is attached from the flash layout the STM32 bootloader reports (detect_target.sh: 64 × 2 KB pages = H, 128 × 2 KB = H4) and act on that; with no device in DFU mode they stop and say so rather than assume. You can still pass F072 or F303 explicitly — 2_prog.sh then refuses if the attached device is the other one, so the wrong image cannot be written by mistake. 1_build.sh adds the ARM toolchain to PATH itself if it finds one under /usr/local or /opt.

Flash Firmware

When the build of your firmware is finished, you can flash it onto your NanoVNA device. First, let the device enter DFU mode by one of following methods.

  • Open the device and jumper BOOT0 pin to Vdd pin when powering the device.
  • Select menu Config->DFU (needs recent firmware).
  • Press the jog switch on your -H4 when powering the device.

Then, flash the firmware using dfu-util via USB.

For NanoVNA-H:

Go to your NanoVNA-D directory and type:

dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D build/H.bin

For NanoVNA-H4:

Go to your NanoVNA-D directory and type:

dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D build/H4.bin

Or simply type directly after building the firmware (for both variants).

Go to your NanoVNA-D directory and type:

make flash

Ignore the apparent error message during flashing

The low-level tool dfu-util displays a lot of information that is very useful especially for developers, but can confuse the user. In particular, please ignore the message about corrupt firmware, this is the normal behaviour of the unit before clearing the status. It is important to note that after clearing the status, there is no longer an error condition present.

...
Determining device status...
DFU state(10) = dfuERROR, status(10) = Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations
Clearing status
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
...

Companion Tools

There are several numbers of great companion PC tools from third-party.

Documentation

Reference

Note

Hardware design material is disclosed to prevent bad quality clone. Please let me know if you would have your own unit.

Credit

Based on code from:

Contributors

About

Firmware for NanoVNA, NanoVNA-H, NanoVNA-H4. Support SD Card, external Serial connection, fast measure, fast exchange vs CPU

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages