// Control · Hoe het denkt — 5 varianten (input/output schema) const CtrlDenkt = {}; const INPUTS = [ ["Belasting","live load (kW)"], ["Capaciteit","aansluiting limit"], ["Prioriteiten","locatie-regels"], ["Bronnen","net · batterij · gen · solar"], ]; const OUTPUTS = [ ["Battery","ontladen / laden"], ["Generator","start / stop"], ["EV Chargers","limit per paal"], ["Solar / Net","buffer / export"], ]; const FLOW = [ ["Piekbelasting","Batterij ontlaadt automatisch om de piek af te vlakken."], ["Batterij leeg","Generator start tijdelijk om door te draaien."], ["Solar beschikbaar","Eigen opwek gaat eerst de batterij in."], ["EV laden actief","Vermogen wordt verdeeld over palen en machines."], ]; CtrlDenkt.DenktV1 = function DenktV1() { // Original hub schema return (
05 · Hoe het denkt
// Beslissingsschema

Het systeem neemt beslissingen voor je.

Continu, op basis van actuele belasting, beschikbare capaciteit, prioriteiten op locatie en energiebronnen — zonder handmatige actie.

Control EMS PLATFORM v2.0 · Real-time {INPUTS.map(([t,s],i)=>{ const x = [80,360,740,1060][i]; const y = i%2?20:50; return ( INPUT · {String(i+1).padStart(2,"0")} {t} {s} ); })} {OUTPUTS.map(([t,s],i)=>{ const x=[80,360,740,1060][i]; const y=i%2?400:370; return ( OUTPUT · {String(i+1).padStart(2,"0")} {t} {s} ); })}
{FLOW.map(([w,t],i)=>(
WANNEER
{w}
→ DAN
{t}
))}
); }; CtrlDenkt.DenktV2 = function DenktV2() { // Decision tree return (
05 · Hoe het denkt · DECISION TREE

De logica achter elke beslissing.

Iedere seconde Belasting > capaciteit? CHECK · 01 {/* yes branch */} JA → ACTIE Batterij ontladen Vlak de piek af binnen 200ms {/* no branch */} NEE → Solar beschikbaar? CHECK · 02 Buffer in batterij → ACTIE Status quo → NIETS

↳ > 40 beslisregels per site, allemaal automatisch toegepast.

); }; CtrlDenkt.DenktV3 = function DenktV3() { // Pipeline horizontal return (
05 · Hoe het denkt · PIPELINE

Vier stappen, elke seconde.

{[ ["01","Meten","Belasting · capaciteit · prioriteit · bronnen","INPUT"], ["02","Wegen","Vergelijk met regels en limieten","ANALYSE"], ["03","Beslissen","Welke actie levert het beste resultaat","BESLIS"], ["04","Sturen","Stuur signalen naar batterij, gen, palen","ACTIE"], ].map(([n,t,d,tag],i)=>(
{tag}
{n}

{t}

{d}

~ {[80,140,40,200][i]}ms
{i<3 &&
}
))}
↳ TOTAAL CYCLUS: ~460ms — sneller dan een mens kan blinken
); }; CtrlDenkt.DenktV4 = function DenktV4() { // Logic table - if/then/auto return (
05 · Hoe het denkt · LOGIC TABLE

Wat gebeurt er, wanneer.

#
WANNEER
DAN
SNELHEID
{[ ["01","Piekbelasting > 95% capaciteit","→","Batterij ontlaadt automatisch","< 200ms"], ["02","Batterij < 15% en piek > drempel","→","Generator start tijdelijk","2s"], ["03","Solar > eigen verbruik","→","Overschot gaat in batterij","real-time"], ["04","EV-paal vraagt vermogen","→","Verdeel over palen + machines","< 500ms"], ["05","Net beschikbaar + tarief laag","→","Batterij laadt bij","real-time"], ["06","Onderhoud asset gepland","→","Routeer load om asset heen","planned"], ].map(([n,w,a,t,s])=>(
{n}
{w}
{a}
{t}
{s}
))}

↳ Alles automatisch — geen handmatige actie nodig.

); }; CtrlDenkt.DenktV5 = function DenktV5() { // Live trace - terminal style const lines = [ ["14:32:08.124","INFO","load=486kW cap=630kW soc=78%","ok"], ["14:32:08.291","INFO","prediction: peak in 18s","watch"], ["14:32:09.512","WARN","load=624kW approaching cap","trigger"], ["14:32:09.604","ACT ","battery → discharge 60kW","exec"], ["14:32:09.689","INFO","load=564kW within bounds","ok"], ["14:32:12.103","INFO","ev-charger-03 ramp request","queue"], ["14:32:12.205","ACT ","throttle ev-charger-03 to 22kW","exec"], ["14:32:14.012","INFO","solar production +12kW","ok"], ["14:32:14.118","ACT ","battery → charge 12kW","exec"], ]; return (
05 · Hoe het denkt · LIVE TRACE

Wat het systeem ziet en doet — live.

● control@site-001 · tracev2.0 · live
{lines.map(([t,lv,m,tag],i)=>{ const lvColor = lv.trim()==="WARN"?"#FFD700": lv.trim()==="ACT"?"var(--power-orange)":"var(--muted)"; const tagColor = tag==="exec"?"var(--power-orange)":tag==="trigger"?"#FFD700":"var(--muted)"; return (
{t} [{lv}] {m} {tag}
); })}

↳ ~ 4–8 acties per minuut, 24/7. Volledig auditeerbaar.

); }; CtrlDenkt.DenktV6 = function DenktV6() { return (
05 · Hoe het denkt · LOOP

De feedback-lus draait continu.

{[ [170,190,"Sensoren","Lezen elke 100ms"], [550,50,"Analyse","Vergelijk met regels"], [930,190,"Beslissing","Kies beste actie"], [550,330,"Sturing","Naar assets"], ].map(([x,y,t,d],i)=>( {t} {d} 0{i+1} ))}
); }; CtrlDenkt.DenktV7 = function DenktV7() { return (
05 · Hoe het denkt · INPUTS/OUTPUTS COLUMNS

Ingangen, regels, uitgangen.

{[ ["INPUTS",["Belasting","Capaciteit","Prioriteiten","Bronnen","Tarief","Weersvoorspelling"],"var(--muted)"], ["REGELS",["Peak shaving","Load balancing","Solar first","Generator min-uren","SOC-bandbreedte","Failover"],"var(--power-orange)"], ["OUTPUTS",["Battery (laad/ontlaad)","Generator (start/stop)","EV palen (limit)","Solar (export)","Net (import/export)","Alerts"],"var(--off-white)"], ].map(([t,items,c])=>(
{t}
{items.map((x,i)=>(
{String(i+1).padStart(2,"0")} · {x}
))}
))}
); }; CtrlDenkt.DenktV8 = function DenktV8() { return (
05 · Hoe het denkt · STATE MACHINE

Het systeem heeft vijf states.

{[ [120,160,"IDLE","Niets te doen","#9A9182"], [340,160,"MONITOR","Watching","#9A9182"], [560,80,"BALANCE","Bijsturen","#FF6B2B"], [560,240,"PROTECT","Piek voorkomen","#FF6B2B"], [820,160,"RECOVER","Herstellen","#FFD700"], ].map(([x,y,t,d,c],i)=>( {t} {d} ))}
); }; CtrlDenkt.DenktV9 = function DenktV9() { return (
05 · Hoe het denkt · IF/THEN PSEUDOCODE

Pseudocode van een typische cyclus.

// every 100ms
read load, capacity, soc, sources
if load > 0.95 * capacity:
battery.discharge(load - capacity)
elif soc < 0.15 and load > threshold:
generator.start()
elif solar > consumption:
battery.charge(solar - consumption)
else:
continue monitoring

↳ Vereenvoudigd. Werkelijke regels: 40+ per site.

); }; CtrlDenkt.DenktV10 = function DenktV10() { return (
05 · Hoe het denkt · COCKPIT

Het denken — visueel.

{[ ["LOAD","486","kW","#FF6B2B",.78], ["SOC","78","%","#FFD700",.78], ["MARGIN","144","kW","#7AA37A",.23], ].map(([k,n,u,c,p])=>(
{k}● live
{n} {u}
))}
↳ DECISION 14:32:08 load + 12% prediction → battery discharge 60kW (200ms)
↳ NEXT solar peak in ~12min → schedule battery charge
); }; CtrlDenkt.DenktV16 = function DenktV16() { // Hub variant — radial circular const inputs = INPUTS; const outputs = OUTPUTS; return (
05 · Hoe het denkt · HUB · RADIAL

Alles draait rondom één centrum.

CONTROL EMS · v2 {[...inputs, ...outputs].map((item,i)=>{ const total = inputs.length + outputs.length; const angle = (i / total) * 2 * Math.PI - Math.PI/2; const isOut = i >= inputs.length; const r = 240; const x = 400 + Math.cos(angle) * r; const y = 300 + Math.sin(angle) * r; const lx = 400 + Math.cos(angle) * 80; const ly = 300 + Math.sin(angle) * 80; return ( {item[0]} {isOut?"OUT":"IN"} ); })}
); }; CtrlDenkt.DenktV17 = function DenktV17() { // Hub — orbital with rings return (
05 · Hoe het denkt · HUB · ORBITAL RINGS

Drie ringen rondom de kern.

INPUTS · OUTER RULES · MIDDLE OUTPUTS · INNER CONTROL CORE {INPUTS.map(([t],i)=>{ const angles = [-2.4,-1.2,1.2,2.4]; const a = angles[i]; const x = 450 + Math.cos(a) * 380; const y = 260 + Math.sin(a) * 190; return ( {t} ); })} {["Peak shaving","Load balance","Failover"].map((t,i)=>{ const a = -1.6 + i*1.6; const x = 450 + Math.cos(a) * 270; const y = 260 + Math.sin(a) * 135; return ( {t} ); })} {OUTPUTS.map(([t],i)=>{ const angles = [-2.4,-1.2,1.2,2.4]; const a = angles[i] + Math.PI; const x = 450 + Math.cos(a) * 160; const y = 260 + Math.sin(a) * 80; return ( {t} ); })}
); }; CtrlDenkt.DenktV18 = function DenktV18() { // Hub — left/right with detail panels return (
05 · Hoe het denkt · HUB · GROUPED I/O

Inputs links. Outputs rechts. Brein in het midden.

↳ Inputs
{INPUTS.map(([t,s],i)=>(
{t}
{s}
))}
EMS PLATFORM
Control
v2 · live
● 4 inputs ↓
○ regels ⇄
● 4 outputs ↑
↳ Outputs
{OUTPUTS.map(([t,s],i)=>(
{t}
{s}
))}
); }; CtrlDenkt.DenktV19 = function DenktV19() { // Hub — minimal/asymmetric, large negative space return (
05 · Hoe het denkt · HUB · MINIMAL
// Hoe het denkt

Eén kern.
Acht zenuwen.

{INPUTS.map(([t],i)=>{ const y = 40 + i*70; return ( {t} INPUT · {String(i+1).padStart(2,"0")} ); })} CONTROL EMS · v2 {OUTPUTS.map(([t],i)=>{ const y = 40 + i*70; return ( {t} OUTPUT · {String(i+1).padStart(2,"0")} ); })}
); }; CtrlDenkt.DenktV20 = function DenktV20() { // Hub — schematic blueprint with grid return (
05 · Hoe het denkt · HUB · BLUEPRINT

Schematisch — zoals een ingenieur het tekent.

DWG-001 · CONTROL · I/O SCHEMATIC REV 02 {INPUTS.map(([t,s],i)=>{ const y = 80 + i*70; return ( IN-{String(i+1).padStart(2,"0")} {t} ); })} CONTROL EMS·CORE P/N: WTQ-CTRL-2 {OUTPUTS.map(([t,s],i)=>{ const y = 80 + i*70; return ( OUT-{String(i+1).padStart(2,"0")} {t} ); })} SCALE · 1:1 · UNIT · MM · SHEET 1/1
); }; CtrlDenkt.DenktV11 = function DenktV11() { return (
05 · Hoe het denkt · ANNOTATED SCREEN

Het denken — geannoteerd.

{[["LOAD","486 kW"],["SOC","78%"],["GEN","OFF"],["MARGIN","144 kW"]].map(([k,v])=>(
{k}
{v}
))}
A B
↳ A · 14:32:08
Voorspelt piek over 12 min — bereidt batterij voor.
↳ B · 14:44:21
Piek aangekomen — batterij ontlaadt 60kW. Geen generator nodig.
); }; CtrlDenkt.DenktV12 = function DenktV12() { const cards = [ ["IF","load > 95% capacity","→ batterij ontlaad","CRITICAL"], ["IF","SOC < 15% AND demand high","→ generator start","FALLBACK"], ["IF","solar > consumption","→ batterij laad","HARVEST"], ["IF","tarief laag AND SOC < 80%","→ batterij laad van net","ECONOMIC"], ["IF","piek voorspeld < 5min","→ pre-position batterij","PREDICTIVE"], ["IF","grid frequentie afwijkt","→ failover modus","SAFETY"], ]; return (
05 · Hoe het denkt · DECISION CARDS

Zes typische beslissingen.

{cards.map(([kw,cond,act,tag],i)=>(
{kw} · {String(i+1).padStart(2,"0")} {tag}
{cond}
{act}
))}
); }; CtrlDenkt.DenktV13 = function DenktV13() { return (
05 · Hoe het denkt · LATENCY STRIP

De cyclus duurt 100 milliseconden.

{[ [0,18,"SENSE","#9A9182"], [18,40,"PREDICT","#FFD700"], [40,68,"DECIDE","#FF6B2B"], [68,92,"ACT","#FF6B2B"], [92,100,"LOG","#7AA37A"], ].map(([s,e,t,c])=>(
{t}
))}
{[0,10,20,30,40,50,60,70,80,90,100].map(n=>(
{n}ms
))}
{[ ["SENSE","Lees alle sensoren — load, SOC, solar, frequenties."], ["PREDICT","Voorspel kort de komende 60 sec op basis van patronen."], ["DECIDE","Vergelijk staat met regels, kies optimale actie."], ["ACT","Stuur commando naar batterij/generator/EV/solar."], ["LOG","Audit-trail wegschrijven, leer van uitkomst."], ].map(([t,d],i)=>(
0{i+1} · {t}

{d}

))}
); }; CtrlDenkt.DenktV14 = function DenktV14() { return (
05 · Hoe het denkt · OPTIMALISATIE

Wat het systeem optimaliseert.

↳ Doelfunctie
// minimize
cost = α·grid_kWh
{" "}+ β·gen_hours
{" "}+ γ·peak_kW²
{" "}+ δ·battery_wear
// subject to
load_served ≥ 100%
SOC ∈ [10%, 95%]
↳ Wat dat betekent
{[ ["α","Minder van het net halen — vooral bij dure tarieven."], ["β","Generator zo min mogelijk laten draaien."], ["γ","Pieken zwaar straffen — kwadratisch wegen."], ["δ","Batterij niet onnodig zwaar belasten."], ].map(([s,d])=>(
{s}

{d}

))}
); }; CtrlDenkt.DenktV15 = function DenktV15() { return (
05 · Hoe het denkt · NARRATIEF

Een dag in 5 stappen.

Geen flowchart, geen pseudocode — gewoon wat het systeem doet, in volgorde.

{[ ["07:14","Ochtend","Load loopt op. Batterij vol uit nacht-tarief. Begint met ontladen, geen net-import."], ["10:42","Solar piek","Zon op dak produceert 180kW. Batterij laadt op met overschot. Net-export geblokkeerd."], ["13:08","EV golf","Drie chauffeurs pluggen in. Control verlaagt laadtempo van twee om piek te voorkomen."], ["16:35","Piek voorspeld","Algoritme ziet patroon: piek over 8 min. Batterij wordt voorgepositioneerd."], ["22:50","Nacht","Lage tarief. Batterij laadt tot 95%. Generator stand-by, niet gestart vandaag."], ].map(([t,kw,d],i)=>(
{t}

{kw}

{d}

))}
); }; window.CtrlDenkt = CtrlDenkt;