Skip to content

Latest commit

 

History

History
69 lines (52 loc) · 4.27 KB

protocol.md

File metadata and controls

69 lines (52 loc) · 4.27 KB

How it talks to the inverter

Transport: it's HID, not a serial port

The USB port presents as 0665:5161 ("Cypress USB to Serial" — the name is misleading). There's no CDC/serial interface, so no /dev/ttyUSB0 ever appears. Linux binds it as a raw HID device, /dev/hidrawN, and axpert.py talks to it through hidapi.

On the tested unit the product string reads "STMicroelectronics HID in FS Mode" — the inverter's own STM32 speaks USB directly, borrowing Cypress's ID so the vendor's Windows software recognises it.

The same protocol is available on the RS232/RJ45 port at 2400 baud 8N1, if you'd rather use a UART.

Framing

request:  <ASCII command> <CRC hi> <CRC lo> 0x0D
reply:    ( <ASCII data> <CRC hi> <CRC lo> 0x0D
  • CRC is CRC-16/XMODEM (poly 0x1021, init 0, no reflection).
  • If a CRC byte is 0x28 (, 0x0A LF or 0x0D CR, the protocol adds 1 to it, so it can't be mistaken for a delimiter.
  • The reply's CRC covers the leading (. Evidence: the error reply (NAKss — crc("(NAK") is ss.
  • axpert.py checks every reply's CRC and drops corrupted ones.

Example — QPIGS is exactly 8 bytes: 51 50 49 47 53 B7 A9 0D.

Over HID

  • Commands go out in 8-byte HID output reports, zero-padded. A 14-byte command is two reports; the inverter buffers until it sees CR.
  • On Linux, hid_write() wants a report-ID byte first (0x00 here). Some units of this family want it, some don't — axpert.py tries one, falls back to the other, and remembers which worked.
  • Replies come back as 8-byte input reports; ~14 of them for a QPIGS reply. Read until 0x0D.
  • The ESP32 bridge does the same as SET_REPORT control transfers out and interrupt IN for replies — what the Linux kernel does behind /dev/hidraw.

Commands used

All reads are Q… commands. Setting changes start with P, M, D or F; this project only ever sends POP0x, PCP0x and DAT…, and only when you ask.

Command Gives
QPI Protocol (PI30)
QMN, QID, QSID, QVFW Model, serial, long serial (contains QID), firmware
QMOD Mode: L grid, B battery, S standby, F fault…
QPIGS Live status (21 fields, or 24 on some firmware)
QPIRI Ratings and current settings
QPIWS Warning bits (bit 5 = line fail)
QFLAG Feature flags (buzzer, auto-restart, …)
QBMS What the battery's BMS reports, when one is linked
QOPPT, QCHPT 24 hourly output / charger priority slots (+4 trailing values)
QET, QLT Lifetime solar / load, Wh
QEDyyyymmdd, QLDyyyymmdd, QEMyyyymm, QEYyyyy… Daily, monthly, yearly energy
QT Inverter clock

Things proved on a real unit

Field Finding How
load_percent Exactly floor(VA ÷ rated VA × 100) — apparent power, truncated 45/45 samples
pv_charging_power Solar power reaching the battery, after charger losses Always a few W under PV volts × amps, never above
Battery current Whole amps only — ±27 W per sample at 53 V Raw values
Energy balance Solar + battery = load + ~10–30 W (the inverter's own draw) Closes on every run
Status bits b2/b1/b0 Charging / from solar / from grid Flip in step with the measured charge current
QOPPT/QCHPT First 24 values are hourly slots Match the priorities in QPIRI
Battery type 8 Lithium with a BMS link (LIb) QBMS answers, SOC and charge limit sync

Gotchas

  • Energy history follows the inverter's clock. QED20260816 returns nothing if the inverter thinks it's 2027. Read QT first and build dates from that (the dashboard does). After correcting the clock, older days stay filed under the old dates.
  • 24-field QPIGS. Some firmware appends feed-to-grid status, country code and exported watts. parse() keeps any extra fields as unmapped_N rather than dropping them.
  • In BMS mode, QPIRI's battery voltages can be stale. The BMS's values (QBMS) are what's in force. Saving any setting on the screen refreshes them.
  • The BMS changes the charge limit as the battery fills (seen 10 A → 80 A → 60 A on one unit). A low limit near full is normal.
  • Programs 12/13/29 in percent (lithium mode) aren't reported over PI30; only voltage-mode values appear in QPIRI.