Programming a Victron Inverter with VE.Bus without Venus or GX device. Linux based, only using the MK3 adapter.
Also check out victron-mk3 — a working library that implements many inverter functions. This repo focuses on the parts that library doesn't cover: direct setting reads/writes, charge profile configuration, and protocol details that Victron's documentation gets wrong.
FINDINGS.md — Comprehensive protocol reference covering the full VE.Bus MK2/MK3 wire protocol, reverse-engineered from USB packet captures and iterative bench testing. Includes:
- Complete frame format, checksum calculation, and command/response reference
- Setting 0, 1 and 60 flag register bit maps (UPS, PowerAssist, Weak AC, reduced float, dynamic current limiter, wide frequency range, lithium, Solar & Wind priority)
- Charge profile settings and the exact 8-write sequence VEConfigure uses for LiFePO4
- Grid code / LOM setting behavior and the residual cleanup problem when reverting to "None"
- Timing, ACK quirks, cross-model differences (MultiPlus vs. Quattro), and practical gotchas
- Methodology for mapping unknown settings using sweep-and-diff
- A cross-check against VictronConnect's own VE.Bus driver: names for settings 0–88, every flag bit and RAM variables 0–37, plus alarms, error codes and energy counters (§12)
Find Victron's official (incomplete) protocol documentation here: https://www.victronenergy.com/upload/documents/Technical-Information-Interfacing-with-VE-Bus-products-MK2-Protocol-3-14.pdf
| Script | Purpose |
|---|---|
tui/tui.py |
Interactive terminal dashboard — live telemetry, decoded flags, charge-profile editing, guarded writes (see the TUI README) |
tui/vebus/protocol.py |
Reusable backend: serial/checksum/frame protocol, SerialBackend, MockBackend, and all decoders. Importable by scripts and tests |
example_scripts/setv.py |
Set absorption and float voltage (WriteViaID example) |
example_scripts/weakac.py |
One-shot: enable Weak AC (Setting 0, bit 14) — self-contained, pyserial only |
reverse_engineering/settings_sweep.py |
Sweep all 256 setting IDs — dump supported settings to CSV for diffing |
reverse_engineering/ram_sweep.py |
Sweep all 256 RAM variable IDs — identify live telemetry values |
The sweeper scripts are the primary tool for mapping unknown settings. Run a sweep, change one parameter in VEConfigure, sweep again, and diff the CSV outputs. See FINDINGS.md § Methodology for Mapping Unknown Settings for details.
A reactive terminal dashboard (Textual) that exposes the reverse-engineered features in one place — live telemetry, decoded flag registers, charge-profile editing (including a LiFePO4 fixed-profile wizard), and guarded, readback-verified writes.
See the TUI README for features, running instructions, safety notes, and tests.
Victron's documentation is incomplete and some of it is out of date. The most important points:
Use CommandWriteViaID (0x37). The documented two-step write (CommandWriteSetting 0x33 + CommandWriteData 0x34) did not work in our testing, although VictronConnect uses it, so the cause is open (FINDINGS §13). The write frame that works here is:
07 FF 58 37 01 [setting_id] [value_lo] [value_hi] [checksum]
07— length byteFF— protocol marker58— Winmon command letter ('X'; replies echo it, see FINDINGS §2)37— CommandWriteViaID01— flags: bit 0 = setting, bit 1 = RAM only (0x01= RAM + EEPROM,0x03= RAM only)- Setting value is little-endian, voltage settings scaled ×100 (e.g., 5600 = 56.00V)
See FINDINGS.md § Command Reference for the full command set including ReadSetting, GetSettingInfo, ReadRAMVar, and State commands.
- Victron MultiPlus, Quattro, or compatible VE.Bus inverter/charger
- MK3-USB interface
- USB connection to host computer
- Python 3.x
- pyserial
pip install pyserial# Set absorption and float voltage (from example_scripts/)
from setv import VoltageSettings
setter = VoltageSettings()
setter.set_voltage(56.0, 2) # Absorption = 56.00V
setter.set_voltage(54.0, 3) # Float = 54.00V# Discover all settings on your inverter
python reverse_engineering/settings_sweep.py /dev/ttyUSB0 -o baseline.csv
# Discover live RAM variables
python reverse_engineering/ram_sweep.py /dev/ttyUSB0 -o ramvars.csvNote: Writes go to EEPROM which has limited write cycles. These tools are for configuration and discovery, not automation loops.
- Verify voltage settings with a multimeter after writing
- Incorrect charge parameters can damage batteries
- Never blindly copy flag register values between different models — base values differ between MultiPlus and Quattro
- Always use read-modify-write when changing individual bits in flag registers (Settings 0, 1 and 60)
- On systems with more than one unit, settings written to address 0 change only that unit; VictronConnect writes every unit (FINDINGS §12.8)
This project was developed through reverse engineering and practical testing. If you discover additional protocol details, setting ID mappings, or corrections, please contribute them back.
MIT — permissive. You're free to use, modify, and distribute this, including commercially; just keep the copyright and permission notice. The software is provided "as is", with no warranty and no liability for misuse — and note this drives real power hardware, so see the safety notes above.