USB Protocol Reference
Technical reference for communicating with NanoVNA-H over USB. Use this guide to build PC applications, automation scripts, or understand the device interface.
USB Device Identification
Section titled “USB Device Identification”Device Descriptor
Section titled “Device Descriptor”| Field | Value | Description |
|---|---|---|
| idVendor | 0x0483 | STMicroelectronics |
| idProduct | 0x5740 | Virtual COM Port |
| bcdUSB | 0x0110 | USB 1.1 |
| bcdDevice | 0x0200 | Device version 2.00 |
| bMaxPacketSize0 | 64 | Control endpoint packet size |
String Descriptors
Section titled “String Descriptors”| Index | String | Notes |
|---|---|---|
| 1 | nanovna.com | Manufacturer |
| 2 | NanoVNA-H or NanoVNA-H4 | Product (target-dependent) |
| 3 | xyz or unique ID | Serial number |
USB Descriptor Layout
Section titled “USB Descriptor Layout”NanoVNA-H implements the CDC ACM (Communications Device Class - Abstract Control Model) profile.
Configuration Descriptor
Section titled “Configuration Descriptor”Configuration Descriptor (67 bytes)├── Interface 0: CDC Control (Communications Class)│ ├── Header Functional Descriptor│ ├── Call Management Functional Descriptor│ ├── ACM Functional Descriptor│ ├── Union Functional Descriptor│ └── Endpoint 2 IN: Interrupt (8 bytes, interval 255ms)│└── Interface 1: CDC Data (Data Class) ├── Endpoint 1 OUT: Bulk (64 bytes) └── Endpoint 1 IN: Bulk (64 bytes)Endpoints
Section titled “Endpoints”| Endpoint | Direction | Type | Size | Purpose |
|---|---|---|---|---|
| EP1 | OUT | Bulk | 64 bytes | Commands from host |
| EP1 | IN | Bulk | 64 bytes | Responses to host |
| EP2 | IN | Interrupt | 8 bytes | CDC notifications |
Connection Methods
Section titled “Connection Methods”Device path: /dev/ttyACM0 (may increment if multiple devices)
# Using screenscreen /dev/ttyACM0
# Using minicomminicom -D /dev/ttyACM0
# Using Pythonpython -c "import serial; s=serial.Serial('/dev/ttyACM0'); print(s.read_until(b'ch> '))"Permissions: Add user to dialout group:
sudo usermod -aG dialout $USER# Log out and back inDevice path: /dev/tty.usbmodem* (exact suffix varies)
# Find devicels /dev/tty.usbmodem*
# Using screenscreen /dev/tty.usbmodem0001
# Using Pythonpython -c "import serial; s=serial.Serial('/dev/tty.usbmodem0001'); print(s.read_until(b'ch> '))"Device path: COMx (check Device Manager)
Tools:
- PuTTY (Serial mode, select COM port)
- Tera Term (Serial connection)
- Python with pyserial
import serials = serial.Serial('COM3')print(s.read_until(b'ch> '))Driver: Windows 10+ includes CDC ACM driver. Older versions may need STM32 Virtual COM Port Driver.
Shell Protocol
Section titled “Shell Protocol”Protocol Parameters
Section titled “Protocol Parameters”| Parameter | Value |
|---|---|
| Prompt | ch> |
| Line terminator | \r\n (CRLF) |
| Max line length | 64 characters |
| Max arguments | 4 |
| Baud rate | N/A (USB is packet-based) |
Command Format
Section titled “Command Format”command [arg1] [arg2] [arg3] [arg4]\r\nArguments are space-separated. Command names are case-sensitive.
Frequency Arguments
Section titled “Frequency Arguments”Frequencies can use multiplier suffixes:
| Suffix | Multiplier | Example | Value |
|---|---|---|---|
| (none) | 1 | 1000000 | 1 MHz |
k | 1,000 | 1000k | 1 MHz |
M | 1,000,000 | 1M | 1 MHz |
G | 1,000,000,000 | 1.5G | 1.5 GHz |
Example Session
Section titled “Example Session”ch> infoBoard: NanoVNA-H2019-2025 Copyright NanoVNA.comVersion: 1.2.44
ch> sweep 1M 100M 101ch> scan 71000000 0.001234 0.005678 0.000123 -0.0004562000000 0.001245 0.005689 0.000134 -0.000467...ch>Data Output Modes
Section titled “Data Output Modes”Text Mode (Default)
Section titled “Text Mode (Default)”ASCII output with space-separated floating-point values:
[frequency] [S11_re S11_im] [S21_re S21_im]\r\nExample:
1000000 0.998234 -0.023456 0.001234 0.0056782000000 0.997123 -0.024567 0.001345 0.005789- Values are IEEE 754 single-precision floats formatted as ASCII decimal
- Each line terminated with
\r\n - Fields separated by single space
Binary Mode
Section titled “Binary Mode”Enabled by setting bit 7 (SCAN_MASK_BINARY) in the scan mask.
Header:
uint16_t mask; // Output mask (same as argument)uint16_t points; // Number of sweep pointsPer-point data (based on mask bits):
// if SCAN_MASK_OUT_FREQ (bit 0):uint32_t frequency; // 4 bytes, little-endian
// if SCAN_MASK_OUT_DATA0 (bit 1):float s11_re; // 4 bytes, IEEE 754 LEfloat s11_im; // 4 bytes, IEEE 754 LE
// if SCAN_MASK_OUT_DATA1 (bit 2):float s21_re; // 4 bytes, IEEE 754 LEfloat s21_im; // 4 bytes, IEEE 754 LEScan Mask Bitmask
Section titled “Scan Mask Bitmask”The scan command accepts a bitmask argument controlling output:
| Bit | Mask | Name | Description |
|---|---|---|---|
| 0 | 0x01 | SCAN_MASK_OUT_FREQ | Include frequency in output |
| 1 | 0x02 | SCAN_MASK_OUT_DATA0 | Include S11 (CH0) data |
| 2 | 0x04 | SCAN_MASK_OUT_DATA1 | Include S21 (CH1) data |
| 3 | 0x08 | SCAN_MASK_NO_CALIBRATION | Skip calibration correction |
| 4 | 0x10 | SCAN_MASK_NO_EDELAY | Skip electrical delay |
| 5 | 0x20 | SCAN_MASK_NO_S21OFFS | Skip S21 offset |
| 7 | 0x80 | SCAN_MASK_BINARY | Binary output mode |
Common Mask Values
Section titled “Common Mask Values”| Mask | Hex | Output |
|---|---|---|
3 | 0x03 | Freq + S11 (text) |
7 | 0x07 | Freq + S11 + S21 (text) |
135 | 0x87 | Freq + S11 + S21 (binary) |
15 | 0x0F | Freq + S11 + S21, no cal (text) |
Scan Command Examples
Section titled “Scan Command Examples”# Freq + S11 only (text)scan 3
# Freq + S11 + S21 (text, most common)scan 7
# Freq + S11 + S21 (binary, for programmatic use)scan 135
# S11 + S21 without cal correction (raw ADC values)scan 15
# Custom range: 1 MHz to 100 MHz, 201 points, output S11 onlyscan 1M 100M 201 3Binary Protocol Data Structures
Section titled “Binary Protocol Data Structures”Scan Binary Output
Section titled “Scan Binary Output”┌──────────────────────────────────────────────────────────────┐│ Header (4 bytes) │├─────────────────┬────────────────────────────────────────────┤│ mask (uint16) │ points (uint16) │├─────────────────┴────────────────────────────────────────────┤│ Point 0 Data │├──────────────────────────────────────────────────────────────┤│ [freq uint32] [s11_re float] [s11_im float] ││ [s21_re float] [s21_im float] │├──────────────────────────────────────────────────────────────┤│ Point 1 Data ... Point N-1 Data │└──────────────────────────────────────────────────────────────┘Byte order: Little-endian (ARM Cortex-M native)
Parsing Example (Python)
Section titled “Parsing Example (Python)”import structimport serial
def scan_binary(port, start_hz, stop_hz, points): """Perform binary scan and return parsed data.""" ser = serial.Serial(port, timeout=5)
# Send scan command with binary flag (0x87 = freq + S11 + S21 + binary) cmd = f"scan {start_hz} {stop_hz} {points} 135\r\n" ser.write(cmd.encode())
# Read header header = ser.read(4) mask, num_points = struct.unpack('<HH', header)
# Calculate bytes per point bytes_per_point = 0 if mask & 0x01: bytes_per_point += 4 # freq if mask & 0x02: bytes_per_point += 8 # S11 if mask & 0x04: bytes_per_point += 8 # S21
# Read all point data data = ser.read(bytes_per_point * num_points)
# Parse points results = [] offset = 0 for i in range(num_points): point = {} if mask & 0x01: point['freq'] = struct.unpack('<I', data[offset:offset+4])[0] offset += 4 if mask & 0x02: point['s11'] = complex(*struct.unpack('<ff', data[offset:offset+8])) offset += 8 if mask & 0x04: point['s21'] = complex(*struct.unpack('<ff', data[offset:offset+8])) offset += 8 results.append(point)
# Read past prompt ser.read_until(b'ch> ') ser.close() return resultsSerial Console (USART)
Section titled “Serial Console (USART)”Alternative to USB, available on exposed pins.
Hardware Configuration
Section titled “Hardware Configuration”| Signal | Pin (F072) | Pin (F303) |
|---|---|---|
| TX | PA9 | PA9 |
| RX | PA10 | PA10 |
| GND | GND | GND |
Serial Parameters
Section titled “Serial Parameters”| Parameter | Default | Range |
|---|---|---|
| Baud rate | 38400 | 19200 - 3000000 |
| Data bits | 8 | - |
| Stop bits | 1 | - |
| Parity | None | - |
| Flow control | None | - |
Available Baud Rates
Section titled “Available Baud Rates”19200, 38400, 57600, 115200, 230400, 460800, 921600, 1843200, 2000000, 3000000Configure via menu: Config → EXPERT SETTINGS → SERIAL SPEED
Or shell command: usart_cfg {baudrate}
Switching Console
Section titled “Switching Console”# Enable serial console (disables USB console)usart 1
# Disable serial console (enables USB console)usart 0The VNA_MODE_CONNECTION flag controls which console is active.
Error Handling
Section titled “Error Handling”No Response
Section titled “No Response”If the device doesn’t respond:
-
Check device enumeration:
- Linux:
lsusb | grep 0483:5740 - macOS:
system_profiler SPUSBDataType | grep -A5 NanoVNA - Windows: Check Device Manager
- Linux:
-
Check permissions:
- Linux: User in
dialoutgroup? - macOS: May need explicit terminal permissions
- Windows: Correct COM port selected?
- Linux: User in
-
Send empty line: Send
\r\nto get a freshch>prompt
Command Errors
Section titled “Command Errors”| Error | Cause |
|---|---|
| (no output) | Unknown command |
usage: ... | Missing or invalid arguments |
too many arguments, max 4 | More than 4 arguments |
Data Corruption
Section titled “Data Corruption”If binary data appears corrupted:
- Ensure no other application is accessing the port
- Check byte order (little-endian)
- Verify mask matches expected fields
- Account for all bytes in header before point data
Source Code References
Section titled “Source Code References”| Component | File | Lines |
|---|---|---|
| USB descriptors | usbcfg.c | 39-137 |
| String descriptors | usbcfg.c | 150-199 |
| Unique ID generation | usbcfg.c | 201-228 |
| Shell protocol constants | main.c | 43-50 |
| Scan mask definitions | main.c | 1371-1377 |
| Binary output logic | main.c | 1434-1441 |
| Text output logic | main.c | 1442-1448 |
| Command table | main.c | 2912-3033 |
| USART configuration | main.c | 3064-3111 |
See Also
Section titled “See Also”- Shell Command Overview — Complete command reference
- Sweep & Measurement Commands —
scancommand details - Data Export Commands —
data,frequenciescommands - USB Connection How-To — Practical connection guide