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

@@ -2485,3 +2485,140 @@ Preuve par mutation, les deux sens séparément :
---
*Document mis à jour le : 01/09/2026 (~20:15) — tolérance temporelle de la politique batterie branchée, golden 61/61*
## 36. Session du 03/09/2026 — Un demarrage se decide sur l'excedent, pas sur la production
### Le releve
Le 03/09, la voiture est branchee a **19:44**. Le controleur lance la charge
dans la seconde. En 33 minutes (19:44 → 20:17, arret par `stop_source_lost`) :
| | valeur integree |
|---|---:|
| pris par la voiture | **0,897 kWh** |
| rendu par la batterie | **1,479 kWh** |
| produit par le PV | 0,327 kWh |
| SOC | **94 % → 85 %** |
Au meme moment, le bilan energetique publiait : croisement PV/conso a **9 h**,
**11,66 kWh a couvrir**, SOC requis **99,7 %**, `grid_needed` ON. Dans sa propre
arithmetique (plancher 22 %, 15 kWh utiles), la charge du soir a fait passer le
manque de la nuit de **0,86 kWh a 2,21 kWh** — elle l'a plus que double, pour
mettre dans la voiture 0,9 kWh qu'elle allait de toute facon reprendre en heures
creuses a 01:24. La fenetre du soir ferme a 20:30 ; il n'y a rien entre les deux.
Precedent immediat, nuit du 02-03/09 : EDF relache a 02:30 a 45 %, batterie a
20 % vers 05:45, reseau maintenu jusqu'a 10:33 — dont **1,49 kWh importes entre
07:24 et 10:33, hors heures creuses**. Marge perdue le soir, rachetee au plein
tarif le matin.
### La cause
`pv_start_min_w` (700 W) est une **puissance PV absolue**. A 19:44 : PV 758 W,
maison 1202 W, batterie deja a −12,2 A. Le controleur a lu « 758 ≥ 700, donc il
y a du soleil » et a lance 1,6 kW. **L'excedent valait −444 W.**
Verification dans la vraie chaine (rejeu du releve) : `rawSolarStartOk` ET
`batteryAssistSolarStartOk` etaient TOUS DEUX vrais. Un correctif sur le seul
seuil PV n'aurait donc rien change — l'assistance batterie aurait demarre la
charge de toute facon. Les deux chemins devaient etre traites ensemble.
Deux temporisations ont ensuite prolonge la faute, sans en etre la cause :
`charging_hold_cloud_tolerance` a pris **le coucher du soleil pour un passage
nuageux** (19:46 → 20:00), puis, la tolerance souple du 01/09 epuisee a 19:57,
`min_run` (29 min) a maintenu la charge **16 minutes de plus**, conditions de
maintien deja declarees perdues. Non traite ici.
### Le correctif (deploye 03/09 20:51, golden 64/64)
Une seule grandeur, dans `BATTERY_CLOUD_LOCKS.js`. `derived.houseNonEvcsW`
existait deja (calcule dans WINDOWS_SOURCEV2, deja lu par BCL) : **aucun champ
de snapshot, aucun helper, aucune constante nouvelle.**
```js
const solarSurplusW = parsed.pvPowerW - derived.houseNonEvcsW;
```
Sans injection et reseau absent, cette grandeur vaut la puissance batterie au
signe pres. C'est 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 (raison d'etre
de P3 et de l'assistance batterie).
- **DEFICIT** — 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.
Deux tests, parce que les deux chemins n'ont pas le meme metier :
- **chemin « soleil reel »** (`rawSolarStartOk`) : excedent ≥ `pv_start_min_w`.
Meme helper, meme valeur, appliquee a la bonne grandeur ;
- **chemin « provocation »** (assistance batterie, ou sourceMode
`solar_potential`) : excedent ≥ **0**. On n'exige pas d'excedent mesurable —
il est censure par construction — seulement que la batterie ne porte pas deja
la maison.
⚠️ **PORTEE : DEMARRAGE UNIQUEMENT.** Les conditions de MAINTIEN sont
inchangees : une charge etablie a deja son plancher de decharge et sa tolerance
temporelle (§35), et couper une charge en cours sur une mesure d'excedent
bruitee recreerait l'oscillateur qu'on venait d'eteindre.
Verification empirique de la frontiere sur le releve du 03/09 : de 17:00 a 19:41,
`pv_censored` ON et excedent **toujours positif** (+14 a +212 W) ; a partir de
19:42, excedent negatif. La frontiere a zero separe exactement les deux regimes
sur la mesure reelle.
### Golden 61 → 64, et un scenario corrige
La paire de releves REELS, prise a 54 min d'intervalle, est le coeur du test :
| scenario | PV | maison | batterie | excedent | attendu |
|---|---:|---:|---:|---:|---|
| `excedent-censure-demarre` (18:50) | 769 W | 755 W | 0 A | **+14 W** | `start_min_current` 6 A |
| `excedent-deficit-ne-demarre-pas` (19:44) | 758 W | 1202 W | −12,2 A | **−444 W** | `idle_wait_conditions` |
**11 W d'ecart sur la lecture PV.** L'ancien code voyait la meme chose dans les
deux. Sans cette paire, rien ne prouverait que la nouvelle grandeur discrimine
ce que l'ancienne confondait.
Troisieme scenario, `excedent-grosse-production-grosse-maison` : PV 3000 W,
maison 2800 W, SOC 60 — pas de censure possible, la production mesuree EST la
ressource et elle est deja prise. Il exerce le chemin « soleil reel », que la
paire ne touche pas (elle passe par l'assistance).
**`apresmidi-provocation-p3` a ete corrige** : il portait PV 300 W, maison 600 W,
batterie +2 A, reseau ouvert — un trou de 300 W que rien n'alimente, etat
physiquement inatteignable. Il passait quand meme, precisement parce que le
demarrage ne regardait que la production et jamais le bilan. Remis coherent en
gardant son intention (production sous `pv_hold_min` 500 ET sous `pv_start_min`
700, donc seul `solar_potential` peut demarrer) : PV 430 W, maison 400 W,
excedent +30 W — la vraie signature de la censure.
Preuve par mutation, dans les deux sens : retour au seuil absolu → 2 echecs
cibles ; garde neutralisee → les 2 memes. Dans les deux cas
`excedent-censure-demarre` reste VERT, ce qui prouve qu'il tient par le chemin
assistance et non par la garde. Restauration → 64/64.
### Limite connue
Si `sensor.victron_consumption_power_l1` passe `unavailable`, la maison est lue
a 0 et l'excedent redevient la production brute — c'est-a-dire le comportement
d'avant ce correctif. Degradation vers l'existant, jamais pire.
### Ce que ce correctif ne fait PAS (suite convenue avec le proprietaire)
2. **Lire `input_boolean.evcs_balance_pv_censored`** pour conditionner la
provocation `solar_potential`, au lieu de l'approximer par SOC ≥ 90. Le
03/09 la censure s'est arretee a 19:30 (`batterie_pleine_sans_puits` →
`production non bridee` a 20:00) : l'approximation disait « oui » au moment
exact ou la chose approximee devenait fausse.
3. **Lire `evcs_balance_required_soc` / `_energy_to_cover_kwh`** pour que le
plancher du soir cesse d'etre un niveau fixe (`evening_soc_start_min` = 85).
⚠️ **CONSTAT STRUCTUREL, a garder en tete pour la suite** :
`grep evcs_balance workflows/evcs-surplus-controller-v2.6.json` → **0**, idem
pour l'hysteresis. Le bilan energetique calcule et publie l'heure de croisement,
l'energie a couvrir, le SOC requis, `grid_needed` et `pv_censored` — et **aucun
des deux workflows qui decident n'en lit une seule valeur**. Meme contradiction
sur la cible du matin : `night_target_soc` = 35 % (regle sur le TOTAL de demain,
33,9 kWh ≥ 18 → « fort ») contre 99,7 % pour le bilan, qui regarde QUAND
l'energie arrive — demain matin est creux : 0,03 kWh a 7 h, 0,77 a 8 h, 1,81 a
9 h. Deux nombres, memes donnees, facteur 3.
---
*Document mis a jour le : 03/09/2026 (~20:55) — demarrage sur l'excedent, golden 64/64, deploye*