Files
shaggy-solar/LVX6048/lvx-flash
noise 76765a95ed Grid calibration: correct lever is output-priority SUB, add grid-cal-monitor
Discovered live 2026-06-25 driving an actual grid calibration: forcing a full
grid charge is done via OUTPUT PRIORITY, not voltage thresholds.
- SBU (everyday) won't grid-charge unless the bank is critically low; setting
  charger_priority=solar_and_utility alone does nothing at 52V.
- SUB (output_priority=solar_utility_battery) runs loads on grid AND charges the
  battery to full. Combined with charger_priority=solar_and_utility, grid charging
  engages (device_mode->Hybrid/Line, line_dir->input, pack current jumps to ~120A).
- Both POP/PCP set via lvx-control (all-mode-safe, atomic, no flash/USB). Revert
  POP->solar_battery_utility, PCP->solar_first when done.

The re_discharge/flash.py approach is dead (firmware NAKs stop_charge>float);
profile eg4-lp4-v2-calibration.yaml marked DEPRECATED.

- grid-cal-monitor: supervises a SUB grid charge, safety aborts (cell>3.60V/
  temp>45C), detects re-anchor (all 6 packs ->100%), auto-reverts POP+PCP (trap).
- calibration-charge skill §3 rewritten to the POP lever.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:35:51 -04:00
..
2026-04-27 06:50:04 -04:00
2026-04-24 16:34:10 -04:00

lvx-flash

Apply declarative YAML settings profiles to an LVX6048 inverter via PI18.

Reuses the patched powermon install at ~/.local/share/uv/tools/powermon/ — the shebang in flash.py points there, so no extra setup is needed.

Commands

# 1. Snapshot the inverter's current settings into an editable profile.
./flash.py dump  --out profiles/current.yaml

# 2. Copy/edit. Preview the diff against the live device at any time.
./flash.py diff  --profile profiles/winter.yaml

# 3. Apply. The tool stops powermon.service for the duration, writes each
#    changed setting via the corresponding PI18 set command, verifies via
#    PIRI readback, and restarts powermon.service at the end.
./flash.py apply --profile profiles/winter.yaml --confirm

# 4. Compare two inverters live (for parallel setups). Exits 0 if identical,
#    1 if divergent. Useful as a quick "are the two in sync?" check.
./flash.py compare --device-a /dev/lvx6048-1 --device-b /dev/lvx6048-2

# 5. Runtime sync-check for paralleled units. Reads GS+FWS+MOD+VFW from each
#    and reports firmware mismatch, parallel-valid flag, active fault codes,
#    mode mismatch, AC voltage/frequency divergence. Exits 0 on pass, 1 on fail.
./flash.py sync-check --device-a /dev/lvx6048-1 --device-b /dev/lvx6048-2

Device selection on every subcommand:

  • --serial SN (default — uses SERIAL_UNIT_1 for single-device commands, SERIAL_UNIT_{1,2} for pairs) — globs /dev/hidraw* and picks the one whose PI18 ID matches. Resilient to cable moves.
  • --device PATH — explicit hidraw path, skips auto-resolution. Useful for probing an unknown unit.

The known-stack serials are hard-coded as SERIAL_UNIT_1 / SERIAL_UNIT_2 constants at the top of flash.py; edit them if a unit is replaced.

sync-check depends on the FWS / PGS additions to powermon/protocols/pi18.py; the --serial flow depends on the UsbPortConfig.serial_number field addition. Both are described in Install.md §5(d)(e).

Profile schema

All keys are optional. Only present keys are applied; the rest are left alone.

key range / enum PI18 setter
battery_type AGM | FLOODED | USER PBT
cutoff_voltage 40.0 48.0 V PSDV
stop_discharge_voltage 44.0 51.0 V BUCD (pair)
stop_charge_voltage 0 (full) or 48.0 58.0 V BUCD (pair)
bulk_voltage 48.0 58.4 V MCHGV (pair)
float_voltage 48.0 58.4 V (≤ bulk_voltage) MCHGV (pair)
max_charging_current 10, 20, 30, 40, 50, 60, 70, 80 A MCHGC
max_utility_charging_current 2, 10, 20, 30, 40, 50, 60, 70, 80 A MUCHGC
output_source_priority solar_utility_battery | solar_battery_utility POP
charger_priority solar_first | solar_and_utility | solar_only PCP
solar_power_priority battery_load_utility_ac | load_battery_utility PSP
grid_tie enabled | disabled PEI / PDI

Pair settings (BUCD, MCHGV) must have both halves present.

Safety

  • apply refuses to run without --confirm.
  • Range + consistency validation runs before any write. A failure aborts before touching the inverter.
  • Each write is followed by a PIRI readback that must match to within 0.05 V. A mismatch aborts.
  • Settings are applied in an order that's safe for a battery: cutoff → BUCD → MCHGV → currents → priorities → grid-tie mode.
  • powermon.service is stopped for the write window so the two processes don't fight over /dev/lvx6048-1, then restarted even if the run aborts.

Caveats

  • Parallel setups: PCP / MCHGC / MUCHGC are indexed by parallel unit (the tool sends unit 0 — master). Some firmware only accepts sets on the master; the slave mirrors silently.
  • PIRI reports max_charging_current as the effective combined (solar + AC) cap, which can exceed MCHGC's 80 A range. dump omits it with a comment when that happens.
  • Changing battery_type while the unit is actively charging is generally allowed by the firmware but not recommended.