# Relevé banc — ECS-306 et commutations par relais Dépôt : `etm-powersync-energy-plugin-etm` · Banc : `192.168.1.75` (`nymea-dev-rpi`) Installation émulée : `specs/spec_ecs.md` §4.0 (INST-100), cf. INST-104. > **Ce document est publié AVANT la mesure.** La section « Prédiction » est > horodatée du **2026-08-09** et commitée avant tout profil lancé. Une > reconstruction analytique publiée après coup ne vaut rien ; publiée avant, elle > est falsifiable. Les résultats viendront s'ajouter en dessous, sans jamais > réécrire la prédiction — si elle est fausse, elle reste, et c'est le > renseignement utile. --- ## 1. Dispositif Trois charges, un seul budget de surplus, cascade par rang ascendant. | Charge | Rang | Adaptateur | Paliers / états | Verrous | |---|---|---|---|---| | `chauffe-eau` | 1 | `relay-router` — Relay1/2/3 (500/1000/2000 W) | 0…3500 W, 8 valeurs | `minOnS`/`minOffS` = 60 s (300 s pour le volet 1, cf. §3) | | PAC SG-Ready | 2 | `sg-ready` — Relay4/5, codé en dur | P3 = 1500 W, P4 = 3000 W | `minStateHoldS` = 300 s | | `sonde-residu` | 3 | `relay-router` — Relay6, **1 relais, 100 W** | 0 / 100 W | `minOnS`/`minOffS` = 10 s | **La sonde est un instrument de mesure, pas une charge.** Aucune résistance n'est câblée sur Relay6 : le relais claque, rien ne consomme. Ce qu'elle rend observable est une **décision d'allocation** — le résidu que le waterfall laisse à la charge suivante — et non une puissance. Son palier à 100 W est choisi très au-dessous de l'écart attendu (500 W) pour que le basculement soit franc. Pilotage du surplus : `banc/cmd/manual {"grandeur":"pv","mode":true,"value":}` sur le broker `192.168.1.131`, `modele.py:178`. `banc/cmd/pause` fige l'horloge du modèle et rend le profil reproductible. --- ## 2. Prédiction — 2026-08-09, avant mesure ### Pourquoi la télémétrie ne discrimine pas Les Things sont des relais **GPIO** : leur ThingClass n'expose pas `currentPower`. `RelayRouter::telemetry()` retombe donc sur le **nominal commandé** (`relayrouter.cpp:113-114`), et `currentPowerW == palier commandé` en permanence. Conséquence : `budget_charge = budget + palier_courant`. Tant que le budget reste positif, les deux versions choisissent le même palier et laissent le même résidu. **La divergence n'apparaît qu'en import net**, budget signé négatif. ### Volet 1 — point de fonctionnement discriminant Surplus 3600 W jusqu'à ce que le chauffe-eau atteigne 3500 W et arme `minOn`, puis chute à **−300 W** maintenue. ``` budget_charge = −300 + 3500 = 3200 ``` | | Palier retenu | Résidu annoncé | PAC (rang 2) | Sonde (rang 3) | |---|---|---|---|---| | **`+etm2`** | 3000 (plus haut ≤ 3200) | **+200 W** | état 2 (200 < P3) | **ALLUMÉE** (100 ≤ 200) | | **`+etm3`** | 3500 (forcé par `lockMinPowerW`) | **−300 W** | état 2 | **ÉTEINTE** (100 > −300) | Sous `+etm2`, le routeur écrête malgré tout à 3500 W (verrou interne) : **500 W sont consommés de plus que comptés**, et ce sont ces 500 W que la sonde révèle. **Prédiction falsifiable : la sonde s'allume sous `+etm2`, reste éteinte sous `+etm3`. Si elle s'allume sous `+etm3`, le raisonnement est faux.** Prédiction secondaire : **la PAC ne changera pas d'état** entre les deux versions — 200 W comme −300 W sont tous deux sous P3 = 1500 W. Le volet 1 ne montrera donc rien sur la PAC ; c'est la sonde qui porte la démonstration. Sans elle, ce relevé aurait conclu « aucun effet observable » à tort. ### Volet 2 — commutations par relais Balayage complet 0 → 3500 W puis retour, plateaux ≥ 90 s (`minOnS` = 60 s). Comptage attendu sur un aller simple : | Relais | Commutations | Part | |---|---|---| | R500 | **7** | bit de poids faible | | R1000 | **3** | | | R2000 | **1** | | | **total** | **11** | | La transition **1500 → 2000 W** (`{R500,R1000}` → `{R2000}`) bascule **les trois relais**, soit **3 des 11** commutations à elle seule. C'est la seule du câblage dans ce cas. **Piège prédit — le cliquet.** `currentPowerW` valant le nominal commandé, le budget rendu à la charge inclut toujours son propre palier : un profil qui ne fait que **décroître en surplus positif** ne fera jamais redescendre le palier. Il faut des plateaux à **surplus négatif** pour provoquer la descente, sinon le chauffe-eau reste à 3500 W du début à la fin et le relevé est vide. --- ## 3. Protocole Deux campagnes **séparées**, jamais fusionnées : si un résultat surprend, il faut pouvoir dire lequel des deux réglages en est la cause. **Volet 1** — `minOnS` du chauffe-eau porté à **300 s** le temps de l'essai, pour élargir la fenêtre d'observation. Écart de réglage assumé et déclaré ; remis à 60 s après. **Volet 2** — `minOnS` à 60 s, plateaux ≥ 90 s, avec plateaux à surplus négatif. **Ordre d'exécution** : `+etm3` étant déjà installé, mesurer l'**après** d'abord, puis descendre en `+etm2`, refaire le même profil, puis remonter en `+etm3`. **Vérification obligatoire au retour en `+etm2`** : relire paliers et rangs par `NymeaEnergy.GetLoadConfig` **avant** de lancer le profil. La configuration a été écrite par `+etm3` ; si `+etm2` la rejetait — silencieusement ou non — on mesurerait deux dispositifs différents sans le voir. --- ## 4. Résultats ### 4.0 — Un défaut trouvé avant toute mesure (2026-08-09) La première tentative a révélé un **blocage circulaire dans ECS-412**, pas dans le banc : la charge sonde restait figée à 0 W sous 4 kW de surplus disponible. Un horodatage de dernière commutation nul servait de sentinelle « écoulé = 0 » à chaque cycle, si bien que toute charge démarrant relais ouverts avec `minOffS > 0` ne pouvait jamais s'enclencher. **La prédiction du §2 annonçait « sonde éteinte sous `+etm3` » — et elle l'était, mais pour la mauvaise raison.** Sans un test de falsification cherchant *pourquoi* elle se vérifiait, ce relevé aurait coché la prédiction et conclu à tort. Une prédiction juste peut être confirmée par un mécanisme faux ; c'est la limite de l'exercice, et elle mérite d'être écrite ici. Corrigé en `1.15.2+etm4` (armement paresseux et transitoire), couvert par `testEcsColdStartLockExpires`. **Vérifié au banc après déploiement** : sonde éteinte deux cycles, puis enclenchée — le verrou court puis expire. ### 4.1 — Volet 1, expérience naturelle sous `+etm4` Le contraste attendu entre `+etm2` et `+etm3` a été observé **au sein d'un même binaire**, sur deux cycles consécutifs au même budget : l'un verrou actif, l'autre verrou expiré. Le cycle à verrou expiré reproduit exactement ce que ferait `+etm2`, puisque sans verrou le clamp d'ECS-306 n'a rien à contraindre. | | Budget charge | Chauffe-eau | Résidu annoncé | Sonde (rang 3) | |---|---|---|---|---| | **Verrou minOn ACTIF** | 3202 W | **maintenu 3500 W** | **−198 W** | **éteinte** | | **Verrou EXPIRÉ** | 3201 W | 3000 W (plus haut ≤ budget) | **+201 W** | **allumée** | Traces brutes : ``` "chauffe-eau" → "Verrou minOn — chauffe-eau maintenue à 3500 W (puissance engagée, budget 3202 W) ; le résidu en tient compte" "sonde-residu" → "Verrou minOn — sonde residu maintenue à 0 W (budget -198 W)" "chauffe-eau" → "Surplus PV 3201 W — chauffe-eau consigne 3000 W (palier)" "sonde-residu" → "Surplus PV 201 W — sonde residu consigne 100 W (palier)" ``` **Arithmétique vérifiée**, à 2 W près du prédit : `3202 − 3500 = −298`, puis recrédit de la sonde elle-même (100 W, alors allumée) → `−198`. Côté verrou expiré : `3201 − 3000 = +201`, sonde éteinte donc aucun recrédit → `+201`, au-dessus de son palier de 100 W. ### Ce qui est démontré, et ce qui ne l'est pas **Démontré, directement** : au même budget, honorer le verrou ou l'ignorer change le résidu de 500 W et **fait basculer la charge de rang 3**. C'est la moitié *comptable* de l'affaire, et elle est observée sans ambiguïté. **NON démontré directement** : l'écart entre consommé et compté. Dans le cycle à verrou expiré, le routeur applique **réellement** 3000 W — il n'y a donc aucun écart dans ce cycle-là. L'autre moitié — le routeur qui écrête à 3500 W pendant que le scheduler ne compte que 3000 — est observée dans le **premier** cycle, pas dans le second. Le résultat tient donc par **composition de deux moitiés observées, chacune dans un cycle différent du même binaire**. C'est solide, mais ce n'est pas une observation directe du défaut complet. **Un `+etm2` réellement installé reste le seul moyen de voir les deux moitiés dans le même cycle** — c'est ce qui reste à faire, et c'est pourquoi l'expérience naturelle ne le remplace pas. **La prédiction secondaire est confirmée aussi** : la PAC de rang 2 est restée en état 4 sur les deux cycles. Sans la charge sonde, ce relevé aurait conclu « aucun effet observable ». ### 4.2 — Volet 2, commutations : PRÉDICTION FALSIFIÉE (protocole en cause) Profil de 18 plateaux de 100 s, montée 0 → 3600 W puis descente jusqu'à −3000 W. | Cible surplus | Palier | Commutations | |---|---|---| | 0 → 3600 (8 plateaux, montée) | **3500 W tout du long** | **0** | | 3600 → 500 (6 plateaux, descente) | **3500 W tout du long** | **0** | | 0 | 3000 W | 1 — R500 | | −500 | 2000 W | 1 — R1000 | | −1500 | 500 W | 2 — R500, R2000 | | −3000 | 0 W | 1 — R500 | **Mesuré : R500 = 3, R1000 = 1, R2000 = 1 — total 5.** **Prédit : 7 / 3 / 1 — total 11.** **Transitions à trois relais observées : AUCUNE.** La frontière 1500 → 2000 n'a jamais été franchie. #### Le cliquet est confirmé, et plus fort que prédit **Quatorze plateaux consécutifs sans une seule commutation**, de 0 à 3600 W puis retour à 500 W. Le palier n'a bougé qu'une fois le surplus **négatif**. La prédiction du §2 sur ce point est non seulement juste, elle était trop prudente : ce n'est pas seulement la descente en surplus positif qui ne fait rien redescendre, c'est **toute la plage positive**. #### Pourquoi la prédiction 7/3/1 est fausse : un EMBALLEMENT propre au banc Ce n'est pas un « mauvais point de départ ». Le chauffe-eau était à 3500 W pour une raison **mécanique**, et elle mérite d'être comprise avant qu'on ne « corrige » la mauvaise chose. Deux faits se composent sur ce banc : 1. les Things sont des relais **GPIO** : leur ThingClass n'expose pas `currentPower`, donc le recrédit anti-clignotement (correction B) crédite le **nominal commandé** ; 2. le rootmeter de `.75` est la **vue SunSpec du simulateur**, aveugle aux résistances réellement câblées sur ces broches. La consommation de l'ECS ne fait donc **jamais** baisser l'export mesuré. Résultat : `budget_charge = surplus + palier` **double-compte**. Chaque cycle, le budget apparent dépasse le palier courant, la charge monte d'un cran — et recommence. Tant que le surplus dépasse 500 W, le palier grimpe jusqu'au plafond. C'est un **emballement**, et il explique à lui seul les quatorze plateaux sans commutation. > **NE PAS « CORRIGER » LA CORRECTION B.** Cet emballement est un **artefact de > banc**, pas un défaut du moteur. Sur une installation réelle, l'ECS est **derrière > le compteur réseau** : sa consommation fait réellement chuter l'export, le > recrédit compense exactement ce que la charge vient de retirer, et la boucle est > juste. Supprimer ou amoindrir le recrédit casserait l'anti-oscillation qu'il > protège (ECS-404) sans rien régler. Le défaut est dans la **cécité du compteur du > banc**, pas dans l'arithmétique du budget. #### Conséquence sur ECS-303 : NON affaibli La remarque « la frontière 1500 → 2000 est inatteignable en montée » vaut **pour ce banc**, où l'emballement interdit toute montée pas à pas. Elle ne vaut pas pour une installation réelle : la rampe matinale y traverse la bande 1500-2000 W lentement, et la frontière est franchie normalement. **ECS-303 reste donc justifié.** Et le volet 2 n'est **pas** à refaire depuis le palier 0 sur le simulateur — il est à faire **après le câblage** de la résistance physique et du compteur, sur la vraie installation. C'est le seul contexte où le comptage de commutations dit quelque chose sur la durée de vie des contacteurs. ### 4.3 — Ce qui reste à mesurer - **`+etm2` réellement installé**, pour confirmer que le cycle « verrou expiré » est bien un substitut fidèle. L'expérience naturelle est convaincante mais elle n'est pas la comparaison demandée. - **Volet 2** — relevé de commutations par relais : non commencé.