Un demarrage se decide sur l excedent, pas sur la production

Le 03/09 a 19:44, voiture branchee : PV 758 W, maison 1202 W, batterie deja
a -12 A, nuit qui tombe. Le controleur a lance 1,6 kW de charge parce que
pv_start_min_w (700 W) est une puissance PV absolue : "758 >= 700, donc il y
a du soleil". L excedent valait -444 W. En 33 minutes la voiture a pris
0,897 kWh et la batterie en a rendu 1,479 kWh (SOC 94 -> 85), la veille d une
nuit que le bilan energetique annoncait deja deficitaire.

Rejeu du releve dans la vraie chaine : rawSolarStartOk ET
batteryAssistSolarStartOk etaient tous deux vrais. Corriger le seul seuil PV
n aurait donc rien change ; les deux chemins sont traites ensemble.

La grandeur juste est ce qui reste une fois la maison servie. Sans injection
et reseau absent, PV - maison(hors EVCS) vaut la puissance batterie au signe
pres, et separe les deux situations que la mesure PV seule confond : sous
censure la production se cale sur la maison, l excedent vaut ~0 et il y a de
la ressource refusee ; en deficit reel l excedent est negatif et la batterie
porte deja la maison. Zero est la frontiere physique entre les deux, verifiee
sur le releve du 03/09 (excedent positif sur toute la plage ou pv_censored
etait ON, negatif ensuite).

Aucune constante nouvelle, aucun champ de snapshot, aucun helper :
derived.houseNonEvcsW existait deja. Le chemin "soleil reel" reutilise
pv_start_min_w tel quel, applique a la bonne grandeur ; le chemin
"provocation" exige seulement excedent >= 0. Demarrage uniquement : les
conditions de maintien gardent leur plancher et leur tolerance temporelle.

Golden 61 -> 64, autour d une paire de releves reels pris a 54 minutes d ecart
dont les lectures PV ne different que de 11 W (769 puis 758) : le premier
demarre, le second non. apresmidi-provocation-p3 est corrige : il portait
PV 300 W, maison 600 W, batterie +2 A reseau ouvert, un trou de 300 W que rien
n alimente, et passait quand meme parce que le demarrage ne regardait jamais
le bilan. Mutation dans les deux sens : 2 echecs cibles a chaque fois,
excedent-censure-demarre restant vert (il tient par le chemin assistance).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
Tallagrand Thierry
2026-09-03 20:53:50 +02:00
parent 10987a04d8
commit ef3d7ed7b2
5 changed files with 322 additions and 8 deletions

View File

@@ -570,6 +570,54 @@ const commonSafetyHoldOk =
parsed.evcsVehicleConnected &&
!parsed.evcsModeIsAuto;
// =====================================================
// EXCEDENT SOLAIRE — LA GRANDEUR QUI DECIDE D'UN DEMARRAGE (03/09/2026)
// =====================================================
// Incident du 03/09 19:44 : PV 758 W, maison 1202 W, batterie deja a -12 A,
// nuit qui tombe. Le controleur a lance 1,6 kW de charge parce que
// pv_start_min_w (700 W) est une PUISSANCE PV ABSOLUE : "758 >= 700, donc il y
// a du soleil". L'excedent, lui, valait -444 W. En 33 minutes la voiture a pris
// 0,897 kWh et la batterie en a rendu 1,479 kWh, la veille d'une nuit que le
// bilan energetique annoncait deja deficitaire (SOC requis 99,7 %).
//
// La grandeur juste n'est pas la production, c'est ce qui RESTE une fois la
// maison servie. Sans injection et reseau absent, elle vaut la puissance
// batterie au signe pres :
//
// excedent = PV - maison(hors EVCS) ~= puissance batterie
//
// C'est aussi ce qui separe les deux situations que la mesure PV seule confond
// (PV_mesuree = min(ressource, conso + absorption batterie)) :
//
// - CENSURE : batterie pleine, MPPT bride faute de puits. La production se
// cale sur la maison, l'excedent vaut ~0, la batterie ne bouge pas. Il y a
// de la ressource REFUSEE : la provoquer avec la voiture est legitime, et
// c'est toute la raison d'etre de P3 / de l'assistance batterie.
// - DEFICIT reel : soir, nuages. L'excedent est NEGATIF, la batterie porte
// deja la maison. Charger la voiture, c'est la vider.
//
// Zero n'est donc pas un seuil de plus : c'est la frontiere physique entre les
// deux, et elle etait invisible tant qu'on regardait la production seule.
// Aucune constante n'est introduite ; le chemin "soleil reel" reutilise
// pv_start_min_w tel quel, applique a la bonne grandeur.
//
// PORTEE : DEMARRAGE uniquement. Les conditions de MAINTIEN sont inchangees —
// une charge etablie a deja son plancher de decharge et sa tolerance temporelle
// (01/09), et couper une charge en cours sur une mesure d'excedent bruitee
// recreerait l'oscillateur qu'on vient d'eteindre.
const solarSurplusW = parsed.pvPowerW - derived.houseNonEvcsW;
// Chemin PROVOCATION (batterie haute, ou sourceMode solar_potential) : on
// n'exige pas d'excedent mesurable — il est censure par construction — mais on
// exige que la batterie ne porte pas deja la maison.
const solarSurplusProvocationOk = solarSurplusW >= 0;
// Chemin SOLEIL REEL : l'excedent doit atteindre le seuil de demarrage.
const solarSurplusStartOk =
context.sourceMode === 'solar_potential'
? solarSurplusProvocationOk
: solarSurplusW >= context.effectivePvStartMinW;
// =====================================================
// BATTERY-ASSISTED SOLAR START/HOLD
// IMPORTANT:
@@ -601,6 +649,7 @@ const batteryAssistSolarStartOk =
parsed.soc >= Math.max(profileSocStartFloor, batteryAssistSolarStartSocMin) &&
parsed.soc > batteryAssistSolarHoldSocMin &&
parsed.batteryCurrentA >= profileBatteryDischargeFloorA &&
solarSurplusProvocationOk &&
cloudDebtNextKwh <= batteryAssistSolarDebtStartMaxKwh &&
!cloudDebtActive;
@@ -629,10 +678,7 @@ const rawSolarStartOk =
commonSafetyStartOk &&
parsed.soc >= effectiveSocStartFloor &&
parsed.batteryCurrentA >= profileBatteryDischargeFloorA &&
(
context.sourceMode === 'solar_potential' ||
parsed.pvPowerW >= context.effectivePvStartMinW
);
solarSurplusStartOk;
const solarStartOk =
rawSolarStartOk || batteryAssistSolarStartOk;
@@ -972,6 +1018,11 @@ return [{
profileSocHoldFloor,
effectiveSocHoldFloor,
profileBatteryDischargeFloorA,
// Excedent solaire (03/09/2026) : la grandeur qui autorise un demarrage.
solarSurplusW,
solarSurplusProvocationOk,
solarSurplusStartOk,
batteryCurrentHardExceeded,
mustStopHard,
gridBatteryProtectionStop,