Page de decision : dimensionnement du parc batterie
Generateur rejouable (tools/gen-page-batteries.py) plutot qu'un HTML ecrit a la main : les chiffres viennent des mesures et se recalculent. Base : 37 nuits completes issues des statistiques long terme de Home Assistant (fin juillet au 4 septembre, maison seule, voiture deduite) et la courbe energie/SOC etablie sur 576 paliers. Le chiffre qui cadre la decision : les 7 modules actifs delivrent 10,7 kWh a la maison, la nuit mediane en demande 13,2 — la batterie passe la nuit seule 1 fois sur 37. Reparer le module en panne porte cela a 5/37 seulement ; deux modules de plus le portent a 32/37. Reparer seul ne resout rien. Second point, moins attendu : au-dela de la consommation nocturne le stockage ne cycle plus. Le surplus de milieu de journee est un probleme de preneur, pas de stockage — la voiture absorbe deja 9,8 kWh/jour en mediane. Reserve inscrite en clair : toutes les mesures sont d'ete, les compteurs exploitables ne remontant qu'a fin juillet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
565
docs/pages/dimensionnement-batteries.html
Normal file
565
docs/pages/dimensionnement-batteries.html
Normal file
@@ -0,0 +1,565 @@
|
||||
<title>Dimensionner le parc batterie</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,500;12..96,700&family=IBM+Plex+Mono:wght@400;600&family=Newsreader:ital,opsz,wght@0,6..72,300;0,6..72,400;0,6..72,600;1,6..72,400&display=swap">
|
||||
<style>
|
||||
:root {
|
||||
--ground:#e7eaee; --surface:#f6f8f9; --surface-2:#dde3e8;
|
||||
--ink:#101821; --ink-2:#3d4a57; --muted:#6b7885; --rule:#c6cfd7;
|
||||
--solaire:#c9791a; --solaire-d:#a35f10; --stock:#166b78; --stock-d:#0f4e58;
|
||||
--reseau:#a8422c; --vert:#3f6b3a;
|
||||
--mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;
|
||||
--titre:"Bricolage Grotesque","Helvetica Neue",Arial,sans-serif;
|
||||
--corps:"Newsreader",Georgia,"Times New Roman",serif;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--ground:#0d1319; --surface:#141c24; --surface-2:#1d2831;
|
||||
--ink:#e4eaef; --ink-2:#b3c0cb; --muted:#8695a2; --rule:#2b3945;
|
||||
--solaire:#e79a3c; --solaire-d:#c47d24; --stock:#3aa5b5; --stock-d:#2b8290;
|
||||
--reseau:#d9705a; --vert:#7ab070;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"] {
|
||||
--ground:#0d1319; --surface:#141c24; --surface-2:#1d2831;
|
||||
--ink:#e4eaef; --ink-2:#b3c0cb; --muted:#8695a2; --rule:#2b3945;
|
||||
--solaire:#e79a3c; --solaire-d:#c47d24; --stock:#3aa5b5; --stock-d:#2b8290;
|
||||
--reseau:#d9705a; --vert:#7ab070;
|
||||
}
|
||||
* { box-sizing:border-box; }
|
||||
body { background:var(--ground); color:var(--ink); font-family:var(--corps);
|
||||
font-size:17.5px; line-height:1.62; font-weight:300;
|
||||
-webkit-font-smoothing:antialiased; padding:0 20px 96px; }
|
||||
.page { max-width:1040px; margin:0 auto; }
|
||||
.col { max-width:64ch; }
|
||||
h1,h2,h3,.chapeau,.code,.n,.axe,.val,.etiq,.compte,table,.jauge em,.tag,.puce b {
|
||||
font-family:var(--titre); }
|
||||
h1 { font-size:clamp(2.3rem,5.4vw,3.9rem); line-height:1.02; font-weight:700;
|
||||
letter-spacing:-.028em; text-wrap:balance; margin:0 0 .5rem;
|
||||
max-width:15ch; }
|
||||
.surtitre { font-family:var(--mono); font-size:.7rem; letter-spacing:.16em;
|
||||
text-transform:uppercase; color:var(--muted); margin:56px 0 20px; }
|
||||
.chapeau { font-family:var(--corps); font-size:1.24rem; line-height:1.55;
|
||||
color:var(--ink-2); max-width:56ch; font-weight:300; }
|
||||
h2 { font-size:1.62rem; font-weight:700; letter-spacing:-.018em;
|
||||
margin:72px 0 4px; text-wrap:balance; }
|
||||
h2 + .sous { font-family:var(--mono); font-size:.72rem; letter-spacing:.1em;
|
||||
text-transform:uppercase; color:var(--muted); margin:0 0 22px; }
|
||||
h3 { font-size:1.06rem; font-weight:700; margin:34px 0 6px; letter-spacing:-.01em; }
|
||||
p { margin:0 0 1.05em; }
|
||||
strong { font-weight:600; color:var(--ink); }
|
||||
em.i { font-style:italic; }
|
||||
hr { border:0; border-top:1px solid var(--rule); margin:64px 0; }
|
||||
a { color:var(--stock); }
|
||||
|
||||
/* --- verdict --- */
|
||||
.verdict { background:var(--surface); border:1px solid var(--rule);
|
||||
border-left:4px solid var(--solaire); border-radius:3px;
|
||||
padding:26px 30px; margin:38px 0 8px; max-width:66ch; }
|
||||
.verdict p:last-child { margin-bottom:0; }
|
||||
.verdict .gros { font-family:var(--titre); font-weight:700;
|
||||
font-size:1.3rem; line-height:1.3; letter-spacing:-.015em; }
|
||||
|
||||
/* --- planches --- */
|
||||
.planche { background:var(--surface); border:1px solid var(--rule);
|
||||
border-radius:4px; padding:26px 26px 18px; margin:26px 0 30px; }
|
||||
.planche h4 { font-family:var(--titre); font-size:.95rem; font-weight:700;
|
||||
margin:0 0 3px; letter-spacing:-.005em; }
|
||||
.planche .note { font-size:.88rem; color:var(--muted); margin:0 0 18px;
|
||||
max-width:64ch; line-height:1.5; }
|
||||
svg { width:100%; height:auto; display:block; overflow:visible; }
|
||||
.grille { stroke:var(--rule); stroke-width:1; }
|
||||
.axe { fill:var(--muted); font-size:12.5px; }
|
||||
.axe.unite { font-size:11.5px; letter-spacing:.02em; }
|
||||
.compte { fill:var(--muted); font-size:11px; }
|
||||
.val { fill:var(--ink-2); font-size:12px; font-weight:500; }
|
||||
.barre-nuit { fill:var(--stock); opacity:.62; }
|
||||
.barre-haut { fill:var(--stock); }
|
||||
.barre-bas { fill:var(--reseau); }
|
||||
.genou { stroke:var(--reseau); stroke-width:1.5; stroke-dasharray:5 4; }
|
||||
text.genou { fill:var(--reseau); stroke:none; }
|
||||
.seuil { stroke:var(--solaire); stroke-width:1.5; stroke-dasharray:4 3; }
|
||||
text.seuil { fill:var(--solaire-d); stroke:none; }
|
||||
.seuil-etat { stroke:var(--reseau); stroke-width:2; }
|
||||
text.seuil-etat { fill:var(--reseau); stroke:none; }
|
||||
.etiq { font-size:12.5px; font-weight:600; letter-spacing:.01em; }
|
||||
.b-sol { fill:var(--solaire); }
|
||||
.b-res { fill:var(--reseau); opacity:.85; }
|
||||
.pt-mai { fill:var(--ground); stroke:var(--ink-2); stroke-width:1.6; }
|
||||
.ligne-mai { fill:none; stroke:var(--ink-2); stroke-width:1.6; opacity:.55; }
|
||||
.legende { display:flex; flex-wrap:wrap; gap:20px; margin-top:14px;
|
||||
font-family:var(--mono); font-size:.72rem; color:var(--muted); }
|
||||
.legende span { display:inline-flex; align-items:center; gap:7px; }
|
||||
.legende i { width:11px; height:11px; border-radius:2px; display:inline-block; }
|
||||
|
||||
/* --- tableau --- */
|
||||
.enrobe { overflow-x:auto; margin:26px 0 10px;
|
||||
border:1px solid var(--rule); border-radius:4px; background:var(--surface); }
|
||||
table { border-collapse:collapse; width:100%; min-width:720px; font-size:.9rem; }
|
||||
th { font-size:.68rem; letter-spacing:.1em; text-transform:uppercase;
|
||||
color:var(--muted); font-weight:600; text-align:left; padding:15px 14px 11px;
|
||||
border-bottom:1px solid var(--rule); white-space:nowrap; }
|
||||
td { padding:13px 14px; border-bottom:1px solid var(--rule); vertical-align:middle; }
|
||||
tr:last-child td { border-bottom:0; }
|
||||
td.n, th.n { text-align:right; font-family:var(--mono);
|
||||
font-variant-numeric:tabular-nums; }
|
||||
td.code { font-weight:700; font-size:1rem; width:42px; }
|
||||
td.forte { font-weight:600; font-size:1rem; }
|
||||
.sur { color:var(--muted); font-size:.78rem; font-weight:400; }
|
||||
tr.etat { background:color-mix(in srgb, var(--reseau) 9%, transparent); }
|
||||
tr.etat td.code { color:var(--reseau); font-size:.8rem; font-weight:600; }
|
||||
tr.bon td.code { color:var(--stock); }
|
||||
tr.faible td.code { color:var(--muted); }
|
||||
.jauge { min-width:126px; }
|
||||
.jauge span { display:block; height:7px; border-radius:4px;
|
||||
background:var(--surface-2); position:relative; overflow:hidden; }
|
||||
.jauge span::after { content:""; position:absolute; inset:0 auto 0 0;
|
||||
width:var(--p); background:var(--stock); border-radius:4px; }
|
||||
.jauge em { font-style:normal; font-size:.74rem; color:var(--muted);
|
||||
display:block; margin-top:5px; font-variant-numeric:tabular-nums; }
|
||||
|
||||
/* --- chiffres cles --- */
|
||||
.cles { display:grid; grid-template-columns:repeat(auto-fit,minmax(168px,1fr));
|
||||
gap:1px; background:var(--rule); border:1px solid var(--rule);
|
||||
border-radius:4px; overflow:hidden; margin:28px 0; }
|
||||
.cles div { background:var(--surface); padding:20px 20px 18px; }
|
||||
.cles b { font-family:var(--titre); font-size:2.1rem; font-weight:700;
|
||||
display:block; line-height:1; letter-spacing:-.03em; }
|
||||
.cles b small { font-size:.9rem; font-weight:500; color:var(--muted);
|
||||
letter-spacing:0; }
|
||||
.cles span { font-size:.84rem; color:var(--muted); display:block; margin-top:8px;
|
||||
line-height:1.42; }
|
||||
|
||||
/* --- listes --- */
|
||||
ol.etapes { list-style:none; counter-reset:e; padding:0; margin:26px 0; }
|
||||
ol.etapes li { counter-increment:e; position:relative; padding:0 0 22px 46px; }
|
||||
ol.etapes li::before { content:counter(e); position:absolute; left:0; top:1px;
|
||||
font-family:var(--titre); font-weight:700; font-size:.82rem;
|
||||
width:28px; height:28px; border-radius:50%; background:var(--stock);
|
||||
color:var(--surface); display:grid; place-items:center; }
|
||||
ol.etapes b { font-family:var(--titre); font-weight:700; }
|
||||
ul.puce { list-style:none; padding:0; margin:18px 0; }
|
||||
ul.puce li { padding:0 0 13px 22px; position:relative; }
|
||||
ul.puce li::before { content:""; position:absolute; left:2px; top:.72em;
|
||||
width:6px; height:6px; border-radius:50%; background:var(--stock); }
|
||||
.tag { font-family:var(--mono); font-size:.66rem; letter-spacing:.09em;
|
||||
text-transform:uppercase; padding:3px 8px; border-radius:3px;
|
||||
background:var(--surface-2); color:var(--ink-2); white-space:nowrap; }
|
||||
.reserve { border-left:3px solid var(--rule); padding-left:22px;
|
||||
color:var(--ink-2); font-size:.97rem; margin:26px 0; max-width:62ch; }
|
||||
.reserve strong { color:var(--ink); }
|
||||
footer { margin-top:78px; padding-top:26px; border-top:1px solid var(--rule);
|
||||
font-family:var(--mono); font-size:.72rem; color:var(--muted); line-height:1.8; }
|
||||
</style>
|
||||
|
||||
<div class="page">
|
||||
|
||||
<p class="surtitre">Installation Airtria · 4 septembre 2026</p>
|
||||
<h1>Dimensionner le parc batterie</h1>
|
||||
<p class="chapeau col">Combien de stockage faut-il pour traverser la nuit sans réseau —
|
||||
et à partir de quel point chaque module supplémentaire cesse de servir à quelque chose.</p>
|
||||
|
||||
<div class="verdict">
|
||||
<p class="gros">Aujourd'hui, la batterie passe la nuit seule 1 fois sur 37.</p>
|
||||
<p>Les 7 modules actifs délivrent 10.7 kWh à la maison. La nuit médiane
|
||||
en demande <strong>13,2</strong>, et la plus lourde observée <strong>17,2</strong>.
|
||||
Le réseau n'est pas un confort : c'est de l'arithmétique.</p>
|
||||
</div>
|
||||
|
||||
<div class="cles">
|
||||
<div><b>13,2<small> kWh</small></b><span>nuit médiane, maison seule, de 20 h à 9 h</span></div>
|
||||
<div><b>15,9<small> kWh</small></b><span>9 nuits sur 10 restent en dessous</span></div>
|
||||
<div><b>1,65<small> kWh</small></b><span>délivré par module, mesuré — pas 2,4 de plaque</span></div>
|
||||
<div><b>37</b><span>nuits complètes mesurées, juillet à septembre</span></div>
|
||||
</div>
|
||||
|
||||
<h2>Ce que la nuit demande</h2>
|
||||
<p class="sous">37 nuits complètes · voiture déduite</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Chaque barre compte les nuits dont la consommation tombe dans une tranche
|
||||
d'un demi-kilowattheure. La distribution est <strong>serrée</strong> : les deux
|
||||
tiers des nuits tiennent entre 12,4 et 14,4 kWh. C'est une bonne nouvelle
|
||||
pour dimensionner — il n'y a pas de queue lointaine à couvrir.</p>
|
||||
<p>Les traits verticaux marquent ce que chaque scénario sait délivrer. Tout ce
|
||||
qui est <em class="i">à gauche</em> du trait est couvert.</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Répartition des nuits, et ce que chaque scénario couvre</h4>
|
||||
<p class="note">Consommation de la maison seule entre 20 h et 9 h, la
|
||||
charge du véhicule soustraite. Source : statistiques long terme de Home Assistant,
|
||||
fin juillet au 4 septembre 2026.</p>
|
||||
<svg viewBox="0 0 1000 330" role="img" aria-label="Répartition des 37 nuits">
|
||||
<line class="grille" x1="119" y1="46" x2="119" y2="250"/>
|
||||
<text class="axe" x="119" y="274" text-anchor="middle">10</text>
|
||||
<line class="grille" x1="208" y1="46" x2="208" y2="250"/>
|
||||
<text class="axe" x="208" y="274" text-anchor="middle">11</text>
|
||||
<line class="grille" x1="297" y1="46" x2="297" y2="250"/>
|
||||
<text class="axe" x="297" y="274" text-anchor="middle">12</text>
|
||||
<line class="grille" x1="386" y1="46" x2="386" y2="250"/>
|
||||
<text class="axe" x="386" y="274" text-anchor="middle">13</text>
|
||||
<line class="grille" x1="476" y1="46" x2="476" y2="250"/>
|
||||
<text class="axe" x="476" y="274" text-anchor="middle">14</text>
|
||||
<line class="grille" x1="565" y1="46" x2="565" y2="250"/>
|
||||
<text class="axe" x="565" y="274" text-anchor="middle">15</text>
|
||||
<line class="grille" x1="654" y1="46" x2="654" y2="250"/>
|
||||
<text class="axe" x="654" y="274" text-anchor="middle">16</text>
|
||||
<line class="grille" x1="744" y1="46" x2="744" y2="250"/>
|
||||
<text class="axe" x="744" y="274" text-anchor="middle">17</text>
|
||||
<line class="grille" x1="833" y1="46" x2="833" y2="250"/>
|
||||
<text class="axe" x="833" y="274" text-anchor="middle">18</text>
|
||||
<line class="grille" x1="922" y1="46" x2="922" y2="250"/>
|
||||
<text class="axe" x="922" y="274" text-anchor="middle">19</text>
|
||||
<text class="axe unite" x="940" y="298" text-anchor="end">kWh consommés par la maison, de 20 h à 9 h</text>
|
||||
<rect class="barre-nuit" x="120.1" y="231.3" width="41.6" height="18.7" rx="2"><title>1 nuit(s) entre 10.0 et 10.5 kWh</title></rect>
|
||||
<text class="compte" x="141" y="224" text-anchor="middle">1</text>
|
||||
<rect class="barre-nuit" x="209.4" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 11.0 et 11.5 kWh</title></rect>
|
||||
<text class="compte" x="230" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="254.1" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 11.5 et 12.0 kWh</title></rect>
|
||||
<text class="compte" x="275" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="298.7" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 12.0 et 12.5 kWh</title></rect>
|
||||
<text class="compte" x="320" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="343.3" y="82.0" width="41.6" height="168.0" rx="2"><title>9 nuit(s) entre 12.5 et 13.0 kWh</title></rect>
|
||||
<text class="compte" x="364" y="75" text-anchor="middle">9</text>
|
||||
<rect class="barre-nuit" x="388.0" y="156.7" width="41.6" height="93.3" rx="2"><title>5 nuit(s) entre 13.0 et 13.5 kWh</title></rect>
|
||||
<text class="compte" x="409" y="150" text-anchor="middle">5</text>
|
||||
<rect class="barre-nuit" x="432.6" y="119.3" width="41.6" height="130.7" rx="2"><title>7 nuit(s) entre 13.5 et 14.0 kWh</title></rect>
|
||||
<text class="compte" x="453" y="112" text-anchor="middle">7</text>
|
||||
<rect class="barre-nuit" x="477.3" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 14.0 et 14.5 kWh</title></rect>
|
||||
<text class="compte" x="498" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="566.5" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 15.0 et 15.5 kWh</title></rect>
|
||||
<text class="compte" x="587" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="611.2" y="212.7" width="41.6" height="37.3" rx="2"><title>2 nuit(s) entre 15.5 et 16.0 kWh</title></rect>
|
||||
<text class="compte" x="632" y="206" text-anchor="middle">2</text>
|
||||
<rect class="barre-nuit" x="655.8" y="231.3" width="41.6" height="18.7" rx="2"><title>1 nuit(s) entre 16.0 et 16.5 kWh</title></rect>
|
||||
<text class="compte" x="677" y="224" text-anchor="middle">1</text>
|
||||
<rect class="barre-nuit" x="700.4" y="231.3" width="41.6" height="18.7" rx="2"><title>1 nuit(s) entre 16.5 et 17.0 kWh</title></rect>
|
||||
<text class="compte" x="721" y="224" text-anchor="middle">1</text>
|
||||
<rect class="barre-nuit" x="745.1" y="231.3" width="41.6" height="18.7" rx="2"><title>1 nuit(s) entre 17.0 et 17.5 kWh</title></rect>
|
||||
<text class="compte" x="766" y="224" text-anchor="middle">1</text>
|
||||
<line class="seuil-etat" x1="185" y1="34" x2="185" y2="250"/>
|
||||
<text class="etiq seuil-etat" x="192" y="49" text-anchor="start">Actuel · 10,7</text>
|
||||
<line class="seuil" x1="322" y1="34" x2="322" y2="250"/>
|
||||
<text class="etiq seuil" x="329" y="66" text-anchor="start">A · 12,3</text>
|
||||
<line class="seuil" x1="596" y1="34" x2="596" y2="250"/>
|
||||
<text class="etiq seuil" x="603" y="49" text-anchor="start">B · 15,3</text>
|
||||
<line class="seuil" x1="870" y1="34" x2="870" y2="250"/>
|
||||
<text class="etiq seuil" x="863" y="66" text-anchor="end">C · 18,4</text>
|
||||
<line class="seuil" x1="695" y1="34" x2="695" y2="250"/>
|
||||
<text class="etiq seuil" x="702" y="49" text-anchor="start">D · 16,5</text>
|
||||
</svg>
|
||||
<div class="legende">
|
||||
<span><i style="background:var(--stock);opacity:.62"></i>nuits mesurées</span>
|
||||
<span><i style="background:var(--reseau)"></i>parc actuel</span>
|
||||
<span><i style="background:var(--solaire)"></i>seuil d'un scénario</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Ce qu'un module délivre vraiment</h2>
|
||||
<p class="sous">576 paliers de SOC mesurés</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Un US2000C annonce 2,4 kWh. Ce n'est pas le chiffre à utiliser. En
|
||||
intégrant la puissance sur chaque palier où le SOC descend d'un point — 576
|
||||
paliers sur huit jours, en écartant ceux où le réseau apportait quoi que ce
|
||||
soit — la réalité de <em class="i">ce</em> parc apparaît :</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Énergie délivrée par point de SOC</h4>
|
||||
<p class="note">Plate à 0,169 kWh de 33 à 93 %, sur six tranches indépendantes.
|
||||
Puis un genou net : en dessous de 33 %, un point de SOC ne vaut plus que
|
||||
<strong>57 %</strong> de ce qu'il vaut en haut d'échelle. Signature
|
||||
classique d'un parc vieillissant — cohérent avec un module en panne sur huit
|
||||
et un autre qui faiblit.</p>
|
||||
<svg viewBox="0 0 1000 320" role="img" aria-label="Énergie par point de SOC">
|
||||
<line class="grille" x1="96" y1="193" x2="940" y2="193"/>
|
||||
<text class="axe" x="84" y="197" text-anchor="end">0,05</text>
|
||||
<line class="grille" x1="96" y1="149" x2="940" y2="149"/>
|
||||
<text class="axe" x="84" y="153" text-anchor="end">0,10</text>
|
||||
<line class="grille" x1="96" y1="106" x2="940" y2="106"/>
|
||||
<text class="axe" x="84" y="110" text-anchor="end">0,15</text>
|
||||
<rect class="barre-bas" x="105" y="152" width="103" height="84" rx="3"><title>88 paliers mesurés</title></rect>
|
||||
<text class="val" x="156" y="142" text-anchor="middle">0,097</text>
|
||||
<text class="axe" x="156" y="260" text-anchor="middle">21-31 %</text>
|
||||
<rect class="barre-haut" x="226" y="88" width="103" height="148" rx="3"><title>78 paliers mesurés</title></rect>
|
||||
<text class="val" x="277" y="78" text-anchor="middle">0,171</text>
|
||||
<text class="axe" x="277" y="260" text-anchor="middle">35-44 %</text>
|
||||
<rect class="barre-haut" x="346" y="90" width="103" height="146" rx="3"><title>76 paliers mesurés</title></rect>
|
||||
<text class="val" x="397" y="80" text-anchor="middle">0,169</text>
|
||||
<text class="axe" x="397" y="260" text-anchor="middle">45-54 %</text>
|
||||
<rect class="barre-haut" x="467" y="95" width="103" height="141" rx="3"><title>85 paliers mesurés</title></rect>
|
||||
<text class="val" x="518" y="85" text-anchor="middle">0,163</text>
|
||||
<text class="axe" x="518" y="260" text-anchor="middle">55-64 %</text>
|
||||
<rect class="barre-haut" x="587" y="88" width="103" height="148" rx="3"><title>80 paliers mesurés</title></rect>
|
||||
<text class="val" x="639" y="78" text-anchor="middle">0,171</text>
|
||||
<text class="axe" x="639" y="260" text-anchor="middle">65-74 %</text>
|
||||
<rect class="barre-haut" x="708" y="89" width="103" height="147" rx="3"><title>81 paliers mesurés</title></rect>
|
||||
<text class="val" x="759" y="79" text-anchor="middle">0,170</text>
|
||||
<text class="axe" x="759" y="260" text-anchor="middle">75-84 %</text>
|
||||
<rect class="barre-haut" x="828" y="90" width="103" height="146" rx="3"><title>62 paliers mesurés</title></rect>
|
||||
<text class="val" x="880" y="80" text-anchor="middle">0,169</text>
|
||||
<text class="axe" x="880" y="260" text-anchor="middle">85-94 %</text>
|
||||
<line class="genou" x1="217" y1="40" x2="217" y2="236"/>
|
||||
<text class="etiq genou" x="226" y="54">genou à 33 %</text>
|
||||
<text class="axe unite" x="940" y="288" text-anchor="end">kWh délivrés par point de SOC · 576 paliers mesurés sur 8 jours</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Dans la fenêtre réellement exploitée — le blocage de charge à 94 % en
|
||||
haut, le plancher ESS à 20 % en bas — les 7 modules actifs contiennent
|
||||
<strong>11,6 kWh</strong>, soit <strong>1,65 kWh par module</strong>.
|
||||
Après restitution par l'onduleur, 10.7 kWh arrivent à la maison.</p>
|
||||
</div>
|
||||
|
||||
<h2>Les scénarios</h2>
|
||||
<p class="sous">colonne décisive : le nombre de nuits couvertes</p>
|
||||
|
||||
<div class="enrobe">
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th></th><th>Scénario</th><th class="n">Modules</th>
|
||||
<th class="n">Utile DC</th><th class="n">Livré AC</th>
|
||||
<th class="n">Nuits</th><th>Couverture</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr class="etat">
|
||||
<td class="code">Actuel</td>
|
||||
<td>7 modules actifs — un en panne, un qui faiblit</td>
|
||||
<td class="n">7</td>
|
||||
<td class="n">11,5</td>
|
||||
<td class="n">10,7</td>
|
||||
<td class="n forte">1<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:3%"></span><em>3 %</em></td>
|
||||
</tr>
|
||||
<tr class="faible">
|
||||
<td class="code">A</td>
|
||||
<td>Réparer le module en panne — 8 modules</td>
|
||||
<td class="n">8</td>
|
||||
<td class="n">13,2</td>
|
||||
<td class="n">12,3</td>
|
||||
<td class="n forte">5<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:14%"></span><em>14 %</em></td>
|
||||
</tr>
|
||||
<tr class="bon">
|
||||
<td class="code">B</td>
|
||||
<td>A + 2 neufs — 10 modules</td>
|
||||
<td class="n">10</td>
|
||||
<td class="n">16,5</td>
|
||||
<td class="n">15,3</td>
|
||||
<td class="n forte">32<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:86%"></span><em>86 %</em></td>
|
||||
</tr>
|
||||
<tr class="bon">
|
||||
<td class="code">C</td>
|
||||
<td>A + 4 neufs — 12 modules</td>
|
||||
<td class="n">12</td>
|
||||
<td class="n">19,8</td>
|
||||
<td class="n">18,4</td>
|
||||
<td class="n forte">37<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:100%"></span><em>100 %</em></td>
|
||||
</tr>
|
||||
<tr class="bon">
|
||||
<td class="code">D</td>
|
||||
<td>4 récents + 6 neufs, vieux pack retiré</td>
|
||||
<td class="n">10</td>
|
||||
<td class="n">17,7</td>
|
||||
<td class="n">16,5</td>
|
||||
<td class="n forte">35<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:95%"></span><em>95 %</em></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Le saut décisif est entre <strong>A</strong> et <strong>B</strong> : réparer
|
||||
le module en panne ne fait passer la couverture que de 1 à 5 nuits sur 37.
|
||||
Deux modules de plus la portent à 32. <strong>Réparer seul ne résout rien.</strong></p>
|
||||
<p>Le scénario <strong>D</strong> mérite un regard : mêmes 10 modules que B, mais
|
||||
le vieux groupe retiré. Le blocage de charge à 94 % disparaît avec lui, et
|
||||
la même quantité de matériel délivre 1,1 kWh de plus.</p>
|
||||
</div>
|
||||
|
||||
<h2>Le plafond que personne ne mentionne</h2>
|
||||
<p class="sous">au-delà de la nuit, le stockage ne tourne plus</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Du stockage au-delà de la consommation nocturne <strong>ne cycle pas</strong>.
|
||||
Il se remplit, il attend, et le lendemain midi il est déjà plein — donc il
|
||||
n'absorbe rien. La nuit demande 13 à 17 kWh : au-delà d'environ douze
|
||||
modules, en été, chaque module supplémentaire est un investissement qui dort.</p>
|
||||
<p>La journée du 4 septembre le montre bien. Le réseau se tait à midi et ne
|
||||
revient jamais ; la production dépasse largement la maison tout l'après-midi ;
|
||||
et pourtant la batterie sature avant 18 h.</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Une journée entière — jeudi 4 septembre</h4>
|
||||
<p class="note">Le réseau n'intervient qu'avant midi, pendant les heures creuses
|
||||
et la reprise du plancher ESS. À partir de 11 h la production dépasse la
|
||||
maison de plusieurs kilowattheures par heure. Le surplus de l'après-midi n'a
|
||||
nulle part où aller.</p>
|
||||
<svg viewBox="0 0 1000 300" role="img" aria-label="Énergie heure par heure">
|
||||
<line class="grille" x1="74" y1="191" x2="950" y2="191"/>
|
||||
<text class="axe" x="64" y="195" text-anchor="end">1</text>
|
||||
<line class="grille" x1="74" y1="156" x2="950" y2="156"/>
|
||||
<text class="axe" x="64" y="160" text-anchor="end">2</text>
|
||||
<line class="grille" x1="74" y1="121" x2="950" y2="121"/>
|
||||
<text class="axe" x="64" y="125" text-anchor="end">3</text>
|
||||
<line class="grille" x1="74" y1="86" x2="950" y2="86"/>
|
||||
<text class="axe" x="64" y="90" text-anchor="end">4</text>
|
||||
<text class="axe" x="96" y="248" text-anchor="middle">00</text>
|
||||
<rect class="b-res" x="138.7" y="160.4" width="16.4" height="65.6" rx="1.5"><title>01 h · 1.88 kWh</title></rect>
|
||||
<rect class="b-res" x="182.5" y="127.3" width="16.4" height="98.7" rx="1.5"><title>02 h · 2.83 kWh</title></rect>
|
||||
<text class="axe" x="184" y="248" text-anchor="middle">02</text>
|
||||
<rect class="b-res" x="226.3" y="225.0" width="16.4" height="1.0" rx="1.5"><title>03 h · 0.03 kWh</title></rect>
|
||||
<rect class="b-res" x="270.1" y="225.3" width="16.4" height="0.7" rx="1.5"><title>04 h · 0.02 kWh</title></rect>
|
||||
<text class="axe" x="271" y="248" text-anchor="middle">04</text>
|
||||
<rect class="b-res" x="313.9" y="225.3" width="16.4" height="0.7" rx="1.5"><title>05 h · 0.02 kWh</title></rect>
|
||||
<rect class="b-res" x="357.7" y="178.6" width="16.4" height="47.4" rx="1.5"><title>06 h · 1.36 kWh</title></rect>
|
||||
<text class="axe" x="359" y="248" text-anchor="middle">06</text>
|
||||
<rect class="b-sol" x="383.6" y="225.3" width="16.4" height="0.7" rx="1.5"><title>07 h · 0.02 kWh</title></rect>
|
||||
<rect class="b-res" x="401.5" y="200.9" width="16.4" height="25.1" rx="1.5"><title>07 h · 0.72 kWh</title></rect>
|
||||
<rect class="b-sol" x="427.4" y="213.8" width="16.4" height="12.2" rx="1.5"><title>08 h · 0.35 kWh</title></rect>
|
||||
<rect class="b-res" x="445.3" y="195.7" width="16.4" height="30.3" rx="1.5"><title>08 h · 0.87 kWh</title></rect>
|
||||
<text class="axe" x="446" y="248" text-anchor="middle">08</text>
|
||||
<rect class="b-sol" x="471.2" y="198.8" width="16.4" height="27.2" rx="1.5"><title>09 h · 0.78 kWh</title></rect>
|
||||
<rect class="b-res" x="489.1" y="212.7" width="16.4" height="13.3" rx="1.5"><title>09 h · 0.38 kWh</title></rect>
|
||||
<rect class="b-sol" x="515.0" y="150.0" width="16.4" height="76.0" rx="1.5"><title>10 h · 2.18 kWh</title></rect>
|
||||
<rect class="b-res" x="532.9" y="220.4" width="16.4" height="5.6" rx="1.5"><title>10 h · 0.16 kWh</title></rect>
|
||||
<text class="axe" x="534" y="248" text-anchor="middle">10</text>
|
||||
<rect class="b-sol" x="558.8" y="79.5" width="16.4" height="146.5" rx="1.5"><title>11 h · 4.2 kWh</title></rect>
|
||||
<rect class="b-res" x="576.7" y="225.3" width="16.4" height="0.7" rx="1.5"><title>11 h · 0.02 kWh</title></rect>
|
||||
<rect class="b-sol" x="602.6" y="144.4" width="16.4" height="81.6" rx="1.5"><title>12 h · 2.34 kWh</title></rect>
|
||||
<text class="axe" x="621" y="248" text-anchor="middle">12</text>
|
||||
<rect class="b-sol" x="646.4" y="103.6" width="16.4" height="122.4" rx="1.5"><title>13 h · 3.51 kWh</title></rect>
|
||||
<rect class="b-sol" x="690.2" y="87.2" width="16.4" height="138.8" rx="1.5"><title>14 h · 3.98 kWh</title></rect>
|
||||
<text class="axe" x="709" y="248" text-anchor="middle">14</text>
|
||||
<rect class="b-sol" x="734.0" y="106.0" width="16.4" height="120.0" rx="1.5"><title>15 h · 3.44 kWh</title></rect>
|
||||
<rect class="b-sol" x="777.8" y="100.8" width="16.4" height="125.2" rx="1.5"><title>16 h · 3.59 kWh</title></rect>
|
||||
<text class="axe" x="797" y="248" text-anchor="middle">16</text>
|
||||
<rect class="b-sol" x="821.6" y="179.6" width="16.4" height="46.4" rx="1.5"><title>17 h · 1.33 kWh</title></rect>
|
||||
<rect class="b-sol" x="865.4" y="196.0" width="16.4" height="30.0" rx="1.5"><title>18 h · 0.86 kWh</title></rect>
|
||||
<text class="axe" x="884" y="248" text-anchor="middle">18</text>
|
||||
<rect class="b-sol" x="909.2" y="221.8" width="16.4" height="4.2" rx="1.5"><title>19 h · 0.12 kWh</title></rect>
|
||||
<polyline class="ligne-mai" points="95.9,226.0 139.7,171.2 183.5,139.1 227.3,203.7 271.1,201.9 314.9,202.6 358.7,198.1 402.5,202.6 446.3,197.0 490.1,197.0 533.9,183.1 577.7,181.7 621.5,183.4 665.3,121.7 709.1,146.1 752.9,156.9 796.7,160.8 840.5,202.6 884.3,199.5 928.1,221.8"/>
|
||||
<circle class="pt-mai" cx="95.9" cy="226.0" r="3.4"><title>00 h · maison 0 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="139.7" cy="171.2" r="3.4"><title>01 h · maison 1.57 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="183.5" cy="139.1" r="3.4"><title>02 h · maison 2.49 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="227.3" cy="203.7" r="3.4"><title>03 h · maison 0.64 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="271.1" cy="201.9" r="3.4"><title>04 h · maison 0.69 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="314.9" cy="202.6" r="3.4"><title>05 h · maison 0.67 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="358.7" cy="198.1" r="3.4"><title>06 h · maison 0.8 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="402.5" cy="202.6" r="3.4"><title>07 h · maison 0.67 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="446.3" cy="197.0" r="3.4"><title>08 h · maison 0.83 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="490.1" cy="197.0" r="3.4"><title>09 h · maison 0.83 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="533.9" cy="183.1" r="3.4"><title>10 h · maison 1.23 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="577.7" cy="181.7" r="3.4"><title>11 h · maison 1.27 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="621.5" cy="183.4" r="3.4"><title>12 h · maison 1.22 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="665.3" cy="121.7" r="3.4"><title>13 h · maison 2.99 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="709.1" cy="146.1" r="3.4"><title>14 h · maison 2.29 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="752.9" cy="156.9" r="3.4"><title>15 h · maison 1.98 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="796.7" cy="160.8" r="3.4"><title>16 h · maison 1.87 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="840.5" cy="202.6" r="3.4"><title>17 h · maison 0.67 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="884.3" cy="199.5" r="3.4"><title>18 h · maison 0.76 kWh</title></circle>
|
||||
<circle class="pt-mai" cx="928.1" cy="221.8" r="3.4"><title>19 h · maison 0.12 kWh</title></circle>
|
||||
<text class="axe unite" x="950" y="276" text-anchor="end">kWh par heure · jeudi 4 septembre 2026</text>
|
||||
</svg>
|
||||
<div class="legende">
|
||||
<span><i style="background:var(--solaire)"></i>production solaire</span>
|
||||
<span><i style="background:var(--reseau);opacity:.85"></i>réseau importé</span>
|
||||
<span><i style="background:var(--ink-2);opacity:.55"></i>maison</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Le lendemain est annoncé à <strong>57,4 kWh</strong>. En face : une maison
|
||||
à 30, une batterie qui peut en prendre 8, et pas de voiture — elle part à 8 h 50.
|
||||
<strong>Une trentaine de kilowattheures seront refusés</strong>, et même douze
|
||||
modules n'y changeraient presque rien.</p>
|
||||
<p>Le surplus de milieu de journée n'est pas un problème de stockage. C'est un
|
||||
problème de preneur. La voiture absorbe déjà 9,8 kWh par jour en médiane :
|
||||
c'est le meilleur rendement de la liste, et il ne coûte rien.</p>
|
||||
</div>
|
||||
|
||||
<h2>Le point dur : les quatre vieux modules</h2>
|
||||
<p class="sous">là où se joue vraiment la décision</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Un module mort, un autre qui faiblit, et un pack qui <strong>bloque la charge
|
||||
à 94 %</strong> — tous dans le groupe le plus ancien. Or dans un groupe
|
||||
Pylontech en parallèle, le BMS gouverne l'ensemble : <strong>le pack faible impose
|
||||
sa loi aux modules neufs</strong>.</p>
|
||||
<p>Ajouter des modules neufs derrière quatre modules fatigués, c'est les faire
|
||||
vieillir au rythme des anciens et hériter du plafond de 94 %. L'observation
|
||||
du propriétaire va dans le même sens : rebrancher le module isolé ferait
|
||||
peut-être <em class="i">descendre</em> le blocage à 85 %.</p>
|
||||
<p>Ce n'est pas un module à récupérer. C'est un groupe à trancher.</p>
|
||||
</div>
|
||||
|
||||
<h3>Réparation, garantie, reprise</h3>
|
||||
<div class="col">
|
||||
<p><span class="tag">à confirmer auprès du distributeur</span></p>
|
||||
<ul class="puce">
|
||||
<li><b>Lire les logs, oui.</b> L'outil est <strong>BatteryView</strong>, de
|
||||
Pylontech, sur le port console RS232 du module : historique d'alarmes, tensions
|
||||
par cellule, nombre de cycles. C'est ce qui distingue une <em class="i">cellule
|
||||
dérivante</em> — souvent récupérable par plusieurs charges lentes et complètes
|
||||
qui laissent le BMS équilibrer — d'un <em class="i">verrouillage par décharge
|
||||
profonde</em>, que certains distributeurs relancent par une source externe à
|
||||
faible courant.</li>
|
||||
<li><b>Réparation : non.</b> Le BMS est intégré et le module scellé. Un
|
||||
remplacement de cellules par un atelier tiers annule la garantie.</li>
|
||||
<li><b>Garantie : c'est la vraie piste.</b> Les US2000C sont couverts une dizaine
|
||||
d'années sous conditions, et le recours passe par le <strong>distributeur</strong>,
|
||||
pas par Pylontech. Avec les logs, le nombre de cycles et six mois de traçabilité
|
||||
d'usage, le dossier est défendable.</li>
|
||||
<li><b>Reprise : aucun programme connu.</b> La fin de vie relève de la filière
|
||||
DEEE — du recyclage, pas de la valeur.</li>
|
||||
<li><b>À vérifier avant de commander :</b> l'US2000C est-il encore commercialisé ?
|
||||
S'il ne l'est plus, les scénarios B et C tombent et la question devient celle
|
||||
d'un parc homogène neuf.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2>Ce que je ferais</h2>
|
||||
<p class="sous">dans cet ordre, sans tout décider aujourd'hui</p>
|
||||
|
||||
<ol class="etapes col">
|
||||
<li><b>Faire lire les logs des quatre vieux modules</b>, pas seulement celui en
|
||||
panne. Vous saurez si vous avez un module à remplacer ou un groupe à retirer —
|
||||
et cela ne coûte rien.</li>
|
||||
<li><b>Brancher le second véhicule</b> les jours de forte production. Vous saurez
|
||||
en une journée combien de kilowattheures un second preneur absorbe réellement,
|
||||
et ce chiffre déplace le dimensionnement.</li>
|
||||
<li><b>Viser 10 à 12 modules équivalents neufs</b>, soit 16 à 20 kWh utiles.
|
||||
C'est la plage qui couvre 85 à 100 % des nuits d'été et qui cycle tous les jours.</li>
|
||||
<li><b>Si les logs condamnent le vieux groupe, ne pas rafistoler.</b> Un parc
|
||||
homogène neuf donne la même capacité en moins d'unités, avec une garantie neuve
|
||||
et un plafond de charge qui ne vous suit plus.</li>
|
||||
</ol>
|
||||
|
||||
<div class="reserve">
|
||||
<p><strong>Ces chiffres sont tous d'été.</strong> Les compteurs exploitables ne
|
||||
remontent qu'à fin juillet. L'hiver, la nuit dure 17 heures au lieu de 13 et la
|
||||
production ne recharge pas : aucun dimensionnement raisonnable ne fera passer un
|
||||
hiver breton sans réseau, et la stratégie des deux charges en heures creuses
|
||||
restera la bonne.</p>
|
||||
<p><strong>Dimensionnez pour vos nuits d'été, pas contre l'hiver.</strong> C'est
|
||||
en été que le stockage travaille tous les jours, et c'est en été que chaque
|
||||
kilowattheure stocké est gratuit.</p>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
Sources : 37 nuits complètes et 38 journées issues des statistiques long terme de
|
||||
Home Assistant (fin juillet – 4 septembre 2026) · courbe énergie/SOC établie sur
|
||||
576 paliers mesurés · relevé horaire du 4 septembre issu de la base
|
||||
d'historisation.<br>
|
||||
Capacité par module mesurée sur le parc réel, blocage de charge à 94 % et
|
||||
plancher ESS à 20 % inclus. Rendement de restitution retenu : 93 %.
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
535
tools/gen-page-batteries.py
Normal file
535
tools/gen-page-batteries.py
Normal file
@@ -0,0 +1,535 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Page de decision : dimensionnement du parc batterie.
|
||||
|
||||
Rejouable. Toutes les valeurs viennent des mesures du 04/09/2026 :
|
||||
37 nuits completes (statistiques long terme Home Assistant, juillet-septembre)
|
||||
et la courbe energie/SOC etablie sur 576 paliers.
|
||||
"""
|
||||
import json, pathlib
|
||||
|
||||
NUITS = [10.2,11,11.2,11.6,11.9,12.4,12.4,12.5,12.5,12.6,12.6,12.7,12.8,12.9,
|
||||
12.9,12.9,13.1,13.1,13.2,13.4,13.4,13.5,13.6,13.7,13.7,13.7,13.9,13.9,
|
||||
14.2,14.4,15,15.2,15.6,15.9,16.4,16.7,17.2]
|
||||
|
||||
# kWh utiles par module, mesures. 1,65 dans la fenetre reelle (blocage a 94 %,
|
||||
# plancher ESS a 20 %) ; 1,77 si le blocage a 94 % disparait avec le vieux pack.
|
||||
BRIDE, LIBRE = 1.65, 1.77
|
||||
ONDULEUR = 0.93 # rendement de restitution vers la maison
|
||||
|
||||
SCENARIOS = [
|
||||
("Actuel", "7 modules actifs — un en panne, un qui faiblit", 7, BRIDE, "etat"),
|
||||
("A", "Réparer le module en panne — 8 modules", 8, BRIDE, "faible"),
|
||||
("B", "A + 2 neufs — 10 modules", 10, BRIDE, "bon"),
|
||||
("C", "A + 4 neufs — 12 modules", 12, BRIDE, "bon"),
|
||||
("D", "4 récents + 6 neufs, vieux pack retiré", 10, LIBRE, "bon"),
|
||||
]
|
||||
|
||||
TRANCHES = [("21-31", 0.097, 88), ("35-44", 0.171, 78), ("45-54", 0.169, 76),
|
||||
("55-64", 0.163, 85), ("65-74", 0.171, 80), ("75-84", 0.170, 81),
|
||||
("85-94", 0.169, 62)]
|
||||
|
||||
JOURNEE = [("00",0.00,0,0,0),("01",0.00,1.88,1.57,1.30),("02",0.00,2.83,2.49,1.83),
|
||||
("03",0.00,0.03,0.64,0),("04",0.00,0.02,0.69,0),("05",0.00,0.02,0.67,0),
|
||||
("06",0.00,1.36,0.80,0),("07",0.02,0.72,0.67,0),("08",0.35,0.87,0.83,0),
|
||||
("09",0.78,0.38,0.83,0),("10",2.18,0.16,1.23,0),("11",4.20,0.02,1.27,0),
|
||||
("12",2.34,0.00,1.22,0),("13",3.51,0.00,2.99,0.96),("14",3.98,0.00,2.29,0.14),
|
||||
("15",3.44,0.00,1.98,0),("16",3.59,0.00,1.87,0),("17",1.33,0.00,0.67,0),
|
||||
("18",0.86,0.00,0.76,0.07),("19",0.12,0.00,0.12,0.09)]
|
||||
|
||||
def couvre(ac):
|
||||
return sum(1 for n in NUITS if n <= ac + 1e-9)
|
||||
|
||||
def calc():
|
||||
out = []
|
||||
for code, nom, mods, par, ton in SCENARIOS:
|
||||
dc = mods * par
|
||||
ac = dc * ONDULEUR
|
||||
n = couvre(ac)
|
||||
out.append(dict(code=code, nom=nom, mods=mods, dc=dc, ac=ac,
|
||||
n=n, pct=round(100 * n / len(NUITS)), ton=ton))
|
||||
return out
|
||||
|
||||
# ----------------------------------------------------------------- graphiques
|
||||
def histo_nuits(sc):
|
||||
"""Repartition des 37 nuits, avec les seuils de chaque scenario."""
|
||||
x0, x1, lo, hi = 74, 940, 9.5, 19.2
|
||||
px = lambda v: x0 + (v - lo) / (hi - lo) * (x1 - x0)
|
||||
bins = {}
|
||||
for v in NUITS:
|
||||
b = int((v - lo) // 0.5)
|
||||
bins[b] = bins.get(b, 0) + 1
|
||||
mx = max(bins.values())
|
||||
base, hmax = 250, 168
|
||||
s = [f'<svg viewBox="0 0 1000 330" role="img" aria-label="Répartition des 37 nuits">']
|
||||
# grille
|
||||
for v in range(10, 20):
|
||||
s.append(f'<line class="grille" x1="{px(v):.0f}" y1="46" x2="{px(v):.0f}" y2="{base}"/>')
|
||||
s.append(f'<text class="axe" x="{px(v):.0f}" y="{base+24}" text-anchor="middle">{v}</text>')
|
||||
s.append(f'<text class="axe unite" x="{x1}" y="{base+48}" text-anchor="end">kWh consommés par la maison, de 20 h à 9 h</text>')
|
||||
for b, n in sorted(bins.items()):
|
||||
g = lo + b * 0.5
|
||||
w = (px(g + 0.5) - px(g)) - 3
|
||||
h = n / mx * hmax
|
||||
s.append(f'<rect class="barre-nuit" x="{px(g)+1.5:.1f}" y="{base-h:.1f}" '
|
||||
f'width="{w:.1f}" height="{h:.1f}" rx="2"><title>{n} nuit(s) entre '
|
||||
f'{g:.1f} et {g+0.5:.1f} kWh</title></rect>')
|
||||
s.append(f'<text class="compte" x="{px(g+0.25):.0f}" y="{base-h-7:.0f}" text-anchor="middle">{n}</text>')
|
||||
# seuils
|
||||
for i, r in enumerate(sc):
|
||||
if r['ac'] > hi or r['ac'] < lo: continue
|
||||
x = px(r['ac'])
|
||||
cl = 'seuil-etat' if r['ton'] == 'etat' else 'seuil'
|
||||
s.append(f'<line class="{cl}" x1="{x:.0f}" y1="34" x2="{x:.0f}" y2="{base}"/>')
|
||||
anc = 'end' if r['ac'] > 17.4 else 'start'
|
||||
dx = -7 if anc == 'end' else 7
|
||||
y = 34 + 15 + (i % 2) * 17
|
||||
s.append(f'<text class="etiq {cl}" x="{x+dx:.0f}" y="{y}" text-anchor="{anc}">'
|
||||
f'{r["code"]} · {r["ac"]:.1f}'.replace(".", ",") + '</text>')
|
||||
s.append('</svg>')
|
||||
return '\n'.join(s)
|
||||
|
||||
def courbe_batterie():
|
||||
x0, x1, base, hmax = 96, 940, 236, 156
|
||||
n = len(TRANCHES)
|
||||
w = (x1 - x0) / n
|
||||
mx = 0.18
|
||||
s = ['<svg viewBox="0 0 1000 320" role="img" aria-label="Énergie par point de SOC">']
|
||||
for v, lab in [(0.05,'0,05'), (0.10,'0,10'), (0.15,'0,15')]:
|
||||
y = base - v / mx * hmax
|
||||
s.append(f'<line class="grille" x1="{x0}" y1="{y:.0f}" x2="{x1}" y2="{y:.0f}"/>')
|
||||
s.append(f'<text class="axe" x="{x0-12}" y="{y+4:.0f}" text-anchor="end">{lab}</text>')
|
||||
for i, (lab, k, np_) in enumerate(TRANCHES):
|
||||
h = k / mx * hmax
|
||||
x = x0 + i * w + 9
|
||||
cl = 'barre-bas' if k < 0.12 else 'barre-haut'
|
||||
s.append(f'<rect class="{cl}" x="{x:.0f}" y="{base-h:.0f}" width="{w-18:.0f}" '
|
||||
f'height="{h:.0f}" rx="3"><title>{np_} paliers mesurés</title></rect>')
|
||||
s.append(f'<text class="val" x="{x+(w-18)/2:.0f}" y="{base-h-10:.0f}" text-anchor="middle">'
|
||||
f'{k:.3f}".replace"</text>'.replace('".replace"', '').replace('.', ','))
|
||||
s.append(f'<text class="axe" x="{x+(w-18)/2:.0f}" y="{base+24:.0f}" text-anchor="middle">{lab} %</text>')
|
||||
xg = x0 + 1 * w
|
||||
s.append(f'<line class="genou" x1="{xg:.0f}" y1="40" x2="{xg:.0f}" y2="{base}"/>')
|
||||
s.append(f'<text class="etiq genou" x="{xg+9:.0f}" y="54">genou à 33 %</text>')
|
||||
s.append(f'<text class="axe unite" x="{x1}" y="{base+52}" text-anchor="end">kWh délivrés par point de SOC · 576 paliers mesurés sur 8 jours</text>')
|
||||
s.append('</svg>')
|
||||
return '\n'.join(s)
|
||||
|
||||
def journee():
|
||||
x0, x1, base, hmax = 74, 950, 226, 150
|
||||
n = len(JOURNEE)
|
||||
w = (x1 - x0) / n
|
||||
mx = 4.3
|
||||
s = ['<svg viewBox="0 0 1000 300" role="img" aria-label="Énergie heure par heure">']
|
||||
for v in (1, 2, 3, 4):
|
||||
y = base - v / mx * hmax
|
||||
s.append(f'<line class="grille" x1="{x0}" y1="{y:.0f}" x2="{x1}" y2="{y:.0f}"/>')
|
||||
s.append(f'<text class="axe" x="{x0-10}" y="{y+4:.0f}" text-anchor="end">{v}</text>')
|
||||
for i, (h, sol, res, mai, voi) in enumerate(JOURNEE):
|
||||
x = x0 + i * w
|
||||
bw = (w - 8) / 2
|
||||
for j, (v, cl) in enumerate([(sol, 'sol'), (res, 'res')]):
|
||||
if v <= 0: continue
|
||||
ht = v / mx * hmax
|
||||
s.append(f'<rect class="b-{cl}" x="{x+3+j*bw:.1f}" y="{base-ht:.1f}" '
|
||||
f'width="{bw-1.5:.1f}" height="{ht:.1f}" rx="1.5"><title>{h} h · {v} kWh</title></rect>')
|
||||
if i % 2 == 0:
|
||||
s.append(f'<text class="axe" x="{x+w/2:.0f}" y="{base+22:.0f}" text-anchor="middle">{h}</text>')
|
||||
pts = ' '.join(f'{x0+i*w+w/2:.1f},{base-m/mx*hmax:.1f}' for i,(_,_,_,m,_) in enumerate(JOURNEE))
|
||||
s.append(f'<polyline class="ligne-mai" points="{pts}"/>')
|
||||
for i, (h, _, _, mai, _) in enumerate(JOURNEE):
|
||||
y = base - mai / mx * hmax
|
||||
s.append(f'<circle class="pt-mai" cx="{x0+i*w+w/2:.1f}" cy="{y:.1f}" r="3.4">'
|
||||
f'<title>{h} h · maison {mai} kWh</title></circle>')
|
||||
s.append(f'<text class="axe unite" x="{x1}" y="{base+50}" text-anchor="end">kWh par heure · jeudi 4 septembre 2026</text>')
|
||||
s.append('</svg>')
|
||||
return '\n'.join(s)
|
||||
|
||||
sc = calc()
|
||||
act = sc[0]
|
||||
b = next(r for r in sc if r['code'] == 'B')
|
||||
c = next(r for r in sc if r['code'] == 'C')
|
||||
|
||||
lignes_sc = '\n'.join(f''' <tr class="{r['ton']}">
|
||||
<td class="code">{r['code']}</td>
|
||||
<td>{r['nom']}</td>
|
||||
<td class="n">{r['mods']}</td>
|
||||
<td class="n">{r['dc']:.1f}</td>
|
||||
<td class="n">{r['ac']:.1f}</td>
|
||||
<td class="n forte">{r['n']}<span class="sur">/37</span></td>
|
||||
<td class="jauge"><span style="--p:{r['pct']}%"></span><em>{r['pct']} %</em></td>
|
||||
</tr>'''.replace('.', ',').replace(',1f', '.1f') for r in sc)
|
||||
|
||||
html = f'''<title>Dimensionner le parc batterie</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,500;12..96,700&family=IBM+Plex+Mono:wght@400;600&family=Newsreader:ital,opsz,wght@0,6..72,300;0,6..72,400;0,6..72,600;1,6..72,400&display=swap">
|
||||
<style>
|
||||
:root {{
|
||||
--ground:#e7eaee; --surface:#f6f8f9; --surface-2:#dde3e8;
|
||||
--ink:#101821; --ink-2:#3d4a57; --muted:#6b7885; --rule:#c6cfd7;
|
||||
--solaire:#c9791a; --solaire-d:#a35f10; --stock:#166b78; --stock-d:#0f4e58;
|
||||
--reseau:#a8422c; --vert:#3f6b3a;
|
||||
--mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;
|
||||
--titre:"Bricolage Grotesque","Helvetica Neue",Arial,sans-serif;
|
||||
--corps:"Newsreader",Georgia,"Times New Roman",serif;
|
||||
}}
|
||||
@media (prefers-color-scheme: dark) {{
|
||||
:root:not([data-theme="light"]) {{
|
||||
--ground:#0d1319; --surface:#141c24; --surface-2:#1d2831;
|
||||
--ink:#e4eaef; --ink-2:#b3c0cb; --muted:#8695a2; --rule:#2b3945;
|
||||
--solaire:#e79a3c; --solaire-d:#c47d24; --stock:#3aa5b5; --stock-d:#2b8290;
|
||||
--reseau:#d9705a; --vert:#7ab070;
|
||||
}}
|
||||
}}
|
||||
:root[data-theme="dark"] {{
|
||||
--ground:#0d1319; --surface:#141c24; --surface-2:#1d2831;
|
||||
--ink:#e4eaef; --ink-2:#b3c0cb; --muted:#8695a2; --rule:#2b3945;
|
||||
--solaire:#e79a3c; --solaire-d:#c47d24; --stock:#3aa5b5; --stock-d:#2b8290;
|
||||
--reseau:#d9705a; --vert:#7ab070;
|
||||
}}
|
||||
* {{ box-sizing:border-box; }}
|
||||
body {{ background:var(--ground); color:var(--ink); font-family:var(--corps);
|
||||
font-size:17.5px; line-height:1.62; font-weight:300;
|
||||
-webkit-font-smoothing:antialiased; padding:0 20px 96px; }}
|
||||
.page {{ max-width:1040px; margin:0 auto; }}
|
||||
.col {{ max-width:64ch; }}
|
||||
h1,h2,h3,.chapeau,.code,.n,.axe,.val,.etiq,.compte,table,.jauge em,.tag,.puce b {{
|
||||
font-family:var(--titre); }}
|
||||
h1 {{ font-size:clamp(2.3rem,5.4vw,3.9rem); line-height:1.02; font-weight:700;
|
||||
letter-spacing:-.028em; text-wrap:balance; margin:0 0 .5rem;
|
||||
max-width:15ch; }}
|
||||
.surtitre {{ font-family:var(--mono); font-size:.7rem; letter-spacing:.16em;
|
||||
text-transform:uppercase; color:var(--muted); margin:56px 0 20px; }}
|
||||
.chapeau {{ font-family:var(--corps); font-size:1.24rem; line-height:1.55;
|
||||
color:var(--ink-2); max-width:56ch; font-weight:300; }}
|
||||
h2 {{ font-size:1.62rem; font-weight:700; letter-spacing:-.018em;
|
||||
margin:72px 0 4px; text-wrap:balance; }}
|
||||
h2 + .sous {{ font-family:var(--mono); font-size:.72rem; letter-spacing:.1em;
|
||||
text-transform:uppercase; color:var(--muted); margin:0 0 22px; }}
|
||||
h3 {{ font-size:1.06rem; font-weight:700; margin:34px 0 6px; letter-spacing:-.01em; }}
|
||||
p {{ margin:0 0 1.05em; }}
|
||||
strong {{ font-weight:600; color:var(--ink); }}
|
||||
em.i {{ font-style:italic; }}
|
||||
hr {{ border:0; border-top:1px solid var(--rule); margin:64px 0; }}
|
||||
a {{ color:var(--stock); }}
|
||||
|
||||
/* --- verdict --- */
|
||||
.verdict {{ background:var(--surface); border:1px solid var(--rule);
|
||||
border-left:4px solid var(--solaire); border-radius:3px;
|
||||
padding:26px 30px; margin:38px 0 8px; max-width:66ch; }}
|
||||
.verdict p:last-child {{ margin-bottom:0; }}
|
||||
.verdict .gros {{ font-family:var(--titre); font-weight:700;
|
||||
font-size:1.3rem; line-height:1.3; letter-spacing:-.015em; }}
|
||||
|
||||
/* --- planches --- */
|
||||
.planche {{ background:var(--surface); border:1px solid var(--rule);
|
||||
border-radius:4px; padding:26px 26px 18px; margin:26px 0 30px; }}
|
||||
.planche h4 {{ font-family:var(--titre); font-size:.95rem; font-weight:700;
|
||||
margin:0 0 3px; letter-spacing:-.005em; }}
|
||||
.planche .note {{ font-size:.88rem; color:var(--muted); margin:0 0 18px;
|
||||
max-width:64ch; line-height:1.5; }}
|
||||
svg {{ width:100%; height:auto; display:block; overflow:visible; }}
|
||||
.grille {{ stroke:var(--rule); stroke-width:1; }}
|
||||
.axe {{ fill:var(--muted); font-size:12.5px; }}
|
||||
.axe.unite {{ font-size:11.5px; letter-spacing:.02em; }}
|
||||
.compte {{ fill:var(--muted); font-size:11px; }}
|
||||
.val {{ fill:var(--ink-2); font-size:12px; font-weight:500; }}
|
||||
.barre-nuit {{ fill:var(--stock); opacity:.62; }}
|
||||
.barre-haut {{ fill:var(--stock); }}
|
||||
.barre-bas {{ fill:var(--reseau); }}
|
||||
.genou {{ stroke:var(--reseau); stroke-width:1.5; stroke-dasharray:5 4; }}
|
||||
text.genou {{ fill:var(--reseau); stroke:none; }}
|
||||
.seuil {{ stroke:var(--solaire); stroke-width:1.5; stroke-dasharray:4 3; }}
|
||||
text.seuil {{ fill:var(--solaire-d); stroke:none; }}
|
||||
.seuil-etat {{ stroke:var(--reseau); stroke-width:2; }}
|
||||
text.seuil-etat {{ fill:var(--reseau); stroke:none; }}
|
||||
.etiq {{ font-size:12.5px; font-weight:600; letter-spacing:.01em; }}
|
||||
.b-sol {{ fill:var(--solaire); }}
|
||||
.b-res {{ fill:var(--reseau); opacity:.85; }}
|
||||
.pt-mai {{ fill:var(--ground); stroke:var(--ink-2); stroke-width:1.6; }}
|
||||
.ligne-mai {{ fill:none; stroke:var(--ink-2); stroke-width:1.6; opacity:.55; }}
|
||||
.legende {{ display:flex; flex-wrap:wrap; gap:20px; margin-top:14px;
|
||||
font-family:var(--mono); font-size:.72rem; color:var(--muted); }}
|
||||
.legende span {{ display:inline-flex; align-items:center; gap:7px; }}
|
||||
.legende i {{ width:11px; height:11px; border-radius:2px; display:inline-block; }}
|
||||
|
||||
/* --- tableau --- */
|
||||
.enrobe {{ overflow-x:auto; margin:26px 0 10px;
|
||||
border:1px solid var(--rule); border-radius:4px; background:var(--surface); }}
|
||||
table {{ border-collapse:collapse; width:100%; min-width:720px; font-size:.9rem; }}
|
||||
th {{ font-size:.68rem; letter-spacing:.1em; text-transform:uppercase;
|
||||
color:var(--muted); font-weight:600; text-align:left; padding:15px 14px 11px;
|
||||
border-bottom:1px solid var(--rule); white-space:nowrap; }}
|
||||
td {{ padding:13px 14px; border-bottom:1px solid var(--rule); vertical-align:middle; }}
|
||||
tr:last-child td {{ border-bottom:0; }}
|
||||
td.n, th.n {{ text-align:right; font-family:var(--mono);
|
||||
font-variant-numeric:tabular-nums; }}
|
||||
td.code {{ font-weight:700; font-size:1rem; width:42px; }}
|
||||
td.forte {{ font-weight:600; font-size:1rem; }}
|
||||
.sur {{ color:var(--muted); font-size:.78rem; font-weight:400; }}
|
||||
tr.etat {{ background:color-mix(in srgb, var(--reseau) 9%, transparent); }}
|
||||
tr.etat td.code {{ color:var(--reseau); font-size:.8rem; font-weight:600; }}
|
||||
tr.bon td.code {{ color:var(--stock); }}
|
||||
tr.faible td.code {{ color:var(--muted); }}
|
||||
.jauge {{ min-width:126px; }}
|
||||
.jauge span {{ display:block; height:7px; border-radius:4px;
|
||||
background:var(--surface-2); position:relative; overflow:hidden; }}
|
||||
.jauge span::after {{ content:""; position:absolute; inset:0 auto 0 0;
|
||||
width:var(--p); background:var(--stock); border-radius:4px; }}
|
||||
.jauge em {{ font-style:normal; font-size:.74rem; color:var(--muted);
|
||||
display:block; margin-top:5px; font-variant-numeric:tabular-nums; }}
|
||||
|
||||
/* --- chiffres cles --- */
|
||||
.cles {{ display:grid; grid-template-columns:repeat(auto-fit,minmax(168px,1fr));
|
||||
gap:1px; background:var(--rule); border:1px solid var(--rule);
|
||||
border-radius:4px; overflow:hidden; margin:28px 0; }}
|
||||
.cles div {{ background:var(--surface); padding:20px 20px 18px; }}
|
||||
.cles b {{ font-family:var(--titre); font-size:2.1rem; font-weight:700;
|
||||
display:block; line-height:1; letter-spacing:-.03em; }}
|
||||
.cles b small {{ font-size:.9rem; font-weight:500; color:var(--muted);
|
||||
letter-spacing:0; }}
|
||||
.cles span {{ font-size:.84rem; color:var(--muted); display:block; margin-top:8px;
|
||||
line-height:1.42; }}
|
||||
|
||||
/* --- listes --- */
|
||||
ol.etapes {{ list-style:none; counter-reset:e; padding:0; margin:26px 0; }}
|
||||
ol.etapes li {{ counter-increment:e; position:relative; padding:0 0 22px 46px; }}
|
||||
ol.etapes li::before {{ content:counter(e); position:absolute; left:0; top:1px;
|
||||
font-family:var(--titre); font-weight:700; font-size:.82rem;
|
||||
width:28px; height:28px; border-radius:50%; background:var(--stock);
|
||||
color:var(--surface); display:grid; place-items:center; }}
|
||||
ol.etapes b {{ font-family:var(--titre); font-weight:700; }}
|
||||
ul.puce {{ list-style:none; padding:0; margin:18px 0; }}
|
||||
ul.puce li {{ padding:0 0 13px 22px; position:relative; }}
|
||||
ul.puce li::before {{ content:""; position:absolute; left:2px; top:.72em;
|
||||
width:6px; height:6px; border-radius:50%; background:var(--stock); }}
|
||||
.tag {{ font-family:var(--mono); font-size:.66rem; letter-spacing:.09em;
|
||||
text-transform:uppercase; padding:3px 8px; border-radius:3px;
|
||||
background:var(--surface-2); color:var(--ink-2); white-space:nowrap; }}
|
||||
.reserve {{ border-left:3px solid var(--rule); padding-left:22px;
|
||||
color:var(--ink-2); font-size:.97rem; margin:26px 0; max-width:62ch; }}
|
||||
.reserve strong {{ color:var(--ink); }}
|
||||
footer {{ margin-top:78px; padding-top:26px; border-top:1px solid var(--rule);
|
||||
font-family:var(--mono); font-size:.72rem; color:var(--muted); line-height:1.8; }}
|
||||
</style>
|
||||
|
||||
<div class="page">
|
||||
|
||||
<p class="surtitre">Installation Airtria · 4 septembre 2026</p>
|
||||
<h1>Dimensionner le parc batterie</h1>
|
||||
<p class="chapeau col">Combien de stockage faut-il pour traverser la nuit sans réseau —
|
||||
et à partir de quel point chaque module supplémentaire cesse de servir à quelque chose.</p>
|
||||
|
||||
<div class="verdict">
|
||||
<p class="gros">Aujourd'hui, la batterie passe la nuit seule 1 fois sur 37.</p>
|
||||
<p>Les 7 modules actifs délivrent {act['ac']:.1f} kWh à la maison. La nuit médiane
|
||||
en demande <strong>13,2</strong>, et la plus lourde observée <strong>17,2</strong>.
|
||||
Le réseau n'est pas un confort : c'est de l'arithmétique.</p>
|
||||
</div>
|
||||
|
||||
<div class="cles">
|
||||
<div><b>13,2<small> kWh</small></b><span>nuit médiane, maison seule, de 20 h à 9 h</span></div>
|
||||
<div><b>15,9<small> kWh</small></b><span>9 nuits sur 10 restent en dessous</span></div>
|
||||
<div><b>1,65<small> kWh</small></b><span>délivré par module, mesuré — pas 2,4 de plaque</span></div>
|
||||
<div><b>37</b><span>nuits complètes mesurées, juillet à septembre</span></div>
|
||||
</div>
|
||||
|
||||
<h2>Ce que la nuit demande</h2>
|
||||
<p class="sous">37 nuits complètes · voiture déduite</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Chaque barre compte les nuits dont la consommation tombe dans une tranche
|
||||
d'un demi-kilowattheure. La distribution est <strong>serrée</strong> : les deux
|
||||
tiers des nuits tiennent entre 12,4 et 14,4 kWh. C'est une bonne nouvelle
|
||||
pour dimensionner — il n'y a pas de queue lointaine à couvrir.</p>
|
||||
<p>Les traits verticaux marquent ce que chaque scénario sait délivrer. Tout ce
|
||||
qui est <em class="i">à gauche</em> du trait est couvert.</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Répartition des nuits, et ce que chaque scénario couvre</h4>
|
||||
<p class="note">Consommation de la maison seule entre 20 h et 9 h, la
|
||||
charge du véhicule soustraite. Source : statistiques long terme de Home Assistant,
|
||||
fin juillet au 4 septembre 2026.</p>
|
||||
{histo_nuits(sc)}
|
||||
<div class="legende">
|
||||
<span><i style="background:var(--stock);opacity:.62"></i>nuits mesurées</span>
|
||||
<span><i style="background:var(--reseau)"></i>parc actuel</span>
|
||||
<span><i style="background:var(--solaire)"></i>seuil d'un scénario</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Ce qu'un module délivre vraiment</h2>
|
||||
<p class="sous">576 paliers de SOC mesurés</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Un US2000C annonce 2,4 kWh. Ce n'est pas le chiffre à utiliser. En
|
||||
intégrant la puissance sur chaque palier où le SOC descend d'un point — 576
|
||||
paliers sur huit jours, en écartant ceux où le réseau apportait quoi que ce
|
||||
soit — la réalité de <em class="i">ce</em> parc apparaît :</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Énergie délivrée par point de SOC</h4>
|
||||
<p class="note">Plate à 0,169 kWh de 33 à 93 %, sur six tranches indépendantes.
|
||||
Puis un genou net : en dessous de 33 %, un point de SOC ne vaut plus que
|
||||
<strong>57 %</strong> de ce qu'il vaut en haut d'échelle. Signature
|
||||
classique d'un parc vieillissant — cohérent avec un module en panne sur huit
|
||||
et un autre qui faiblit.</p>
|
||||
{courbe_batterie()}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Dans la fenêtre réellement exploitée — le blocage de charge à 94 % en
|
||||
haut, le plancher ESS à 20 % en bas — les 7 modules actifs contiennent
|
||||
<strong>11,6 kWh</strong>, soit <strong>1,65 kWh par module</strong>.
|
||||
Après restitution par l'onduleur, {act['ac']:.1f} kWh arrivent à la maison.</p>
|
||||
</div>
|
||||
|
||||
<h2>Les scénarios</h2>
|
||||
<p class="sous">colonne décisive : le nombre de nuits couvertes</p>
|
||||
|
||||
<div class="enrobe">
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th></th><th>Scénario</th><th class="n">Modules</th>
|
||||
<th class="n">Utile DC</th><th class="n">Livré AC</th>
|
||||
<th class="n">Nuits</th><th>Couverture</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{lignes_sc}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Le saut décisif est entre <strong>A</strong> et <strong>B</strong> : réparer
|
||||
le module en panne ne fait passer la couverture que de 1 à 5 nuits sur 37.
|
||||
Deux modules de plus la portent à 32. <strong>Réparer seul ne résout rien.</strong></p>
|
||||
<p>Le scénario <strong>D</strong> mérite un regard : mêmes 10 modules que B, mais
|
||||
le vieux groupe retiré. Le blocage de charge à 94 % disparaît avec lui, et
|
||||
la même quantité de matériel délivre 1,1 kWh de plus.</p>
|
||||
</div>
|
||||
|
||||
<h2>Le plafond que personne ne mentionne</h2>
|
||||
<p class="sous">au-delà de la nuit, le stockage ne tourne plus</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Du stockage au-delà de la consommation nocturne <strong>ne cycle pas</strong>.
|
||||
Il se remplit, il attend, et le lendemain midi il est déjà plein — donc il
|
||||
n'absorbe rien. La nuit demande 13 à 17 kWh : au-delà d'environ douze
|
||||
modules, en été, chaque module supplémentaire est un investissement qui dort.</p>
|
||||
<p>La journée du 4 septembre le montre bien. Le réseau se tait à midi et ne
|
||||
revient jamais ; la production dépasse largement la maison tout l'après-midi ;
|
||||
et pourtant la batterie sature avant 18 h.</p>
|
||||
</div>
|
||||
|
||||
<div class="planche">
|
||||
<h4>Une journée entière — jeudi 4 septembre</h4>
|
||||
<p class="note">Le réseau n'intervient qu'avant midi, pendant les heures creuses
|
||||
et la reprise du plancher ESS. À partir de 11 h la production dépasse la
|
||||
maison de plusieurs kilowattheures par heure. Le surplus de l'après-midi n'a
|
||||
nulle part où aller.</p>
|
||||
{journee()}
|
||||
<div class="legende">
|
||||
<span><i style="background:var(--solaire)"></i>production solaire</span>
|
||||
<span><i style="background:var(--reseau);opacity:.85"></i>réseau importé</span>
|
||||
<span><i style="background:var(--ink-2);opacity:.55"></i>maison</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p>Le lendemain est annoncé à <strong>57,4 kWh</strong>. En face : une maison
|
||||
à 30, une batterie qui peut en prendre 8, et pas de voiture — elle part à 8 h 50.
|
||||
<strong>Une trentaine de kilowattheures seront refusés</strong>, et même douze
|
||||
modules n'y changeraient presque rien.</p>
|
||||
<p>Le surplus de milieu de journée n'est pas un problème de stockage. C'est un
|
||||
problème de preneur. La voiture absorbe déjà 9,8 kWh par jour en médiane :
|
||||
c'est le meilleur rendement de la liste, et il ne coûte rien.</p>
|
||||
</div>
|
||||
|
||||
<h2>Le point dur : les quatre vieux modules</h2>
|
||||
<p class="sous">là où se joue vraiment la décision</p>
|
||||
|
||||
<div class="col">
|
||||
<p>Un module mort, un autre qui faiblit, et un pack qui <strong>bloque la charge
|
||||
à 94 %</strong> — tous dans le groupe le plus ancien. Or dans un groupe
|
||||
Pylontech en parallèle, le BMS gouverne l'ensemble : <strong>le pack faible impose
|
||||
sa loi aux modules neufs</strong>.</p>
|
||||
<p>Ajouter des modules neufs derrière quatre modules fatigués, c'est les faire
|
||||
vieillir au rythme des anciens et hériter du plafond de 94 %. L'observation
|
||||
du propriétaire va dans le même sens : rebrancher le module isolé ferait
|
||||
peut-être <em class="i">descendre</em> le blocage à 85 %.</p>
|
||||
<p>Ce n'est pas un module à récupérer. C'est un groupe à trancher.</p>
|
||||
</div>
|
||||
|
||||
<h3>Réparation, garantie, reprise</h3>
|
||||
<div class="col">
|
||||
<p><span class="tag">à confirmer auprès du distributeur</span></p>
|
||||
<ul class="puce">
|
||||
<li><b>Lire les logs, oui.</b> L'outil est <strong>BatteryView</strong>, de
|
||||
Pylontech, sur le port console RS232 du module : historique d'alarmes, tensions
|
||||
par cellule, nombre de cycles. C'est ce qui distingue une <em class="i">cellule
|
||||
dérivante</em> — souvent récupérable par plusieurs charges lentes et complètes
|
||||
qui laissent le BMS équilibrer — d'un <em class="i">verrouillage par décharge
|
||||
profonde</em>, que certains distributeurs relancent par une source externe à
|
||||
faible courant.</li>
|
||||
<li><b>Réparation : non.</b> Le BMS est intégré et le module scellé. Un
|
||||
remplacement de cellules par un atelier tiers annule la garantie.</li>
|
||||
<li><b>Garantie : c'est la vraie piste.</b> Les US2000C sont couverts une dizaine
|
||||
d'années sous conditions, et le recours passe par le <strong>distributeur</strong>,
|
||||
pas par Pylontech. Avec les logs, le nombre de cycles et six mois de traçabilité
|
||||
d'usage, le dossier est défendable.</li>
|
||||
<li><b>Reprise : aucun programme connu.</b> La fin de vie relève de la filière
|
||||
DEEE — du recyclage, pas de la valeur.</li>
|
||||
<li><b>À vérifier avant de commander :</b> l'US2000C est-il encore commercialisé ?
|
||||
S'il ne l'est plus, les scénarios B et C tombent et la question devient celle
|
||||
d'un parc homogène neuf.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2>Ce que je ferais</h2>
|
||||
<p class="sous">dans cet ordre, sans tout décider aujourd'hui</p>
|
||||
|
||||
<ol class="etapes col">
|
||||
<li><b>Faire lire les logs des quatre vieux modules</b>, pas seulement celui en
|
||||
panne. Vous saurez si vous avez un module à remplacer ou un groupe à retirer —
|
||||
et cela ne coûte rien.</li>
|
||||
<li><b>Brancher le second véhicule</b> les jours de forte production. Vous saurez
|
||||
en une journée combien de kilowattheures un second preneur absorbe réellement,
|
||||
et ce chiffre déplace le dimensionnement.</li>
|
||||
<li><b>Viser 10 à 12 modules équivalents neufs</b>, soit 16 à 20 kWh utiles.
|
||||
C'est la plage qui couvre 85 à 100 % des nuits d'été et qui cycle tous les jours.</li>
|
||||
<li><b>Si les logs condamnent le vieux groupe, ne pas rafistoler.</b> Un parc
|
||||
homogène neuf donne la même capacité en moins d'unités, avec une garantie neuve
|
||||
et un plafond de charge qui ne vous suit plus.</li>
|
||||
</ol>
|
||||
|
||||
<div class="reserve">
|
||||
<p><strong>Ces chiffres sont tous d'été.</strong> Les compteurs exploitables ne
|
||||
remontent qu'à fin juillet. L'hiver, la nuit dure 17 heures au lieu de 13 et la
|
||||
production ne recharge pas : aucun dimensionnement raisonnable ne fera passer un
|
||||
hiver breton sans réseau, et la stratégie des deux charges en heures creuses
|
||||
restera la bonne.</p>
|
||||
<p><strong>Dimensionnez pour vos nuits d'été, pas contre l'hiver.</strong> C'est
|
||||
en été que le stockage travaille tous les jours, et c'est en été que chaque
|
||||
kilowattheure stocké est gratuit.</p>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
Sources : 37 nuits complètes et 38 journées issues des statistiques long terme de
|
||||
Home Assistant (fin juillet – 4 septembre 2026) · courbe énergie/SOC établie sur
|
||||
576 paliers mesurés · relevé horaire du 4 septembre issu de la base
|
||||
d'historisation.<br>
|
||||
Capacité par module mesurée sur le parc réel, blocage de charge à 94 % et
|
||||
plancher ESS à 20 % inclus. Rendement de restitution retenu : 93 %.
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
'''
|
||||
|
||||
p = pathlib.Path('docs/pages/dimensionnement-batteries.html')
|
||||
p.write_text(html, encoding='utf-8')
|
||||
print(f"{p} — {len(html)} caracteres")
|
||||
for r in sc:
|
||||
print(f" {r['code']:<12} {r['mods']:>2} modules {r['dc']:>5.1f} DC {r['ac']:>5.1f} AC {r['n']:>2}/37 {r['pct']:>3} %")
|
||||
Reference in New Issue
Block a user