fix: PV_in_current/watts tramite bilancio energetico DC bus
Build Docker Image for Raspberry Pi / build-and-push (push) Successful in 12m47s

Il protocollo QPGS non espone la corrente reale lato pannelli.
DATA[25] = corrente SCC→batteria SOLTANTO (0 quando batteria carica).

Formula corretta via conservazione energetica del DC bus:
  P_pv = V_batt×DATA[25] + max(0, Load_W − V_batt×DATA[26])

Dove:
  V_batt×DATA[25]  = potenza SCC inviata alla batteria
  Load_W           = potenza consumata dal carico dal bus DC
  V_batt×DATA[26]  = potenza fornita dalla batteria in scarica

Casi coperti:
  1. Bat. in carica (DATA[25]>0, DATA[26]=0):  P = V_b×I_scc + Load
  2. Bat. piena    (DATA[25]=0,  DATA[26]=0):  P = Load
  3. Bat. in scar. (DATA[25]=0,  DATA[26]>0):  P = max(0, Load−Pdisch)

Guard: calcolo solo quando SCC_charging (STATUS b5=1), altrimenti 0.

Aggiunto SCC_current (=DATA[25]) come campo separato per monitorare
la corrente SCC→batteria indipendentemente dalla produzione PV.

Aggiunto SCC_current al topic di discovery HA in mqtt-init-parallel.sh
This commit is contained in:
Pi Developer
2026-02-22 15:22:14 +01:00
parent 74508bd330
commit 94ac952644
2 changed files with 27 additions and 29 deletions
@@ -93,6 +93,7 @@ for inv_id in $(seq 1 $INVERTER_COUNT); do
registerTopic $inv_id "Battery_capacity" "%" "battery-outline"
registerTopic $inv_id "Battery_voltage" "V" "battery-outline"
registerTopic $inv_id "Battery_charge_current" "A" "current-dc"
registerTopic $inv_id "SCC_current" "A" "current-dc"
registerTopic $inv_id "Battery_discharge_current" "A" "current-dc"
registerTopic $inv_id "Load_status_on" "" "power"
registerTopic $inv_id "SCC_charge_on" "" "power"
+26 -29
View File
@@ -103,53 +103,50 @@ processInverter () {
[ "${DATA[12]}" ] && pushMQTTData "$inv_id" "Battery_charge_current" "${DATA[12]}"
[ "${DATA[13]}" ] && pushMQTTData "$inv_id" "Battery_capacity" "${DATA[13]}"
[ "${DATA[14]}" ] && pushMQTTData "$inv_id" "PV_in_voltage" "${DATA[14]}"
[ "${DATA[25]}" ] && pushMQTTData "$inv_id" "SCC_current" "${DATA[25]}"
[ "${DATA[26]}" ] && pushMQTTData "$inv_id" "Battery_discharge_current" "${DATA[26]}"
# ─── PV panel-side power calculation ─────────────────────────────────────
# DATA[25] is labeled "PV input current" by the inverter but is actually
# the SCC *output* current flowing to the battery at battery voltage.
# The inverter protocol does NOT expose the real panel-side current directly.
# ─── Real PV panel power calculation via DC-bus energy balance ────────────
# The QPGS protocol does NOT expose the true PV panel input current directly.
# DATA[25] = "PV input current for battery" = SCC output current to battery ONLY.
# This is 0 when battery is full even though panels are producing.
# DATA[26] = battery discharge current (at battery voltage).
# DATA[9] = AC output load watt (power drawn from DC bus by the inverter).
#
# The SCC is a DC-DC converter: power_in ≈ power_out (ignoring ~5% losses).
# P_pv = V_batt × I_scc (SCC output power = panel power)
# I_pv = P_pv / V_pv (real panel current at panel voltage)
# The DC bus balance equation gives us the real SCC output power:
# SCC_out = Load_watt + Bat_charge Bat_discharge
# = Load + (V_batt × DATA[25]) (V_batt × DATA[26])
# When SCC is the sole DC source:
# P_pv ≈ SCC_out = V_batt×DATA[25] + max(0, Load V_batt×DATA[26])
#
# Edge case - battery fully charged (DATA[25] = 0):
# If SCC_OK (b7=1) and line_loss (b2=1, no AC grid) → solar feeds load directly.
# Best proxy: Load_watt (solar production = what the load is consuming).
# If AC grid is present → solar floats battery, nothing meaningful to report.
# Guard: only calculate when SCC_charging bit (STATUS b5, index 2) = 1.
# When SCC is off, PV production = 0 regardless of field values.
local BATT_V="${DATA[11]:-0}"
local SCC_A="${DATA[25]:-0}"
local DISCH_A="${DATA[26]:-0}"
local PV_V="${DATA[14]:-0}"
local LOAD_W="${DATA[9]:-0}"
local STATUS="${DATA[19]:-00000000}"
# STATUS string b7b6b5b4b3b2b1b0 - each char is one bit:
# index 0=b7=SCC_OK, index 1=b6=AC_charge, index 2=b5=SCC_charge,
# index 5=b2=line_loss (1=no AC grid), index 6=b1=load_on
local SCC_OK="${STATUS:0:1}"
local LINE_LOSS="${STATUS:5:1}"
# STATUS bit layout (b7b6b5b4b3b2b1b0 as string, index 0=b7):
# index 2 = b5 = SCC_charging (1 = SCC actively converting solar)
local SCC_CHARGING="${STATUS:2:1}"
local PV_WATTS PV_CURRENT
if awk -v v="$SCC_A" 'BEGIN{exit !(v+0 > 0)}' 2>/dev/null; then
# SCC delivering current to battery: compute panel-side values
# P_pv = V_batt × I_scc
PV_WATTS=$(echo "$BATT_V $SCC_A" | awk '{printf "%.1f", $1 * $2}')
# I_pv = P_pv / V_pv (real current from panels at panel voltage)
if awk -v v="$PV_V" 'BEGIN{exit !(v+0 > 0)}' 2>/dev/null; then
PV_CURRENT=$(echo "$PV_WATTS $PV_V" | awk '{printf "%.2f", $1 / $2}')
else
PV_CURRENT="0.00"
fi
elif [ "$SCC_OK" = "1" ] && [ "$LINE_LOSS" = "1" ]; then
# SCC OK, battery full, no AC grid → solar feeds load directly
PV_WATTS="$LOAD_W"
if [ "$SCC_CHARGING" = "1" ]; then
# SCC is active: estimate total PV power via DC bus balance
# P_pv = V_batt × I_scc_to_battery + max(0, Load V_batt × I_bat_discharge)
local BATT_CHARGE_W=$(echo "$BATT_V $SCC_A" | awk '{printf "%.1f", $1 * $2}')
local BATT_DISCH_W=$(echo "$BATT_V $DISCH_A" | awk '{printf "%.1f", $1 * $2}')
local LOAD_FROM_SCC=$(echo "$LOAD_W $BATT_DISCH_W" | awk '{v=$1-$2; printf "%.1f", (v>0)?v:0}')
PV_WATTS=$(echo "$BATT_CHARGE_W $LOAD_FROM_SCC" | awk '{printf "%.1f", $1 + $2}')
if awk -v v="$PV_V" 'BEGIN{exit !(v+0 > 0)}' 2>/dev/null; then
PV_CURRENT=$(echo "$PV_WATTS $PV_V" | awk '{printf "%.2f", $1 / $2}')
else
PV_CURRENT="0.00"
fi
else
# SCC off: no solar conversion
PV_WATTS="0.0"
PV_CURRENT="0.00"
fi