← Back to CoursesStemExpert
StemExpert
Intermediate · Handboek · 40. Integratieproject: de klimaatmodule
StemExpert · Brecht Corbeel · schoolium.me
StemExpert
I40. Integratieproject: de klimaatmodule
IIntermediate · deel I11 · Habitat I: energie, water en klimaat

Handboek · hoofdstuk 40Integratieproject: de klimaatmodule

Ontwerpen, dimensioneren, programmeren, testen en verdedigen: je team brengt 39 hoofdstukken samen in de tweede laag van Habitat

Negenendertig hoofdstukken lang leerde je telkens één stuk van de klimaat- en energiemodule berekenen: het warmteverlies, de panelen, de pomp, de pH, een programma met modi. In dit integratieproject zet je team ze samen tot één module die zichzelf van energie, water, warmte en licht voorziet, en die elke minuut noteert wat ze doet. Je legt eerst de lat (het programma van eisen), rekent elke balans na, voegt vijf versies van de code samen tot één programma, laat de module een week alleen draaien, analyseert de logbestanden in Python en verdedigt het resultaat voor een jury. Het handboek is je projectgids, het werkboek je projectmap.

12× uitleg4× uitgewerkt voorbeeld1× proef1× ontleed6× naslag1× verhaal1× het geheel2× code28 opdrachten in het werkboek± 36 lestijden
De klimaat- en energiemodule af: vier goten sla, eigen zonnestroom, en een logger die alles bijhoudt.
De klimaat- en energiemodule af: vier goten sla, eigen zonnestroom, en een logger die alles bijhoudt.
Na dit hoofdstuk
Verhaal · 40.1

Twee filters die niet in elkaar pasten

1/28

Op 13 april 1970, twee dagen na de lancering van Apollo 13, ontplofte een zuurstoftank in de servicemodule. De drie astronauten moesten de reis rond de maan en terug maken in de maanlander, die gebouwd was voor twee mensen en een kort verblijf. Daar liep al snel een tweede probleem op: de koolstofdioxide die ze uitademden, stapelde zich op. De maanlander had te weinig patronen met lithiumhydroxide om CO2 te binden. In de commandomodule lagen er genoeg, maar die waren vierkant, en de houder in de maanlander was rond.

Twee deelsystemen die elk perfect werkten, gebouwd door verschillende teams, pasten niet op elkaar. In Houston zochten ingenieurs een oplossing met alleen wat er aan boord was: plastic zakken, karton, slangen van de ruimtepakken en tape. Ze bouwden de adapter eerst zelf, testten hem, en lazen de bemanning daarna de bouwinstructies voor over de radio. De CO2 daalde weer, en op 17 april landde de capsule veilig.

Dat is integratie: nagaan of delen die elk werken, ook samen werken. De plaats waar ze elkaar raken, heet een interface: een maat, een stekker, een pin, een eenheid, een tijdzone. In de meetkas (Fundamental, hoofdstuk 33) had je er tientallen. De klimaat- en energiemodule heeft er meer, en ze zijn lastiger: een stroommeter die tot 20 A meet naast panelen die met 74 A laden, twee taken die dezelfde pomp schakelen, een energiebudget in UTC en een klok op UTC+1. In dit hoofdstuk zoek je ze op, voor ze in een testweek of in een ruimtevaartverslag opduiken.

Zo werk je met dit hoofdstuk

Het handboek is je projectgids: per fase wat je doet en waarom, met de waarden uit de vorige hoofdstukken, uitgewerkte berekeningen en de resultaten van een voorbeeldteam (Emma, Jonas, Sara en Wout). Het werkboek is je projectmap: per fase de opdrachten, met ruimte om in te vullen en een rubric. Hoofdstuknummers zonder letter verwijzen naar Intermediate; F33 is de meetkas van Fundamental, E-nummers zijn Expert.

Vier eigenaars, één module: debiet meten, pH ijken, de regelkast nakijken en de logbestanden lezen.
Vier eigenaars, één module: debiet meten, pH ijken, de regelkast nakijken en de logbestanden lezen.
Ontleed · 40.2

De klimaat- en energiemodule: alle deelsystemen

2/28

Zo ziet de afgewerkte module eruit. De kweekruimte is binnen 2,40 m lang en 2,00 m diep, met een kasdak onder 25°: de lage wand (zuid) is 1,93 m hoog, de hoge wand (noord) 2,87 m (hoofdstuk 19). Het rek staat tegen de hoge wand, de gang van 0,80 m ligt langs de lage wand. De oostwand grenst aan de woonmodule van het station: daar zitten de deur, het bedieningspaneel en de warmwaterleiding. De zuid- en westwand zijn doorzichtig getekend. Bij elk nummer staat het hoofdstuk waar het onderdeel gekozen of berekend werd.

op het dak vande woonmodulezuid ← · → noord
De module in isometrie, met rechtsboven de panelen op het dak van de woonmodule (zijaanzicht, niet op schaal).
Wijs een nummer aan: de figuur zoomt in. Klik om vast te zetten.
  1. 1
    Kasdak

    Meerwandig polycarbonaat 16 mm, U = 2,0, 5,30 m²: meer dan de helft van het warmteverlies (hoofdstuk 19). Het schuifpaneel van 10 kg glijdt 0,60 m omlaag en opent de nok (hoofdstuk 7 en 8).

  2. 2
    Dakmotor

    Wormwielmotor 12 V met tandriem, H-brug op D6-D8, eindeloop op D23 en D24; sluit in 6,8 s, na 12 s zonder eindpunt volgt een alarm (hoofdstuk 26 en 32).

  3. 3
    Groeilampen

    2 × 95 W, dimbaar met PWM op D5: 200 µmol/(m²·s) op het bed, van 6 tot 22 uur. Ze vullen het daglicht aan (hoofdstuk 25 en 36).

  4. 4
    NFT-rek

    Vier goten van 2,4 m in trappen, elk 12 plaatsen om de 20 cm: 48 kroppen op 2,88 m². Helling 1 : 50, 1,2 L/min per goot (hoofdstuk 36).

  5. 5
    Reservoir en pomp

    60 L, lichtdicht, 65 kg vol, op de vloer binnen de toegelaten zone (hoofdstuk 10 en 11). Pomp 12 W, vlotter, druksensor, NTC en de pH- en EC-sonde.

  6. 6
    Buffervat

    Donker vat van 200 L onder het rek: samen met het reservoir 1,09 MJ per graad. Het houdt de module 's nachts warm (hoofdstuk 18 en 31).

  7. 7
    Convector

    Ventiloconvector op de warmwaterleiding van het station, ±800 W; klep en ventilator via D12 (hoofdstuk 31).

  8. 8
    Ventilator

    Afzuiging hoog in de westwand: 11 m³/h bij PWM 90 voor de CO₂ (hoofdstuk 14), vol boven 25 °C (hoofdstuk 31).

  9. 9
    CO₂-fles

    Fles met een klep op D10: 30 s per halfuur, alleen overdag met het dak dicht (hoofdstuk 14 en 32).

  10. 10
    Sensorkast SK-1

    SHT31 op I²C (0x44) aan een kabel van 3 m, midden in de ruimte op planthoogte: niet in de zon en niet boven de convector (hoofdstuk 30 en 31).

  11. 11
    Lichtsensor

    LDR onder een kapje op de zuidrand van het dak: meet het daglicht, niet de lampen (hoofdstuk 22 en 25).

  12. 12
    Regelkast RK-1

    Geprinte kast in PETG met de Mega, de klok en de SD-kaart (hoofdstuk 37). Het vermogensdeel zit apart.

  13. 13
    Energiekast

    Twee LiFePO4-batterijen van 120 Ah met BMS, de MPPT-regelaar, de zekeringen en de twee meetshunts (hoofdstuk 16, 20 en 30).

  14. 14
    Bedieningspaneel

    Knop S1 naast de deur (kort: dak, lang: onderhoud) en de statusled (hoofdstuk 24 en 32).

  15. 15
    Inspectierobot

    Rijdt een lus door de gang langs drie meetpunten, ±50 s per ronde, en laadt aan zijn station (hoofdstuk 33).

  16. 16
    Zonnepanelen

    4 × 350 Wp = 1,40 kWp onder 60° op het zuiden, in twee rijen op het platte dak van de woonmodule, met ballast (hoofdstuk 6, 10 en 20).

  17. 17
    Wanden en vloer

    Houtskelet met minerale wol: U = 0,22 (wand) en 0,21 (vloer). Samen met het dak en de ventilatie H = 20,2 W/K (hoofdstuk 19).

Uitleg · 40.3

De module als één systeem

3/28

In hoofdstuk 1 van Fundamental beschreef je de meetkas als een systeem met input, proces en output. De module is hetzelfde, maar groter. Het systeemschema toont zeven soorten input (zonlicht, warmte van het station, regenwater, zouten, CO2, plantjes en instellingen), acht deelsystemen en zes soorten output. Drie stromen houden alles samen:

  • energie: zonnestroom via de batterijen naar lampen, pomp, ventilatoren en besturing; warmte van het station via de convector naar de lucht en de buffer;
  • materie: water en zouten in een kringloop van reservoir, goten en planten; CO2 uit de fles en de lucht; sla en plantenresten naar buiten;
  • informatie: metingen naar de Mega, beslissingen naar de actuatoren, een regel per minuut naar de logger.

Een module die zichzelf in leven houdt, moet elke dag drie balansen sluiten. Energie: wat de panelen leveren, moet het verbruik dekken, met de batterijen als buffer voor de nacht en voor grijze dagen. Water: wat de planten verdampen, moet bijgevuld worden voor het reservoir onder 10 cm zakt. Warmte: wat door de schil verdwijnt, moet de convector, de zon of de lampen aanvullen, met de buffer voor de nacht. De fasen van dit project rekenen elke balans na, eerst op papier, daarna in een testweek.

Een schema om mee te zoeken

Loopt er iets mis, volg dan de pijlen terug. Te weinig licht op het bed? Kijk bij licht (lampen, dimmen), bij besturing (energiebeheer, grens) en bij energie (laadtoestand). De foutzoektabel verderop werkt precies zo.

systeemgrens: de klimaat- en energiemoduleinputoutputzonlichtwarmte van hetstationregenwatervoedingszouten,pH-minlucht, CO₂ uit deflesplantjes van dekiemplankinstellingen,onderhoudsla, ±100 kg per jaarzuurstof, waterdampwarmteverlies, 20,2W/Koverschot zonnestroomlogbestanden,meldingenplantenresten,compostenergiepanelen,batterijen,12,8 V-netbesturingMega enklimaat.inov5dataSD-kaart,Pythonklimaatwarmte,lucht, dak,CO₂licht2 × 95 W,dimmenwater en voedingpomp,reservoir,EC, pHteelt48 kroppen in vier NFT-gotenconstructiehoutskelet, kasdak, vloer, rek: draagt en beschermt5 V12,8 VPWM,aan/uitmetingmaterieenergieinformatieterugkoppeling
Blauw is materie, geel energie, paars informatie; de rode stippellijn is de terugkoppeling van de sensoren naar de besturing.
Uitleg · 40.4

Het project: fasen, eigenaars en planning

4/28

Een module van 2,4 bij 2 m bouwt niet elke school. Daarom kies je bij de start een spoor. Beide sporen doorlopen dezelfde fasen en leveren hetzelfde op: een programma van eisen, berekeningen, een programma, logbestanden, een testrapport, een rapport en een verdediging.

spoor A: de echte modulespoor B: tafelopstelling en simulatie
wat staat erde kweekruimte met rek, dak, panelen en batterijenregelkast RK-1 met de Mega, sensorkast SK-1, één goot met pomp en reservoir, één lamp, één batterij
wat je bouwt12,8 V-net, regelkast, hydroponie, sensorendezelfde regelkast en sensoren, op een plank; de rest is model
testweekde logbestanden van de module zelfde simulatie van dit hoofdstuk, plus een week met de echte sensoren op tafel
wat je zeker leertbouwen, keuren, alles samen laten werkenintegreren, testen, data lezen: de module verandert niet van plaats

Eigenaars. Elk teamlid is eigenaar van één deelsysteem en van de interfaces die erbij horen: hij rekent het na, bouwt het, test het en verdedigt het. Eén van de vier is ook integrator: die bewaakt het programma van eisen, de interfacetabel en de planning. Iedereen soldeert, programmeert en test mee.

roleigenaar vanvooral in fasesteunt op hoofdstuk
energiepanelen, batterijen, 12,8 V-net, zekeringen, energiebeheer, interfaces I1, I2, I82, 316, 20, 21, 23
water en voedingpomp, goten, reservoir, EC en pH, bijsturen, interfaces I5, I6, I12, I13, I162, 39, 11-15, 36
klimaat en lichtwarmte, ventilatie, dak, CO₂, lampen, interfaces I3, I9, I11, I14, I15, I172, 314, 18, 19, 25, 26, 31
besturing en dataklimaat.ino versie 5, logger, analyse in Python, interfaces I4, I7, I10, I183, 422, 24, 28-32, 39
integrator (één van de vier)programma van eisen, interfacetabel, planning, testrapport, logboekalle2, 30 (F), 40

Planning. Het voorbeeldteam kreeg twaalf weken van drie lestijden. Fase 1 legt de lat, fase 2 rekent per deelsysteem, fase 3 bouwt en programmeert parallel, fase 4 integreert en test, fase 5 schrijft en verdedigt. Zes mijlpalen zijn momenten waarop iets af moet zijn en getoetst wordt: het programma van eisen ligt vast (week 2), de berekeningen doorstaan een ontwerpreview met de leraar (week 4), de 12,8 V-kant is gekeurd (week 6), versie 5 draait in de simulatie (week 8), de testweek is voorbij (week 10, na de integratietests van week 9) en het rapport is ingediend (week 11).

Het kritieke pad

Zonder gekeurde 12,8 V-kant geen sensoren in de module, zonder werkende code geen integratietest, zonder integratietest geen testweek, zonder testweek geen testrapport. Die keten bepaalt het tempo. De hydroponie start daarom al in week 4, parallel: de planten groeien tijdens het programmeren.

123456789101112week0 · start: teams en rollen1 · programma van eisen1 · interfaces vastleggen2 · dimensioneren3 · 12,8 V-net en regelkast3 · hydroponie opstarten, ijken3 · klimaat.ino v5 samenvoegen4 · integreren, storingstests4 · testweek5 · analyse en technisch rapport5 · verdediginglogboek en portfolioPvE vastontwerpreviewkeuringv5 draaittestweekrapport
Elke balk is een fase, elk ruitje een mijlpaal. De testweek (week 10) staat pas na de integratietests.
Naslag · 40.5

Fase 1: het programma van eisen van de module

5/28

Het programma van eisen is de lat waarmee je de module beoordeelt. Voor de meetkas stelde je het op voor je rekende (Fundamental, hoofdstuk 30). Voor de module ligt al veel vast: 39 hoofdstukken berekenden en beslisten. Het werk van fase 1 is die beslissingen verzamelen, meetbaar maken en elk een toets geven. Drie regels:

  1. Meetbaar: een grootheid, een grens met een eenheid, en hoe je het nagaat. 'Warm genoeg' wordt 'overdag minstens 17,5 °C' (K1).
  2. Vooraf: het criterium ligt vast voor je test, anders ga je het resultaat goedpraten.
  3. Herkomst: bij elke eis staat het hoofdstuk waar de waarde vandaan komt. Verandert daar iets, dan weet je welke eis mee verandert.

Het voorbeeldteam kwam op 54 eisen in twaalf groepen, waarvan 47 moet-eisen. De criteria zijn soms net iets ruimer dan de ontwerpwaarde: de verwarming springt aan onder 18 °C, maar de eis vraagt 17,5 °C, omdat een aan/uit-regeling altijd een beetje doorschiet (hoofdstuk 31) en de sensor ±0,2 °C meet.

De twaalf groepen

lettergroepmoetwensvooral uit hoofdstuk
Kklimaat7114, 31, 34
Llicht3025, 36
Wwater5011, 23, 36
Hvoedingsoplossing4113, 15, 36
Eenergie7116, 20, 21
Bbesturing7029, 31, 32
Ddata5028, 30
Vveiligheid405, 15, 26
Cconstructie208, 10, 26
Ggebruik224, 24, 32
Pteelt1136
Oomgeving0138

Alle eisen

codeeissoortcriterium (vooraf vast)hoofdstuk
K1overdag (7-22 h) minstens 17,5 °C bij de plantenmoetlaagste minuut ≥ 17,5 °C31, 34
K2's nachts (22-6 h) minstens 15,5 °Cmoet≥ 15,5 °C31, 34
K3hoogstens 30 °Cmoet≤ 30 °C31, 34
K4ventilatoren vol boven 25 °C, dak open boven 27 °C; terug onder 24 en 25 °Cmoetdrempels ± 0,3 °C31, 32
K5het dak haalt zijn eindpunt binnen 12 s, anders alarmmoetalarm na 12 s26, 32
K6verwarming hoogstens 6 keer aan per uurwens≤ 631
K7basisventilatie overdag minstens 11 m³/hmoet≥ 11 m³/h14
K8CO₂-klep alleen in DAG met het dak dichtmoetnooit met het dak open14, 32
L1lichtsom op het bed minstens 11,0 mol/(m²·dag)moetelke dag25, 36
L2lampen vullen het daglicht aan tot 200 µmol/(m²·s), hoogstens 1 stap per 200 msmoet± 10 µmol zolang SoC ≥ 40 %25
L3volle lampen: elk van 9 meetpunten ≥ 180 µmol/(m²·s)moet≥ 18025, 36
W11,2 L/min per goot (± 20 %)moet0,96-1,44 L/min11, 36
W2pomp in minuut 0-9 van elk uur, extra beurt als slappe sla verwacht wordtmoetjuist30, 39
W3de pomp draait nooit droogmoetpomp uit na 10 s droog11, 23, 32
W4minstens 5 dagen zonder bijvullen bij 6 L per dagmoet≥ 5 dagen11, 13
W5reservoir lichtdicht: algen onder 5 · 10⁵ per mLmoet< 5 · 10⁵ per mL5
H1EC tussen 1,2 en 1,8 mS/cm (bij 25 °C)moetaltijd13
H2pH tussen 5,5 en 6,5moetaltijd15
H3voedingsoplossing nooit boven 24 °Cmoet≤ 24 °C34, 36
H4voedingsoplossing tussen 18 en 22 °Cwens18-22 °C34, 36
H5pH-sensor om de twee weken in twee punten geijkt, EC met ijkvloeistofmoethelling −0,18 V/pH ± 10 %; EC ± 0,0513, 15
E1van maart tot oktober genoeg zonnestroom: saldo per maand ≥ 0moet≥ 020
E2de batterijen overbruggen de nacht in de slechtste maandmoetuit de batterij ≤ 2,46 kWh16, 20
E3laadtoestand nooit onder 20 %moet≥ 20 %20
E4energiebeheer: onder 40 % lampen op zonnestroom, onder 20 % uit, onder 10 % alarmmoetlampen volgen de grens20, 29
E5laadtoestand elk uur in het EEPROM, na een stroomuitval hersteldmoetverschil ≤ 2 %-punt16, 29
E65 V-rail aan de sensorkast minstens 4,75 Vmoet≥ 4,75 V21
E7batterijen niet laden onder 0 °Cmoetmodule ≥ 0 °C16
E8jaarverbruik hoogstens 700 kWhwens≤ 700 kWh20, 25
B1na een stroomuitval: alles uit, OPSTART 5 s, dan de gewone modusmoetjuist29, 32
B2alarm bij: geen temperatuur 30 s, vlotter droog 10 s, reservoir onder 10 cm, dak-time-out, batterij onder 10 %moetalarm, statusled snel32, 40
B3zonder temperatuur verwarmt de module met de gemiddelde inschakelduurmoetjuist31
B4onderhoud: lange druk van 3 s; pomp uit, dak geblokkeerd, werklicht; na 60 min terugmoetjuist32
B5waakhond: een hangende taak herstart de Mega binnen 2 smoetherstart32
B6langste ronde van loop() hoogstens 100 msmoet≤ 100 ms29
B7één taak per uitgangmoetgeen tweede eigenaar40
D1elke minuut een CSV-regel, één bestand per dagmoet1440 regels per dag30
D2een ontbrekende meting geeft een lege celmoetlege cel30
D3minstens een jaar op de kaartmoet≥ 1 jaar30
D4klok op UTC+1, hoogstens 1 min afwijking per maandmoet≤ 1 min30
D5dag- en weekrapport in Python, gekoppeld aan de eisenmoetdraait28, 30
V1in de kweekruimte alleen 12,8 V en 5 Vmoetin orde5, 20
V2zekering per tak en bij elke batterijpoolmoetin orde20, 23, 26
V3niemand onder een bewegend dakmoetdak staat stil26, 32
V4pH-min (salpeterzuur 0,50 mol/L) gelabeld, met bril en handschoenenmoetin orde15
C1reservoir (65 kg vol) met zijn midden tussen 0,65 en 1,31 m van ligger Amoetin de zone10
C2dakmotor trekt 120 N zonder te blokkerenmoet≥ 120 N8, 26
G1statusled: rustig normaal, snel bij alarm, vast bij onderhoudmoetjuist32
G2kasdak met de hand: korte druk op S1 naast de deurmoetjuist24, 32
G3wekelijks onderhoud (bijvullen, EC en pH) hoogstens 20 minwens≤ 20 min40
G4hydroponie hoogstens € 800wens≤ € 8004
P148 plantplaatsen, om de 8,75 dagen een goot oogstenmoetin orde36
P2minstens 100 kg sla per jaarwens≥ 100 kg36
O1hoogstens 2 kg CO₂-eq per kg slawens≤ 238
012345678aantal eisen735477542210100110000211KLWHEBDVCGPOmoet-eisenwensen
K klimaat, L licht, W water, H voedingsoplossing, E energie, B besturing, D data, V veiligheid, C constructie, G gebruik, P teelt, O omgeving.
Uitleg · 40.6

Interfaces: waar de deelsystemen elkaar raken

6/28

Een interface is een afspraak tussen twee deelsystemen. Het N²-diagram toont ze in één oogopslag: de deelsystemen staan op de diagonaal, en het vakje in rij A en kolom B zegt wat A aan B levert. Een lege rij of kolom is verdacht: een deelsysteem dat niets krijgt of niets geeft, hoort er waarschijnlijk niet bij. De interfacetabel schrijft elke afspraak uit: de waarde met eenheid, de pin of het adres, de eigenaar en de test. Twee interfaces komen van buiten de module: het station (warmte, deur) en de bewoner (de knop).

codevan → naarafspraakeigenaartest
I1energie → water, klimaat, licht12,8 V-rail, elke tak een eigen zekering (hoofdstuk 20, 23, 26)energiespanning aan de verbruiker bij volle last
I2energie → besturing5 V-rail (omvormer 1 A): minstens 4,75 V aan de sensorkast (hoofdstuk 21)energiemeten terwijl de pomp aanslaat
I3besturing → lichtD5, PWM 490 Hz: 0-255 = 0-190 W, hoogstens 1 stap per 200 ms (hoofdstuk 25)besturinglampstand in de logger
I4besturing → waterD9 (IRLZ44N): minuut 0-9 en de extra beurt; één eigenaar (hoofdstuk 23, 39)besturingnaspelen
I5water → besturingvlotter D2 (LOW = water), druk A5: niveau alleen bij stilstaande pomp (hoofdstuk 11)watervlotter optillen
I6voeding → besturingpH A2 (2,50 V bij 7,00; −0,18 V per pH), EC A6 (0,50 V per mS/cm), NTC A0 (hoofdstuk 13, 15, 22)voedingijken
I7klimaat → besturingSHT31 op I²C 0x44, sensorkast op 3 m, pull-ups samen 1,8 kΩ (hoofdstuk 30)klimaatI²C-scanner
I8energie → besturingINA226 0x40 (zon) en 0x41 (verbruik), shunt 100 A / 75 mV (hoofdstuk 30)energiestroomtang ernaast
I9besturing → klimaatD10 CO₂-klep, D11 ventilatoren (PWM), D12 convector, D6-D8 dak, D23/D24 eindeloop (hoofdstuk 26, 31)besturingnaspelen
I10besturing → dataéén CSV-regel per minuut, 17 kolommen, UTC+1, lege cel = geen meting (hoofdstuk 30)datalogbestand lezen
I11licht → besturingLDR A1 onder een kapje: daglicht in lux, gedeeld door 54 = µmol/(m²·s) (hoofdstuk 22, 25)lichtluxmeter ernaast
I12water → teelt1,2 L/min per goot, een film van enkele mm (hoofdstuk 36)watermaatbeker
I13voeding → teeltEC 1,4 mS/cm, pH 5,8, 18-22 °C (hoofdstuk 13, 15, 36)voedinglogger
I14klimaat → teelt18-27 °C overdag, CO₂ ≥ 350 ppm (hoofdstuk 14, 31, 34)klimaatlogger
I15licht → teelt200 µmol/(m²·s) van 6 tot 22 uur: 11,5 mol per dag (hoofdstuk 25, 36)lichtPAR-meter
I16teelt → watertranspiratie 4 à 6 L per dag: bijvullen met regenwater en stamoplossing (hoofdstuk 13, 36)waterniveau in de logger
I17station → klimaatwarmwaterleiding naar de convector (±800 W), de deur, één gedeelde wand (hoofdstuk 19, 31)klimaatconvector aan, temperatuur
I18bewoner → besturingS1 naast de deur op D22 (RC + 74HC14): kort = dak, lang (3 s) = onderhoud (hoofdstuk 24, 32)besturingknoptest

Integratieproblemen opsporen. De meeste problemen vind je niet door één deel te testen, maar door twee documenten naast elkaar te leggen: een budget naast de code, een schema naast een ander hoofdstuk, de code van twee versies naast elkaar. Het voorbeeldteam vond er zes, allemaal vóór de testweek:

gevonden bijprobleemoplossing in versie 5
interface I8 naast hoofdstuk 20de ACS712 op A4 meet tot 20 A, maar de panelen laden met tot ±74 A: de coulombteller telt foutde laadtoestand telt met de twee INA226 (zon min verbruik); A4 blijft vrij
code naast codetaakExtraPomp() (hoofdstuk 39) zet pin 9 aan, acties() (versie 4) zet ze om de 2 s weer uit: de pomp flikkertéén taak beslist over de pomp: minuut 0-9 of de extra beurt
takenlijst van versie 2 en 4modi.ino (hoofdstuk 32) liet het dimmen, het energiebeheer en de logger wegalles terug in één programma, met de modi als kader
budget naast codehoofdstuk 20 rekende 's nachts 2 W voor de ventilatoren; versie 4 liet ze op PWM 90 (5 W) draaien's nachts PWM 36 (2 W): het budget en de code zeggen hetzelfde
integratietest, reservoir bijna leegmet de pomp aan staan er ±3,9 L in slang en goten: het niveau zakt 1,6 cm; bij 11 cm gaf dat elk uur een vals alarmhet niveau telt pas 2 min nadat de pomp gestopt is
budget naast loggerhoofdstuk 20 rekende de lampen van 4 tot 20 uur UTC; de klok van de module loopt op UTC+1één afspraak: alles in UTC+1, lampen van 6 tot 22 uur
Als elk deel werkt, werkt het geheel

Elke rij in de tabel hierboven gaat over delen die apart perfect werkten. De ACS712 meet juist; de extra pompbeurt van hoofdstuk 39 werkt; het budget van hoofdstuk 20 klopt met zijn eigen aannames. Het probleem zit telkens in de afspraak ertussen.

rij: wat een deelsysteem levertkolom: wat een deelsysteem krijgtenergieI2, I8I1I1I1besturingI10I4I9I3dataI5waterI12I6voedingI13I7klimaatI14I11lichtI15I16teeltdeelsysteeminterface (tabel)geen rechtstreekse interface
De besturing ontvangt van bijna iedereen en stuurt bijna iedereen: daar lopen de meeste interfaces samen.
Uitgewerkt voorbeeld · 40.7

Fase 2 · energie: het budget na veertig hoofdstukken

7/28

Hoofdstuk 20 stelde het energiebudget op: 3,27 kWh per dag, waarvan 93 % voor de lampen, en besloot tot een tweede batterij. Sindsdien kwamen er dingen bij: het dimmen met het daglicht (hoofdstuk 25), de convector (hoofdstuk 31), de modi en de logger. Reken het budget na zoals de module nu is. Volstaan de panelen en de batterijen, per maand? En wat betekent dat voor een heel jaar?

0123456kWh per dagjanfebmrtaprmeijunjulaugsepoktnovdeczonnestroom (PVGIS, 1,40 kWp)verbruik met dimmen (versie 5)verbruik zonder dimmen (hoofdstuk 20)
Dimmen halveert het verbruik ruim; alleen in december en januari blijft de zon (geel) onder het gedimde verbruik (groen).
Gegeven
  • PVGIS Brussel, 60° zuid: de gemiddelde dag van elke maand, per uur (hoofdstuk 20); 1,40 kWp
  • lampen van 6 tot 22 uur (UTC+1), met het daglicht in µmol/(m²·s)
  • daglicht op het bed: ±50 lx per W/m² op het paneel (rekenwaarde van dit project), 54 lx per µmol/(m²·s) (hoofdstuk 25)
  • batterijen: 2 × 1,23 = 2,46 kWh bruikbaar; laadrendement 95 %
Gevraagd
  • het budget van een gemiddelde maartdag
  • saldo en nachtbuffer per maand
  • het jaar
Oplossing
  1. 1
    Het budget. De lampen verbruiken niet meer 3040 Wh per dag, maar alleen wat het daglicht niet levert. De rest verandert weinig; twee posten komen erbij en één wordt zuiniger.
    verbruikerhoofdstuk 20 (Wh/dag)versie 5, gemiddelde maartdag (Wh/dag)waarom anders
    groeilampen 2 × 95 W30401206gedimd met het daglicht (hoofdstuk 25): de lampen vullen aan tot 200 µmol
    ventilatoren9695overdag PWM 90, 's nachts PWM 36 (nieuw in versie 5)
    microcontroller, sensoren, logger7272budget 3,0 W; hoofdstuk 21 rekende 0,96 W, de logger 0,07 W
    pomp (10 min per uur)4848en ±1 Wh per extra beurt van 5 min (hoofdstuk 39)
    laadregelaar en BMS1212
    CO₂-klep1,51,632 keer 30 s in DAG, alleen met het dak dicht
    dakmotor0,21,0zonnige dag: ±24 bewegingen van ±7 s (testweek)
    convector: klep en ventilator0,030nieuw: 12 W zolang er verwarmd wordt
    totaal32701465met gedimde lampen: 55 % minder
  2. 2
    Per maand. Zelfde methode als hoofdstuk 20, uur per uur, maar met gedimde lampen:
    maandjanfebmrtaprmeijunjulaugsepoktnovdec
    zon (kWh/dag)1,972,954,195,175,014,964,834,634,613,502,321,75
    verbruik, gedimd2,011,701,441,221,141,091,111,201,331,581,902,11
    uit de batterij1,731,441,160,920,740,660,710,861,071,321,641,84
    saldo−0,121,122,553,703,643,643,503,223,061,750,32−0,44
    Alleen december (−0,44 kWh) en januari (−0,12 kWh) komen tekort; november en februari sluiten nu, zonder dimmen kwamen ze 1,0 en 0,4 kWh per dag tekort.
  3. 3
    De nacht. Uit de batterijen komt hoogstens (december): van wat bruikbaar is. Eén batterij (1,23 kWh) volstaat van oktober tot februari niet: de tweede blijft nodig.
  4. 4
    Het jaar. De panelen kunnen leveren; de module gebruikt er ± van, waarvan voor de lampen. Zonder dimmen was dat . Blijft de oogst 100 kg sla, dan kost een kilo nog lampenergie in plaats van 11,1 (hoofdstuk 36).
Antwoord
Met dimmen daalt het verbruik van een gemiddelde maartdag van 3,27 naar 1,47 kWh. De panelen volstaan van februari tot november; alleen in december en januari is er gemiddeld te weinig zon. De twee batterijen blijven nodig voor de nacht (tot 1,84 kWh).
Klopt dit? Een gemiddelde dag is een optimistische dag. Het dimmen hangt niet lineair af van het licht: op een grijze dag moeten de lampen veel meer doen dan de gemiddelde dag voorspelt, en op een zonnige dag kunnen ze niet minder dan uit. De testweek verderop toont het: op twee grijze maartdagen zakte de laadtoestand onder 40 % en kregen de lampen alleen nog zonne-overschot. Het omgekeerde gebeurt ook: op zonnige dagen zijn de batterijen om 11 uur vol en knijpt de regelaar de zonnestroom af. De jaarbalans klopt dus ruim, de weekbalans niet altijd.
Uitleg · 40.8

Het 12,8 V-net: van paneel tot pin

8/28

Het schema toont de pluskant van het net als één lijn per tak. Het brengt samen wat hoofdstuk 16 (batterij), 20 (panelen en regelaar), 21 (5 V-rail en sterpunt), 23 (MOSFETs), 25 (PWM), 26 (dakmotor) en 30 (INA226) apart vastlegden.

  • Bron. De MPPT-regelaar zet de 30 à 40 V van de panelen om naar de laadspanning van de batterijen (hoofdstuk 20; hoe hij dat doet, zie je in E24). Op een zonnige middag loopt er tot ±74 A naar de rail.
  • Twee meetshunts. De INA226 op 0x40 meet de zonnestroom naar de rail, die op 0x41 de stroom naar de verbruikers. Het verschil is de batterijstroom: daarmee telt versie 5 de laadtoestand. De ACS712 op A4 (hoofdstuk 16) meet maar tot 20 A en zou op een zonnige middag verzadigen.
  • Zekeringen. Een zekering bij elke batterijpool (een batterij levert bij kortsluiting honderden ampère) en één per tak, net boven de stroom die de tak normaal vraagt.
  • Het sterpunt. Elke tak heeft een eigen retourdraad naar de minpool. Een gedeelde massadraad liet de pH 0,48 verspringen als de pomp aansloeg (hoofdstuk 21).
takstroom (rekenwaarde)zekeringschakelaar en pinhoofdstuk
groeilampen 2 × 95 W14,8 A20 AIRLZ44N op koelplaat, D5 (PWM 490 Hz)23, 25
pomp 12 W1,0 A (aanloop meer)2 AIRLZ44N, D9, vrijloopdiode 1N58199, 23
dakmotor1,84 A bij 60 N, 10 A blokkeren5 A traagH-brug 2 × BTS7960, D6-D8, eindeloop D23/D2426
ventilatoren0,39 A bij PWM 901 AIRLZ44N, D11 (PWM)23, 31
CO₂-klep0,47 A1 AIRLZ44N, D10, vrijloopdiode14, 23
convector: klep en ventilator±0,9 A (rekenwaarde 12 W)2 AIRLZ44N, D1231, 40
omvormer 12 → 5 V0,08 A gemiddeld (0,16 A aan de 5 V-kant)1 Aaltijd aan21

De grootste stroom tegelijk: lampen, pomp, een bewegende dakmotor en de ventilatoren vol, plus de omvormer: . Verwarmen en koelen gaan nooit samen, en de CO2-klep gaat niet open met een bewegend dak. De kabels van de rail naar de lampen rekent E5 na met matrices: hoogstens 3 % spanningsval tot elke verbruiker.

zonnepanelen4 × 350 WpMPPT100 A100 A0x40rail +12,8 V100 Abatterij A12,8 V, 120 Ahmet BMS100 Abatterij B12,8 V, 120 Ahmet BMSsterpunt: alle minnen (hoofdstuk 21)0x41verbruikers20 AD5 PWMgroeilampen 2 × 95 W2 AD9Mpomp 12 W5 A traagD6-D8Mdakmotor (H-brug)1 AD11 PWMMventilatoren1 AD10CO₂-klep 6 W2 AD12Mconvector 12 W1 A12 → 5 V5 V: Mega, sensoren,SD, RTC (0,16 A)
Links de bron en de batterijen, in het midden de rail met de twee meetshunts, rechts de zeven takken met hun zekering, schakelaar en pin.
Uitgewerkt voorbeeld · 40.9

Fase 2 · water: pomp, goten en reservoir

9/28

Reken de waterkringloop van de module na. Haalt de pomp het debiet dat de goten nodig hebben? Hoeveel water staat er onderweg als de pomp draait, en wat ziet de druksensor dan? Hoe lang houdt het reservoir het vol zonder bijvullen, en hoeveel water gebruikt de module per jaar?

25 cm: 60 L10 / 12 cm: alarm aan / uit6 cm: vlotterPpHECNTC4,8 L/min, 10 min per uurslang 16 mm2,5 mverdeler: een kraantje per gootgoot 1goot 2goot 3goot 4verzamelbuisvier goten van 2,4 m, elk 1,2 L/minhelling 1 : 50 (overdreven getekend)pomp 12 W: 4,8 L/min bij 1,56 m (hoofdstuk 11); vlotter D2, druk A5, pH A2, EC A6, NTC A01,5 m
Het water gaat 1,5 m omhoog naar de verdeler, loopt in vier goten langs de wortels en valt via de verzamelbuis terug in het reservoir.
Gegeven
  • pomp B: werkpunt 4,8 L/min bij 1,56 m met een slang van 16 mm en 2,5 m (hoofdstuk 11), 12 W elektrisch
  • 4 goten van 2,4 m, 10 cm breed, film van ±3 mm, 1,2 L/min per goot (hoofdstuk 36)
  • reservoir binnen 60 × 40 cm, vol bij 25 cm; alarm onder 10 cm (hoofdstuk 11)
  • verbruik tot 6 L op een warme dag (hoofdstuk 13); 16 L water per kg sla, 100 kg per jaar (hoofdstuk 36)
  • regen in Ukkel 837 mm per jaar (F9); kasdak in bovenaanzicht 2,40 × 2,00 m
Gevraagd
  • debiet en rendement van de pomp
  • water onderweg
  • dagen zonder bijvullen
  • de waterbalans van een jaar
Oplossing
  1. 1
    Debiet. Vier goten van 1,2 L/min vragen : precies het werkpunt. Het hydraulische vermogen is , van de 12 W: een rendement van ±10 % (hoofdstuk 9). In 10 minuten gaat er 48 L rond.
  2. 2
    Water onderweg. Slang: ; film in vier goten: ; verdeler en verzamelbuis ±0,5 L. Samen , dus zakt het reservoir zolang de pomp draait.
  3. 3
    Dagen zonder bijvullen. Tussen 25 en 10 cm zit : dagen op warme dagen. In de testweek verdampten de planten gemiddeld per dag.
  4. 4
    Het jaar. Transpiratie , het reservoir om de 5 weken verversen: . Samen . Op het kasdak valt regen.
Antwoord
De pomp levert precies de 4,8 L/min van vier goten. Terwijl ze draait, staan er ±3,9 L onderweg en meet de druksensor 1,6 cm te laag: versie 5 leest het niveau pas 2 minuten na de pomp. Het reservoir houdt 6 warme dagen vol; de module gebruikt ±2,2 m³ water per jaar, en het kasdak vangt er bijna het dubbele.
Klopt dit? De alarmgrens van 10 cm heeft een hysterese tot 12 cm (hoofdstuk 32). Die 2 cm is maar iets groter dan de 1,6 cm die de pomp wegneemt: zonder de regel 'niveau bij stilstaande pomp' gaf een reservoir op 11 cm elk uur in minuut 1 tot 9 een alarm. Nog een interface: de goten liggen in trappen, dus de onderste krijgt meer druk dan de bovenste. Het voorbeeldteam mat 1,08 tot 1,31 L/min en zette de kraantjes bij tot 1,19 à 1,21 L/min (eis W1).
Uitgewerkt voorbeeld · 40.10

Fase 2 · warmte: verlies, buffer en verwarming

10/28

Reken de warmtebalans van de module na, voor een koude winternacht en voor een zonnige lentemiddag. Volstaat de convector van 800 W? Wat doet de buffer? En volstaan de ventilatoren en het dak om de module onder 27 °C te houden?

Tbuitenschil 16,5 W/Klucht: 3,7 tot 104 W/K(ventilatie, ventilatoren, dak)T luchtC lucht80 kJ/KPkoppeling 30 W/KT bufferC buffer1,10 MJ/K0 °CSHT31: τ = 60 sP = convector (0 of 800 W) + zon (tot ±1,4 kW) + lampen (tot 190 W)
Temperaturen als spanningen, warmtestromen als stromen: de lucht warmt snel op en af, de buffer traag.
Gegeven
  • H = 20,2 W/K (hoofdstuk 19); ontwerptemperatuur buiten −8 °C (Ukkel)
  • overdag verwarmen onder 18 °C, 's nachts onder 16 °C; convector 800 W (hoofdstuk 31)
  • buffer: 200 L vat + 60 L reservoir; lucht met alles wat snel meewarmt 80 kJ/K (hoofdstuk 31)
  • zon door het kasdak op een heldere lentemiddag tot ±1,4 kW; buiten 14 °C
  • ventilatoren vol +40 W/K, dak open +60 W/K (hoofdstuk 31)
Gevraagd
  • vermogen bij −8 °C
  • de buffer
  • koelen op een zonnige dag
Oplossing
  1. 1
    Winter. Overdag (18 °C) bij −8 °C: ; hoofdstuk 19 rekende 567 W voor 20 °C. De convector heeft ±275 W over om op te warmen. Schakelen de lampen aan, dan komt er tot 190 W bij.
  2. 2
    De buffer. : veertien keer de snelle knoop. Koelt de buffer 's nachts 2 °C af, dan geeft hij 2,2 MJ = 0,6 kWh warmte af. Hij remt het afkoelen en vlakt de zaagtand van de verwarming af (hoofdstuk 18 en 31).
  3. 3
    Zonnige lentemiddag. Om 1,4 kW zonnewarmte bij 14 °C buiten kwijt te raken zonder boven 27 °C te gaan, moet . De schil alleen haalt 20 W/K; met de ventilatoren vol en het dak open is het : genoeg, net.
Antwoord
De convector van 800 W volstaat bij −8 °C met ±275 W reserve; de buffer (1,09 MJ/K) overbrugt de schommelingen. Op een zonnige lentedag moeten de ventilatoren en het dak samen werken: 120 W/K tegenover 108 W/K nodig. In de testweek kwam de module op de twee zonnige dagen tot 27,1 °C (eis K3).
Klopt dit? De testweek vroeg 14,0 kWh warmte van het station in zeven maartdagen, van 0,8 tot 4,3 uur verwarming per dag. Die warmte komt niet uit de batterijen: alleen de klep en de ventilator van de convector (12 W) staan in het energiebudget. In de zomer is het omgekeerde probleem groter: dan helpt een schaduwdoek meer dan meer ventilatie (versie 2).
Uitleg · 40.11

Fase 2 · licht: lichtsom, lampen en dimmen

11/28

Planten tellen fotonen, geen watt (hoofdstuk 36). Het ontwerp vraagt 200 µmol/(m²·s) op het bed, 16 uur per dag. Dat is de lichtsom (daglichtsom, DLI):

lichtsom van de module

Twee lampen van 95 W moeten dus op het bed krijgen: 3,0 µmol per joule (hoofdstuk 36 rekende 3,0, een zuinige lamp met reflecterende wanden).

Dimmen. De LDR meet het daglicht in lux; gedeeld door 54 wordt dat µmol/(m²·s) (hoofdstuk 25). De lampen vullen het verschil aan tot 200: bij 100 µmol daglicht branden ze op de helft, vanaf 200 zijn ze uit. De grafiek toont twee dagen uit de testweek. Op de zonnige woensdag is het daglicht van ongeveer 9 tot half zes ruim genoeg; de lampen helpen alleen 's morgens en 's avonds. De lichtsom wordt 21,4 mol: veel meer dan nodig. Op de grijze dinsdag komt het daglicht nauwelijks boven 100.

Energiebeheer. Dinsdag lag de laadtoestand onder 40 %. Dan krijgen de lampen alleen het zonne-overschot: de grens stijgt als de batterijen laden en daalt als ze leveren (hoofdstuk 20 en 29). 's Morgens tot 8 uur bleven de lampen uit, 's middags brandden ze op wat de panelen over hadden, en rond 18 uur gingen ze uit. De lichtsom zakte naar 6,0 mol. Dat is een keuze van het ontwerp: bij een lege batterij gaan eerst de lampen uit, niet de pomp of de besturing. De prijs is eis L1 (verderop).

Meer licht is altijd beter

Boven ±250 à 300 µmol/(m²·s) groeit sla bij deze temperatuur en CO2 nauwelijks sneller, maar ze verdampt meer (hoofdstuk 36). De module dimt daarom naar 200 en laat de middagzon ongebruikt over het bed vallen. Extra licht is pas nuttig als de lichtsom onder het doel blijft.

46810121416182022240100200300400500600700800uur (UTC+1)µmol/(m²·s) op het beddoel 200daglicht + lampendaglicht4681012141618202224050100150200250300uur (UTC+1)µmol/(m²·s) op het beddoel 200daglicht + lampendaglicht
Geel het daglicht, rood wat de lampen erbij doen. Dinsdag blijft de som onder 200: het energiebeheer houdt de lampen laag.
Proef · 40.12

Fase 2 · voedingsoplossing: ijken, bewaken en bijsturen

12/28
Onderzoeksvraag

Meten de pH- en de EC-sonde in het reservoir juist, en hoe stuur je de oplossing bij als de logger een waarschuwing geeft? (Samenstelling: hoofdstuk 12; EC: hoofdstuk 13; pH: hoofdstuk 15.)

Materiaal
  • pH-module en sonde, EC-module en sonde, de Mega met een testprogramma dat de spanning toont
  • bufferoplossingen pH 7,00 en 4,00, EC-ijkvloeistof 1,413 mS/cm, gedemineraliseerd water, tissues
  • maatbeker 1 L, spuitjes van 5 en 20 mL, stamoplossingen A en B, pH-min (salpeterzuur 0,50 mol/L)
  • veiligheidsbril, nitrilhandschoenen, het logboek
VeiligheidSalpeterzuur van 0,50 mol/L is bijtend: bril en handschoenen, altijd zuur in water gieten, nooit omgekeerd, en de fles gelabeld (GHS05) buiten het bereik van de planten bewaren (hoofdstuk 15). Stamoplossing A en B nooit onverdund samen gieten: calcium en fosfaat of sulfaat slaan dan neer.
goede pH3456782,22,42,62,83,03,23,4pHspanning van de pH-module (V)helling −0,177 V per pHpH 5,8: 2,70 Vijklijn van het voorbeeldteambufferoplossingen 7,00 en 4,00streefwaarde
Twee bufferoplossingen bepalen de ijklijn; de band van 5,5 tot 6,5 is de goede pH (eis H2).
Werkwijze
  1. 1Spoel de pH-sonde, zet ze in buffer 7,00 en wacht tot de spanning 30 s stabiel is. Noteer de spanning. Spoel, en herhaal in buffer 4,00.
  2. 2Bereken de helling in V per pH en de spanning bij pH 7. Zet beide in de code (hoofdstuk 15 rekende 2,50 V en −0,18 V per pH).
  3. 3Zet de EC-sonde in de ijkvloeistof van 1,413 mS/cm (25 °C) en vergelijk met wat de module toont na de omrekening naar 25 °C.
  4. 4Bijvullen: meet het niveau, vul met regenwater bij tot 25 cm, en voeg per liter bijgevuld water 10 mL A en 10 mL B toe, telkens apart en goed gemengd.
  5. 5pH te hoog: neem 1 L uit het reservoir en titreer met pH-min tot 5,8 (proeftitratie). Vermenigvuldig met het volume in het reservoir en geef de dosis in twee helften, met 15 minuten rondpompen ertussen.
  6. 6Noteer alles in het logboek: tijd, niveau, EC en pH voor en na, dosis.
Waarneming
metingvoorbeeldteam
buffer pH 7,002,49 V
buffer pH 4,003,02 V
helling−0,177 V per pH (−0,18 ± 10 %: in orde)
EC-ijkvloeistof 1,413 mS/cmmodule toont 1,42 mS/cm
woensdag: bijvullen13 L regenwater + 130 mL A + 130 mL B; niveau 18,9 → 24,3 cm; EC 1,39 → 1,38
maandag na de testweekpH 6,6 in ±35 L; proeftitratie: 1,6 mL pH-min per L; dosis 56 mL in twee keer 28 mL

De spanningen wijken 0,01 V af van hoofdstuk 15: elke sonde is een beetje anders, en ze verandert met de tijd. Daarom ijkt het team om de twee weken (eis H5).

Verklaring

De pH-module geeft . Bij pH 5,8 is dat , of ADC-waarde 556 op de 10-bits ADC van de Mega. Eén stap van de ADC (4,9 mV) is pH: ruim fijn genoeg voor een band van 5,5 tot 6,5. De EC-module geeft 0,50 V per mS/cm (rekenwaarde van dit project): één ADC-stap is . Versie 5 rekent de EC om naar 25 °C met de temperatuur van de NTC (2 % per graad, hoofdstuk 13).

Bijvullen met regenwater alleen zou de EC doen zakken: 13 L water op 45 L oplossing verdunt met ±23 %. Met 10 mL A en 10 mL B per liter krijgt het nieuwe water dezelfde samenstelling. De pH stijgt ondertussen elke dag met ±0,1 à 0,15 (hoofdstuk 15), omdat de planten meer nitraat opnemen dan ze afgeven: in de testweek van 5,86 naar 6,59.

Naslag · 40.13

De module in kerngetallen

13/28

Na fase 2 vat het voorbeeldteam de module samen op één blad: de technische fiche. Ze komt vooraan in het rapport en naast de module aan de muur. Elk getal heeft een herkomst: het hoofdstuk waar het berekend of beslist werd.

deelsysteemkerngetallenhoofdstuk
kweekruimtebinnen 2,40 × 2,00 m, wanden 1,93 en 2,87 m hoog (11,5 m³); vloer 0,40 m boven het terrein; één wand grenst aan het station6, 14, 19
kasdakpolycarbonaat 16 mm (U = 2,0), 5,30 m² onder 25°; schuifpaneel 10 kg op rails, slag 0,60 m, opening aan de nok7, 8, 19
schilwanden U = 0,22, vloer U = 0,21; H = 20,2 W/K (16,3 met nachtscherm): 567 W bij −8 °C buiten en 20 °C binnen19
kweekbed4 NFT-goten van 2,4 m, 48 plaatsen, 2,88 m², helling 1 : 50; om de 8,75 dagen een goot oogsten4, 36
waterreservoir 60 L (25 cm, 2,4 L per cm), alarm onder 10 cm; pomp 12 W, 4,8 L/min bij 1,56 m, 10 min per uur; 1,2 L/min per goot9, 10, 11, 36
voedingsoplossing1,30 g/L zouten; EC 1,4 (1,2-1,8 mS/cm), pH 5,8 (5,5-6,5), 18-22 °C; stamoplossing A en B: 10 mL per L12, 13, 15, 36
warmtebuffer 200 L + 60 L (1,09 MJ/K), lucht 80 kJ/K; convector 800 W; 18/19 °C overdag, 16/17 °C 's nachts18, 19, 31
ventilatie en dak11 m³/h (PWM 90), 's nachts PWM 36; vol boven 25 °C (+40 W/K); dak open boven 27 °C (+60 W/K)14, 26, 31
licht2 × 95 W, 200 µmol/(m²·s) van 6 tot 22 uur (UTC+1): 11,5 mol per dag; 3,0 µmol/J op het bed; gedimd met het daglicht23, 25, 36
zon4 × 350 Wp = 1,40 kWp, 60° zuid, op het dak van de woonmodule; MPPT 100 A; ±1397 kWh per jaar mogelijk6, 20
batterijen2 × LiFePO4 12,8 V 120 Ah: 2,46 kWh bruikbaar, BMS, in de verwarmde module; laadtoestand met twee INA22616, 20, 30
energiebeheervanaf 40 % volgens schema; 20-40 % lampen alleen op zonne-overschot; onder 20 % lampen uit; onder 10 % alarm20, 29
verbruikzonder dimmen 3,27 kWh per dag; met dimmen 1,1 tot 2,1 kWh per dag; ±540 kWh per jaar20, 25, 40
besturingArduino Mega 2560, klimaat.ino versie 5 (510 regels) met pinnen.h en dak.h/.cpp; regelkast RK-1; sensorkast SK-1 op 3 m29-32, 37, 40
dataCSV per minuut, 17 kolommen, ±121 kB per dag, klok op UTC+130, 40
teelt48 kroppen van ±200 g in 35 dagen; ±100 kg sla per jaar34, 36
voetafdruk±164 kg CO₂-eq per jaar, ±1,64 kg per kg sla38
Uitleg · 40.14

Fase 3 · de besturing: vijf versies worden één programma

14/28

De code van de module groeide over vier hoofdstukken, telkens met iets erbij en soms met iets eruit om het nieuwe duidelijk te tonen. Versie 4 (hoofdstuk 32) liet het dimmen, het energiebeheer en de logger weg. In fase 3 worden ze samengevoegd tot versie 5.

versiehoofdstukwat erbij kwamwat er nog ontbrak
129pinnen.h, zeven taken met millis(), dimmen, pomp 10 min per uur, dak met de knop, laadtoestand in het EEPROM, energiebeheerechte klok, logger, regeling
230klok DS3231 (UTC+1), logger op SD en USB, pomp in minuut 0-9, meldingen met #, INA226verwarming, ventilatie, modi
331verwarming en ventilatoren met hysterese, noodprogramma bij een sensorfoutmodi, dak als toestandsmachine
432modi OPSTART, DAG, NACHT, ALARM, ONDERHOUD; dak.h en dak.cpp; alarmbits; CO₂-klepdimmen, energiebeheer en logger (weggelaten)
taak39slapVerwacht(): een extra pompbeurt van 5 min om het halfuureen eigen taak die ook pin 9 stuurt
540alles in één programma; laadtoestand met twee INA226; pH, EC en watertemperatuur; één eigenaar per uitgang; waakhondzie 'wat de module nog niet kan'

Samenvoegen is meer dan knippen en plakken. Vier regels hielden het programma overzichtelijk:

  1. Eén klok. millis() voor de intervallen (om de 2 s meten, om de 200 ms de lampen), de DS3231 voor het uur van de dag, en alles in UTC+1 (hoofdstuk 30).
  2. Nergens delay(). Elke taak kijkt of het haar beurt is en keert meteen terug (hoofdstuk 29). Dan blijft elke ronde kort, en kan de waakhond na 2 s ingrijpen als er toch iets blijft hangen (hoofdstuk 32).
  3. Eén eigenaar per uitgang. Alleen acties() beslist over de pomp; de extra beurt van hoofdstuk 39 is een voorwaarde in die beslissing, geen tweede taak die op pin 9 schrijft. Zo ook: alleen taakLampen() schrijft naar D5, alleen dak.cpp naar de H-brug.
  4. De modi als kader. Wat een taak doet, hangt af van de modus (volgende blad). Een nieuwe functie krijgt dus altijd de vraag: wat doet ze in OPSTART, in ALARM, in ONDERHOUD?
setup()alles uit, EEPROM, SD, klok, OPSTART,dakStart, waakhond 2 singangen: I²C (SHT31, INA226, DS3231), A0-A6, D2, D22-D24uitgangen: D5-D13 (lampen, dak, pomp, CO₂, ventilatoren, convector, led)knopelke ronde:kort oflang (3 s)meten2 s: SHT31,INA226,LDR, pH,EC, NTC,niveauacties2 s:verwarmen,koelen,dak, pomp,CO₂loggen2 s; elkeminuut éénregelmoduselke ronde:vijf modidakelke ronde:zestoestandenlampen200 ms:dimmen engrensstatusled500 of 100ms, of vastEEPROM1 h:laadtoestandbewarenloop(): honderden keren per seconde; elke ronde begint met wdt_reset()de drie gekleurde taken lopen samen om de 2 s, na elkaar, in één ronde
Na setup() draait loop() rond; de drie gekleurde taken lopen om de 2 s, de andere bij elke ronde of op hun eigen ritme.
Uitleg · 40.15

De modi en het dak als toestandsmachines

15/28

De modi komen ongewijzigd uit hoofdstuk 32: OPSTART na elke herstart, DAG en NACHT volgens de klok, ALARM bij een oorzaak die meteen ingrijpen vraagt, ONDERHOUD met een lange druk op S1. Versie 5 voegt er één alarm aan toe (batterij onder 10 %) en drie waarschuwingen die geen modus zijn: pH buiten 5,5-6,5, EC buiten 1,2-1,8 en een voedingsoplossing boven 24 °C. Een waarschuwing vraagt actie vandaag, geen actie nu; ze komt als melding en in de logger. Waarom niet gewoon alarm? Een pH van 6,6 schaadt de sla niet in een uur, en een module die om de haverklap in ALARM staat, leert zijn bewoners het alarm te negeren.

Wat elke taak doet, hangt af van de modus:

modusverwarmingventilatorenlampenpompdakCO₂
OPSTARTuitlaaguituitdakStart: eindeloop lezendicht
DAG18/19 °C90; vol boven 25 °Cdimmen, grensmin. 0-9 + extravolgt 27/25 °C30 s per halfuur, dak dicht
NACHT16/17 °C36; vol boven 25 °Cuitmin. 0-9dichtdicht
ALARMzoals DAG of NACHTzoals DAG of NACHTzoals DAGniet bij vlotter of niveauoverdag automatischdicht
ONDERHOUDzoals DAG of NACHTvol (verse lucht)werklicht 60uitgeblokkeerddicht

Het dak blijft een eigen toestandsmachine in dak.h en dak.cpp (hoofdstuk 32): DICHT, OPENEN, OPEN, SLUITEN, GESTOPT en DAK_FOUT. De klimaatregeling vraagt alleen 'open' of 'dicht'; dak.cpp beslist wanneer de motor draait, stopt op de eindeloop en geeft DAK_FOUT als het eindpunt na 12 s niet bereikt is. Bij het binnenkomen van DAG volgt het dak meteen de temperatuur: na een herstart overdag sluit het dus eerst, en gaat het opnieuw open zodra het warmer is dan 27 °C.

NORMAALOPSTARTalles uit, 5 sDAG6 tot 22 uurNACHT22 tot 6 uurALARMled snelONDERHOUDled vast aan[5 s]kort / dak met de hand[22 uur][6 uur][alarm]kort[geen oorzaak]langlang of60 minlangaltijdin elke modus: meten, loggen,energiebeheer enwaarschuwingen (pH, EC,watertemperatuur). Na eenstroomuitval of een reset doorde waakhond begint allesopnieuw in OPSTART.
NORMAAL omvat DAG en NACHT: een overgang vanuit het kader geldt voor beide. Waarschuwingen zijn geen modus.
Code · 40.16

klimaat.ino versie 5

16/28

Het volledige programma, 510 regels. pinnen.h en dak.h/dak.cpp zijn dezelfde bestanden als in hoofdstuk 32 (hieronder te downloaden). Lees het van boven naar onder: de instellingen verwijzen naar de eisen (K1, L1, ...), elk blok begint met een kopregel, en de volgorde in loop() is de volgorde van het blokschema.

C++ (Arduino)klimaat.ino510 regelsDownload
// klimaat.ino - de sturing van de klimaatmodule, versie 5 (Arduino Mega 2560, hoofdstuk 40)// Samengevoegd: klok, logger, dimmen en energiebeheer (versie 2, hoofdstuk 30), de klimaatregeling (hoofdstuk 31),// de modi en het kasdak als toestandsmachines (versie 4, hoofdstuk 32) en de extra pompbeurt (hoofdstuk 39).// Nieuw: de laadtoestand telt met de twee INA226, pH, EC en de temperatuur van de voedingsoplossing worden bewaakt,// één taak beslist over de pomp, 's nachts draaien de ventilatoren trager, het niveau telt alleen als de pomp// stilstaat, en een waakhond van 2 s. I2C: INA226 0x40 en 0x41, SHT31 0x44, DS3231 0x68 (wintertijd).#include <Wire.h>#include <SPI.h>#include <SD.h>#include <EEPROM.h>#include <RTClib.h>#include <Adafruit_SHT31.h>#include <avr/wdt.h>#include "pinnen.h"#include "dak.h" // ---------------------------------------------------------------- instellingen (programma van eisen, hoofdstuk 40)const unsigned long MEET_MS = 2000;                  // meten en beslissenconst unsigned long LAMP_MS = 200;                   // lampen: hoogstens één stap per 200 ms (L4)const unsigned long LANG_MS = 3000;                  // lange druk op S1: onderhoud aan of uit (B4)const unsigned long ONDERHOUD_MAX_MS = 3600000UL;const unsigned long BEWAAR_MS = 3600000UL;           // laadtoestand elk uur in het EEPROM (B1)const unsigned long POMP_RUST_MS = 120000UL;         // niveau pas 2 min na het stoppen van de pomp (W3)const float DAG_LAAG = 18.0, NACHT_LAAG = 16.0;      // verwarming aan onder LAAG, uit boven LAAG + 1 (K1, K2)const float KOEL_AAN = 25.0, KOEL_UIT = 24.0;        // ventilatoren vol (K4)const float DAK_OPEN = 27.0, DAK_DICHT = 25.0;       // kasdak (K4)const int VENT_DAG = 90, VENT_NACHT = 36, VENT_VOL = 255, WERKLICHT = 60;const float DOEL = 200.0, LAMPEN_VOL = 200.0, LUX_PER_UMOL = 54.0;  // umol/(m2 s) op het kweekbed (L1, L2)const float SOC_VOL = 40.0, SOC_ZON = 20.0, SOC_ALARM = 10.0;       // energiebeheer (L3, E5)const float CAPACITEIT_AH = 240.0;                   // twee LiFePO4 van 120 Ah (hoofdstuk 20)const float PH_LAAG = 5.5, PH_HOOG = 6.5, EC_LAAG = 1.2, EC_HOOG = 1.8, WATER_WARM = 24.0;   // H1-H3const float SLAP_LICHT = 25.0, SLAP_VOCHT = 60.5;    // extra pompbeurt: klx en % (hoofdstuk 39)const int SD_CS = 53;const byte INA_ZON = 0x40, INA_VERBRUIK = 0x41;const float R_SHUNT = 0.00075;                       // shunt 100 A / 75 mVconst int ADRES_SOC = 0;const char KOP[] = "tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh,licht_lx,batterij_V,soc_pct,lampen_pwm,"                   "verw_pct,dak,water_C,pH,EC_mScm,niveau_cm,modus,alarm"; enum Modus { OPSTART, DAG, NACHT, ALARM, ONDERHOUD };const char* NAAM[] = {"OPSTART", "DAG", "NACHT", "ALARM", "ONDERHOUD"};const byte A_SENSOR = 1, A_WATER = 2, A_NIVEAU = 4, A_DAK = 8, A_BATTERIJ = 16;   // alarm: meteen ingrijpenconst byte W_PH = 1, W_EC = 2, W_WARM = 4, W_SD = 8;                              // waarschuwing: vandaag bijsturen // ---------------------------------------------------------------- toestandAdafruit_SHT31 sht;RTC_DS3231 rtc;DateTime klok, minuut;Modus modus = OPSTART;byte alarmen = 0, waarschuwingen = 0;unsigned long modusSinds = 0, vorigeMeting = 0, vorigeLamp = 0, vorigeBewaring = 0, ledSinds = 0;unsigned long knopSinds = 0, droogSinds = 0, pompSinds = 0;float luchtT = NAN, luchtRV = NAN, lux = 0, uBat = 0, uBus = NAN, iZon = NAN, iVerbruik = NAN;float soc = 50.0, waterT = NAN, ph = NAN, ec = NAN, niveau = 0, gemAan = 0.5;int geenMeting = 0, grens = 255, stand = 0;bool verwarmen = false, koelen = false, warm = false, laden = false, pompAan = false;bool extraBeurt = false, extraBeslist = false, niveauLaag = false, batLeeg = false;bool knopWas = false, langGemeld = false, ledAan = false, kaartOk = false, bezig = false;float somT, somRV, somLux, somZon, somVerbruik, somU, somWT, somPH, somEC, somNiveau, somStand;   // loggerint nT, nMeting, nVermogen, nWT, nPH, nVerw;byte eindModus = OPSTART, eindAlarm = 0, eindDak = 0;float eindSoc = 50.0;char opdracht[32];int lengte = 0; // ---------------------------------------------------------------- meldingenvoid printTwee(int x) {  if (x < 10) Serial.print('0');  Serial.print(x);} void melding(const char* tekst) {                    // "# 14:02:31 tekst" (ook dak.cpp gebruikt ze)  Serial.print("# ");  printTwee(klok.hour());  Serial.print(':');  printTwee(klok.minute());  Serial.print(':');  printTwee(klok.second());  Serial.print(' ');  Serial.println(tekst);} // ---------------------------------------------------------------- sensoren (hoofdstuk 11, 13, 15, 22, 30)int gemiddeld(int pin) {                             // 16 metingen middelen tegen ruis  long som = 0;  for (int i = 0; i < 16; i++) som += analogRead(pin);  return som / 16;} float daglichtLux() {                                // LDR onder een kapje, 1,0 kOhm naar GND  int n = gemiddeld(LDR);  if (n < 1) n = 1;  float r = 1000.0 * (1024.0 - n) / n;  return 10.0 * pow(r / 15000.0, -1.0 / 0.7) / 0.10;} float batterijspanning() {                           // deler 100 kOhm / 33 kOhm  return gemiddeld(BATTERIJ) * 5.0 / 1024.0 * (133.0 / 33.0);} float waterTemperatuur() {                           // NTC in het reservoir, B = 3913 K  int n = gemiddeld(NTC);  if (n < 5 || n > 1018) return NAN;                 // draad los of kortsluiting  float r = 10000.0 * (1024.0 - n) / n;  return 1.0 / (1.0 / 298.15 + log(r / 10000.0) / 3913.0) - 273.15;} float phWaarde() {                                   // 2,50 V bij pH 7,00, -0,18 V per pH (hoofdstuk 15)  float u = gemiddeld(PH) * 5.0 / 1024.0;  if (u < 0.1 || u > 4.9) return NAN;  return 7.0 + (2.50 - u) / 0.18;} float ecWaarde(float t) {                            // 0,50 V per mS/cm, omgerekend naar 25 graden (hoofdstuk 13)  float e = gemiddeld(EC) * 5.0 / 1024.0 / 0.50;  if (isnan(t)) return e;  return e / (1.0 + 0.02 * (t - 25.0));} float niveauCm() {                                   // MPX5010 onderaan het reservoir (hoofdstuk 11)  float u = gemiddeld(DRUK) * 5.0 / 1024.0;  float p = (u / 5.0 - 0.04) / 0.09 * 1000.0;        // Pa  return p / (1000.0 * 9.81) * 100.0;} long inaLees(byte adres, byte reg) {                 // INA226: 16 bits uit een register, of -1  Wire.beginTransmission(adres);  Wire.write(reg);  if (Wire.endTransmission() != 0) return -1;  if (Wire.requestFrom(adres, (byte)2) != 2) return -1;  byte hoog = Wire.read();  byte laag = Wire.read();  return ((long)hoog << 8) | laag;} float inaStroom(byte adres) {                        // A: shuntspanning (2,5 uV per stap) gedeeld door 0,75 mOhm  long s = inaLees(adres, 0x01);  if (s < 0) return NAN;  return (int16_t)s * 0.0000025 / R_SHUNT;} float inaSpanning(byte adres) {                      // V: busspanning, 1,25 mV per stap  long b = inaLees(adres, 0x02);  if (b < 0) return NAN;  return b * 0.00125;} byte band(byte w, byte bit, float x, float laag, float hoog, float marge) {   // waarschuwing met hysterese  if (isnan(x)) return w;  if (x < laag || x > hoog) return w | bit;  if (x > laag + marge && x < hoog - marge) return w & ~bit;  return w;} // ---------------------------------------------------------------- meten, laadtoestand, alarmen (om de 2 s)void meten(unsigned long nu) {  float t, rv;  if (sht.readBoth(&t, &rv)) { luchtT = t; luchtRV = rv; geenMeting = 0; }  else { luchtT = luchtRV = NAN; geenMeting++; }  lux = daglichtLux();  uBat = batterijspanning();  iZon = inaStroom(INA_ZON);  iVerbruik = inaStroom(INA_VERBRUIK);  uBus = inaSpanning(INA_VERBRUIK);  if (!isnan(iZon) && !isnan(iVerbruik)) {           // coulombteller (hoofdstuk 16) met de twee INA226    float iLaad = iZon - iVerbruik;                  // A, positief = de batterijen laden    soc += iLaad * (MEET_MS / 3600000.0) / CAPACITEIT_AH * 100.0;    if (uBat >= 14.2 && iLaad > 0.0 && iLaad < 2.0) soc = 100.0;    // vol: opnieuw ijken    soc = constrain(soc, 0.0, 100.0);    laden = iLaad > 0.0;  }  if (soc >= SOC_VOL) grens = 255;                   // energiebeheer (hoofdstuk 20)  else if (soc < SOC_ZON) grens = 0;  else if (laden) grens = min(grens + 5, 255);       // er is zon over: meer licht mag  else grens = max(grens - 5, 0);                    // de batterij levert: minder licht  waterT = waterTemperatuur();  ph = phWaarde();  ec = ecWaarde(waterT);  if (digitalRead(VLOTTER) == LOW) droogSinds = nu;  // LOW = genoeg water; een losse draad = droog  if (!pompAan && nu - pompSinds >= POMP_RUST_MS) niveau = niveauCm();   // water in de goten telt niet mee  if (!niveauLaag && niveau < 10.0) niveauLaag = true;                 // 10 en 12 cm  else if (niveauLaag && niveau > 12.0) niveauLaag = false;  if (!batLeeg && soc < SOC_ALARM) batLeeg = true;                     // 10 en 15 %  else if (batLeeg && soc > SOC_ALARM + 5.0) batLeeg = false;  byte nieuw = 0;  if (geenMeting >= 15) nieuw |= A_SENSOR;           // 30 s geen luchttemperatuur  if (nu - droogSinds >= 10000) nieuw |= A_WATER;    // 10 s droog  if (niveauLaag) nieuw |= A_NIVEAU;  if (dak == DAK_FOUT) nieuw |= A_DAK;  if (batLeeg) nieuw |= A_BATTERIJ;  if (nieuw & ~alarmen & A_SENSOR) melding("oorzaak: geen temperatuur");  if (nieuw & ~alarmen & A_WATER) melding("oorzaak: vlotter droog");  if (nieuw & ~alarmen & A_NIVEAU) melding("oorzaak: reservoir onder 10 cm");  if (nieuw & ~alarmen & A_DAK) melding("oorzaak: dak haalt zijn eindpunt niet");  if (nieuw & ~alarmen & A_BATTERIJ) melding("oorzaak: batterij onder 10 %");  alarmen = nieuw;  byte w = band(waarschuwingen, W_PH, ph, PH_LAAG, PH_HOOG, 0.05);  w = band(w, W_EC, ec, EC_LAAG, EC_HOOG, 0.05);  w = band(w, W_WARM, waterT, 0.0, WATER_WARM, 0.5);  if (w & ~waarschuwingen & W_PH) melding("waarschuwing: pH buiten de band, bijsturen");  if (w & ~waarschuwingen & W_EC) melding("waarschuwing: EC buiten de band, bijsturen");  if (w & ~waarschuwingen & W_WARM) melding("waarschuwing: voedingsoplossing te warm");  waarschuwingen = w | (kaartOk ? 0 : W_SD);} // ---------------------------------------------------------------- de knop: kort of lang (hoofdstuk 24, 32)void leesKnop(unsigned long nu, bool& kort, bool& lang) {  bool in = digitalRead(KNOP) == HIGH;               // na de 74HC14: hoog = ingedrukt  kort = lang = false;  if (in && !knopWas) { knopSinds = nu; langGemeld = false; }  if (in && !langGemeld && nu - knopSinds >= LANG_MS) { lang = true; langGemeld = true; }  if (!in && knopWas && !langGemeld) kort = true;  knopWas = in;} // ---------------------------------------------------------------- de modi (hoofdstuk 32)bool isDag() { return klok.hour() >= 6 && klok.hour() < 22; }Modus gewoon() { return isDag() ? DAG : NACHT; } void naar(Modus nieuw, unsigned long nu) {  Modus oud = modus;  modus = nieuw;  modusSinds = nu;  char tekst[32] = "modus ";  strcat(tekst, NAAM[nieuw]);  melding(tekst);  if (nieuw == ONDERHOUD) dakBlokkeer(true, nu);     // niemand onder een bewegend dak  if (oud == ONDERHOUD) dakBlokkeer(false, nu);  if (nieuw == NACHT) dakVraag(false);  if (nieuw == DAG) dakVraag(warm);} void taakModus(unsigned long nu, bool kort, bool lang) {  switch (modus) {    case OPSTART:                                    // 5 s: sensoren en klok lezen      if (nu - modusSinds >= 5000) naar(gewoon(), nu);      break;    case DAG:    case NACHT:      if (alarmen) naar(ALARM, nu);      else if (lang) naar(ONDERHOUD, nu);      else if (gewoon() != modus) naar(gewoon(), nu);      else if (kort) dakKnop(nu);                    // korte druk: het dak met de hand (G2)      break;    case ALARM:      if (kort) {                                    // bevestigen        if (alarmen & A_DAK) {          dakHerstel(nu);          alarmen &= ~A_DAK;        }        if (alarmen == 0) naar(gewoon(), nu);        else melding("alarm blijft: oorzaak nog aanwezig");      } else if (lang) naar(ONDERHOUD, nu);      break;    case ONDERHOUD:      if (lang || nu - modusSinds >= ONDERHOUD_MAX_MS) naar(gewoon(), nu);      break;  }} // ---------------------------------------------------------------- klimaat, pomp en CO2 (om de 2 s)void acties(unsigned long nu) {  bool dag = isDag();  float laag = dag ? DAG_LAAG : NACHT_LAAG, hoog = laag + 1.0;  if (isnan(luchtT)) {                               // noodprogramma: blind met de gemiddelde inschakelduur    verwarmen = (nu / 1000UL) % 600UL < (unsigned long)(gemAan * 600);    koelen = false;  } else {    if (!verwarmen && luchtT < laag) verwarmen = true;    else if (verwarmen && luchtT > hoog) verwarmen = false;    if (!koelen && luchtT > KOEL_AAN) koelen = true;    else if (koelen && luchtT < KOEL_UIT) koelen = false;    if (verwarmen) koelen = false;    gemAan += ((verwarmen ? 1.0 : 0.0) - gemAan) * (MEET_MS / 3600000.0);    bool automatisch = dag && (modus == DAG || (modus == ALARM && !(alarmen & A_DAK)));    if (!warm && luchtT > DAK_OPEN) { warm = true; if (automatisch) dakVraag(true); }    else if (warm && luchtT < DAK_DICHT) { warm = false; if (automatisch) dakVraag(false); }  }  if (modus == ONDERHOUD) koelen = true;             // verse lucht voor wie binnen werkt  bool verw = verwarmen && modus != OPSTART;  digitalWrite(VERWARMING, verw ? HIGH : LOW);  if (verw) nVerw++;  analogWrite(VENTILATOREN, koelen ? VENT_VOL : (dag ? VENT_DAG : VENT_NACHT));  // de pomp: één taak beslist over pin 9 (minuut 0-9 van elk uur, extra beurt om het halfuur)  int m = klok.minute();  if (m == 30 && !extraBeslist) {    extraBeslist = true;    extraBeurt = dag && lux / 1000.0 > SLAP_LICHT && luchtRV <= SLAP_VOCHT;    if (extraBeurt) melding("extra pompbeurt: slappe sla verwacht");  }  if (m < 30 || m >= 35) extraBeurt = extraBeslist = false;  bool pomp = (modus == DAG || modus == NACHT || modus == ALARM) && (m < 10 || extraBeurt)              && !(alarmen & (A_WATER | A_NIVEAU));  if (pomp != pompAan) { pompAan = pomp; pompSinds = nu; }  digitalWrite(POMP, pomp ? HIGH : LOW);  // CO2: alleen in DAG, met het dak dicht en zonder koelen: om het halfuur 30 s (K8)  bool co2 = modus == DAG && dak == DICHT && !koelen && m % 30 == 0 && klok.second() < 30;  digitalWrite(CO2_KLEP, co2 ? HIGH : LOW);} // ---------------------------------------------------------------- groeilampen: dimmen en energiebeheervoid taakLampen(unsigned long nu) {  if (nu - vorigeLamp < LAMP_MS) return;  vorigeLamp += LAMP_MS;  int doel = 0;  if (modus == ONDERHOUD) doel = WERKLICHT;  else if ((modus == DAG || modus == ALARM) && isDag()) {    float f = constrain((DOEL - lux / LUX_PER_UMOL) / LAMPEN_VOL, 0.0, 1.0);    doel = min((int)(f * 255 + 0.5), grens);  }  if (doel > stand) stand++;  else if (doel < stand) stand--;  analogWrite(LAMPEN, stand);} // ---------------------------------------------------------------- logger (hoofdstuk 30): elke minuut één regelvoid wisSommen() {  somT = somRV = somLux = somZon = somVerbruik = somU = somWT = somPH = somEC = somNiveau = somStand = 0;  nT = nMeting = nVermogen = nWT = nPH = nVerw = 0;} size_t schrijfRegel(Print& uit) {  size_t n = 0;  char tijd[17];  snprintf(tijd, sizeof(tijd), "%04d-%02d-%02d %02d:%02d", minuut.year(), minuut.month(), minuut.day(),           minuut.hour(), minuut.minute());  n += uit.print(tijd);  n += uit.print(',');  if (nT > 0) n += uit.print(somT / nT, 1);  n += uit.print(',');  if (nT > 0) n += uit.print(somRV / nT, 1);  n += uit.print(',');  if (nVermogen > 0) n += uit.print(somVerbruik / nVermogen / 60.0, 2);  n += uit.print(',');  if (nVermogen > 0) n += uit.print(somZon / nVermogen / 60.0, 2);  n += uit.print(',');  if (nMeting > 0) n += uit.print(somLux / nMeting, 0);  n += uit.print(',');  if (nVermogen > 0) n += uit.print(somU / nVermogen, 2);  n += uit.print(',');  n += uit.print(eindSoc, 1);  n += uit.print(',');  if (nMeting > 0) n += uit.print(somStand / nMeting, 0);  n += uit.print(',');  if (nMeting > 0) n += uit.print(100.0 * nVerw / nMeting, 0);  n += uit.print(',');  n += uit.print(eindDak);  n += uit.print(',');  if (nWT > 0) n += uit.print(somWT / nWT, 1);  n += uit.print(',');  if (nPH > 0) n += uit.print(somPH / nPH, 2);  n += uit.print(',');  if (nPH > 0) n += uit.print(somEC / nPH, 2);  n += uit.print(',');  if (nMeting > 0) n += uit.print(somNiveau / nMeting, 1);  n += uit.print(',');  n += uit.print(eindModus);  n += uit.print(',');  n += uit.print(eindAlarm);  n += uit.println();  return n;} void opslaan() {  size_t lang = schrijfRegel(Serial);  if (!kaartOk) return;  char naam[20];  snprintf(naam, sizeof(naam), "LOG/%04d%02d%02d.CSV", minuut.year(), minuut.month(), minuut.day());  bool nieuw = !SD.exists(naam);  File f = SD.open(naam, FILE_WRITE);  if (!f) {    melding("waarschuwing: SD, kan het bestand niet openen");    kaartOk = false;    return;  }  if (nieuw) f.println(KOP);  if (schrijfRegel(f) < lang) {    melding("waarschuwing: SD-kaart vol");    kaartOk = false;  }  f.close();} void loggen() {                                      // om de 2 s, na meten() en acties()  DateTime begin(klok.year(), klok.month(), klok.day(), klok.hour(), klok.minute(), 0);  if (!bezig) {    minuut = begin;    bezig = true;  } else if (begin.unixtime() != minuut.unixtime()) {    opslaan();    wisSommen();    minuut = begin;  }  if (!isnan(luchtT)) { somT += luchtT; somRV += luchtRV; nT++; }  if (!isnan(iZon) && !isnan(iVerbruik) && !isnan(uBus)) {    somZon += iZon * uBus;    somVerbruik += iVerbruik * uBus;    somU += uBus;    nVermogen++;  }  if (!isnan(waterT)) { somWT += waterT; nWT++; }  if (!isnan(ph) && !isnan(ec)) { somPH += ph; somEC += ec; nPH++; }  somLux += lux;  somStand += stand;  somNiveau += niveau;  nMeting++;  eindModus = modus;  eindAlarm = alarmen;  eindDak = dak;  eindSoc = soc;} void leesOpdracht() {                                // T2021-03-08 09:00:00 + Enter: de klok zetten  while (Serial.available() > 0) {    char c = Serial.read();    if (c == '\n' || c == '\r') {      opdracht[lengte] = '\0';      int j, mo, d, u, mi, s;      if (lengte > 0 && sscanf(opdracht, "T%d-%d-%d %d:%d:%d", &j, &mo, &d, &u, &mi, &s) == 6) {        rtc.adjust(DateTime(j, mo, d, u, mi, s));        klok = rtc.now();        melding("klok gezet");        wisSommen();        bezig = false;      }      lengte = 0;    } else if (lengte < (int)sizeof(opdracht) - 1) {      opdracht[lengte] = c;      lengte++;    }  }} // ---------------------------------------------------------------- statusled en EEPROMvoid taakStatusled(unsigned long nu) {               // normaal 500 ms, alarm 100 ms, onderhoud vast aan (G1)  if (modus == ONDERHOUD) { digitalWrite(STATUSLED, HIGH); return; }  unsigned long periode = (modus == ALARM) ? 100 : 500;  if (nu - ledSinds < periode) return;  ledSinds = nu;  ledAan = !ledAan;  digitalWrite(STATUSLED, (ledAan && modus != OPSTART) ? HIGH : LOW);} void taakBewaren(unsigned long nu) {                 // de laadtoestand overleeft een stroomonderbreking  if (nu - vorigeBewaring < BEWAAR_MS) return;  vorigeBewaring += BEWAAR_MS;  EEPROM.put(ADRES_SOC, soc);                        // schrijft alleen de bytes die veranderen} // ---------------------------------------------------------------- setup en loopvoid setup() {  wdt_disable();                                     // misschien zijn we net door de waakhond herstart  const int UIT[] = {LAMPEN, PWM_DICHT, PWM_OPEN, DAK_ENABLE, POMP, CO2_KLEP, VENTILATOREN, VERWARMING, STATUSLED};  for (int p : UIT) { pinMode(p, OUTPUT); digitalWrite(p, LOW); }   // veilig starten: alles uit  digitalWrite(DAK_ENABLE, HIGH);  pinMode(VLOTTER, INPUT_PULLUP);  pinMode(KNOP, INPUT);  pinMode(EIND_OPEN, INPUT_PULLUP);  pinMode(EIND_DICHT, INPUT_PULLUP);  Serial.begin(115200);  Wire.begin();  rtc.begin();  sht.begin(0x44);                                   // antwoordt ze niet, dan volgt het alarm na 30 s  klok = rtc.now();  byte ina[] = {INA_ZON, INA_VERBRUIK};  for (int i = 0; i < 2; i++) {                      // INA226: 128 metingen middelen (282 ms)    Wire.beginTransmission(ina[i]);    Wire.write(0x00);    Wire.write(0x49);    Wire.write(0x27);    Wire.endTransmission();  }  kaartOk = SD.begin(SD_CS);  if (kaartOk && !SD.exists("LOG")) SD.mkdir("LOG");  EEPROM.get(ADRES_SOC, soc);  if (isnan(soc) || soc < 0.0 || soc > 100.0) soc = 50.0;   // leeg EEPROM: een ruwe schatting  eindSoc = soc;  niveau = niveauCm();  unsigned long nu = millis();  droogSinds = nu;  melding("klimaatmodule v5 (hoofdstuk 40)");  Serial.print("# laadtoestand uit het EEPROM: ");  Serial.print(soc, 1);  Serial.println(" %");  if (!kaartOk) melding("waarschuwing: geen SD-kaart");  Serial.println(KOP);  naar(OPSTART, nu);  dakStart(nu);  wdt_enable(WDTO_2S);                               // komt loop() 2 s niet langs wdt_reset(): herstart (B5)} void loop() {  wdt_reset();  unsigned long nu = millis();  leesOpdracht();  bool kort, lang;  leesKnop(nu, kort, lang);  if (nu - vorigeMeting >= MEET_MS) {    vorigeMeting += MEET_MS;    klok = rtc.now();    meten(nu);    acties(nu);    loggen();  }  taakModus(nu, kort, lang);  taakDak(nu);  taakLampen(nu);  taakStatusled(nu);  taakBewaren(nu);}

Wat er nieuw is tegenover versie 2 en 4:

  • De laadtoestand telt nu met de twee INA226: iLaad = iZon - iVerbruik, om de 2 s opgeteld (een coulombteller, hoofdstuk 16). Bij 14,2 V met een kleine laadstroom zijn de batterijen vol en wordt de teller opnieuw op 100 % gezet.
  • Het energiebeheer zit in meten(): boven 40 % mogen de lampen alles, onder 20 % niets, daartussen schuift de grens 5 stappen op of af naargelang de batterijen laden of leveren (hoofdstuk 29).
  • band() geeft een waarschuwing met hysterese: aan buiten de band, pas weer uit als de waarde 0,05 (of 0,5 °C) binnen de band zit. Zonder hysterese zou een pH die rond 6,50 schommelt tientallen meldingen geven (hoofdstuk 31).
  • De pomp wordt in acties() beslist: minuut 0-9, of minuut 30-34 als de beslisboom om 30 minuten slappe sla verwachtte, nooit bij een water- of niveau-alarm en niet in ONDERHOUD. Het niveau telt pas 2 minuten na de pomp.
  • De logger schrijft 17 kolommen: de 7 van hoofdstuk 28 en 30, en 10 nieuwe achteraan, zodat oude Python-scripts blijven werken (hoofdstuk 30).

Getest. Het programma compileert zonder waarschuwingen met g++ tegen een nagebootste Arduino, ook met int = 16 bit zoals op de Mega. In een gesloten lus met een model van de module draaide het een week: 59 miljoen rondes van loop(), de langste 48,8 ms (eis B6: hoogstens 100 ms; de SHT31 alleen wacht al 20 ms), 432 schrijfbeurten in het EEPROM (alleen bytes die veranderen) en acht dagbestanden op de kaart. De testweek van dit hoofdstuk komt uit dezelfde simulatie, in Python nagebouwd: per dag verschillen verbruik, zon en warmte minder dan 0,5 %.

Naslag · 40.17

Het logformaat van versie 5

17/28

Eén regel per minuut, op de SD-kaart in LOG/JJJJMMDD.CSV en tegelijk over USB (hoofdstuk 30). Een lege cel betekent: geen geldige meting in die minuut. Nieuwe kolommen komen achteraan, zodat een script dat de eerste zeven kolommen leest, blijft werken.

kolomeenheidwat erin staatsinds
tijdstipjjjj-mm-dd uu:mmbegin van de minuut, UTC+128
temperatuur_C°Cgemiddelde van de SHT31 (leeg zonder meting)28
vocht_pct%relatieve vochtigheid van de lucht28
verbruik_WhWhenergie naar de verbruikers in die minuut (INA226 0x41)28
zon_WhWhgeleverde zonnestroom in die minuut (INA226 0x40)28
licht_lxlxdaglicht op de LDR30
batterij_VVbusspanning van de rail30
soc_pct%laadtoestand aan het einde van de minuut40
lampen_pwm0-255gemiddelde lampstand40
verw_pct%deel van de minuut met de verwarming aan40
dak0-5DICHT, OPENEN, OPEN, SLUITEN, GESTOPT, DAK_FOUT40
water_C°Cvoedingsoplossing (NTC)40
pHgemiddelde van de minuut40
EC_mScmmS/cmomgerekend naar 25 °C40
niveau_cmcmreservoir, gemeten bij stilstaande pomp40
modus0-4OPSTART, DAG, NACHT, ALARM, ONDERHOUD40
alarmbits1 temperatuur, 2 vlotter, 4 niveau, 8 dak, 16 batterij40

Vijf regels uit de testweek (donderdag, de sensorkast is van 14:02 tot 14:07 losgekoppeld)

tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh,licht_lx,batterij_V,soc_pct,lampen_pwm,verw_pct,dak,water_C,pH,EC_mScm,niveau_cm,modus,alarm
2021-03-11 14:01,25.4,49.6,0.49,0.58,39142,14.30,100.0,0,0,2,21.5,6.21,1.36,21.5,1,0
2021-03-11 14:02,,,0.35,0.43,39112,14.30,100.0,0,0,2,21.5,6.21,1.36,21.5,3,1
2021-03-11 14:03,,,0.34,0.42,39082,14.30,100.0,0,0,2,21.5,6.21,1.36,21.5,3,1
2021-03-11 14:07,26.2,47.6,0.49,0.57,38961,14.30,100.0,0,0,2,21.6,6.21,1.36,21.5,3,0
2021-03-11 14:08,26.2,47.8,0.49,0.58,38930,14.30,100.0,0,0,2,21.6,6.21,1.36,21.5,3,0

Om 14:02 zijn temperatuur en vocht leeg, springt de modus naar 3 (ALARM) en staat alarmbit 1 (geen temperatuur) aan. Om 14:07 is de meting terug en het alarmbit uit, maar de modus blijft 3 tot iemand kort op S1 drukt (14:09). Het verbruik zakt in die minuten van 0,49 naar 0,35 Wh per minuut: zonder meting koelt het noodprogramma niet, en de ventilatoren vallen terug.

groottewaarde
regel±84 tekens
dagbestand±121 kB (hoofdstuk 30, met 7 kolommen: 68,5 kB)
kaart van 1 GB±23 jaar
Uitleg · 40.18

Fase 4 · testen: van deeltest tot testweek

18/28

Testen volgt de rechterkant van het V-model: van de delen naar het geheel, en elke test toetst de ontwerpstap die ertegenover staat.

  1. Deeltests, zodra een onderdeel klaar is: elke sensor naast een referentie, elke tak met de stroomtang, de pomp met een maatbeker per goot, het dak met een blokje in de rail.
  2. Integratietests: werkt elke interface zoals de tabel zegt? De I²C-scanner vindt vier adressen, de logger schrijft 17 kolommen, de pomp slaat aan in minuut 0 en niet in minuut 11.
  3. Storingstests: je veroorzaakt een fout en kijkt of het systeem reageert zoals ontworpen. Wat er moet gebeuren, schrijf je vooraf op.
  4. De testweek: de module draait zeven dagen alleen. Elke dag kijkt één teamlid in de logbestanden, zonder in te grijpen tenzij de planten of de veiligheid het vragen.
storingstestwanneerwat moet er gebeuren (vooraf)wat de logger toondeeis
stekker van de sensorkast los (5 min)do 14:02na 30 s alarm, noodprogramma voor de verwarming, lege cellenalarm om 14:02:28, 5 regels zonder temperatuurB2, B3, D2
vlotter met de hand omhoog (1 min)do 14:15na 10 s alarm, pomp uitalarm om 14:15:08W3, B2
stekker van de regelkast uit (2 min)do 15:56alles uit; daarna OPSTART, laadtoestand uit het EEPROMOPSTART 15:58:00, DAG 15:58:06; 3 regels ontbrekenB1, E5, D1
lange druk op S1: onderhoudwo 10:12pomp uit, dak geblokkeerd, werklicht, ventilatoren volmodus 4 van 10:12 tot 10:29B4
blokje in de rail van het dakdeeltest, vrna 12 s DAK_FOUT en alarm; kort drukken: opnieuw sluitenzie K5 (voor de testweek)K5
een taak die blijft hangendeeltest (hoofdstuk 32)de waakhond herstart de Mega na 2 sherstartB5

De simulatie als generale repetitie. Voor de module een week alleen blijft, draait het voorbeeldteam versie 5 in een simulatie: het programma krijgt nagebootste sensoren, en een model van de module (warmte zoals hoofdstuk 31, zon zoals hoofdstuk 20) reageert op wat het programma schakelt. Zo vind je fouten in de code voor ze in de echte module zitten. De testweek van dit hoofdstuk is zo'n simulatie; wie de module echt heeft (spoor A), vervangt ze door de eigen logbestanden.

Een model is geen meting

Een simulatie toont wat het programma doet met de module zoals je ze gemodelleerd hebt. Klopt het model niet (een dak dat minder koelt, een sla die meer verdampt), dan klopt de uitkomst ook niet. Schrijf daarom bij elk resultaat of het uit een meting, een berekening of een simulatie komt, en vergelijk het model met echte metingen zodra je ze hebt (E17, E36).

programma van eisen van demoduledimensionering perdeelsysteemonderdelen: schema's, code,rekbouwen en programmerendeeltests: sensor, tak,pompintegratietests:interfaces, storingensysteemtest: de testweektoetsttoetstlinks: ontwerpen, van het geheel naar de delenrechts: testen, van de delen naar het geheel
Links ontwerp je van het geheel naar de delen, rechts test je van de delen naar het geheel; elke stippellijn is een toets.
Uitleg · 40.19

De testweek: 8 tot 14 maart 2021

19/28

De testweek begon op maandag met een grijze start: laadtoestand 55 %, reservoir op 22 cm. Het logboek van het team:

wanneerwatgevolg in de logbestanden
ma 8 maart 0:00start van de testweek; laadtoestand 55 %, reservoir 22 cm, EC 1,40, pH 5,86—
ma en digrijs (zonfactor 0,35 en 0,25), 3 tot 9 °Claadtoestand onder 40 %: de lampen krijgen alleen zonne-overschot
wo 10:12-10:29onderhoud: 13 L regenwater en 130 mL A + 130 mL B bijgevuldmodus 4; niveau van 18,9 naar 24,3 cm
wo en dozonnig, tot 14 °C buitendak 10 en 14 keer open; batterijen vol, zonnestroom afgeknepen
do 14:00-16:00storingstests: sensorkast, vlotter, stroomalarmen, lege cellen, 3 ontbrekende regels
zaheel grijs (zonfactor 0,20)laadtoestand van 77 naar 38 %; lichtsom 9,2 mol
zo 10:12pH boven 6,5waarschuwing in de meldingen; niemand in de module
ma 15 maartpH bijgestuurd met pH-min, reservoir bijgevuld(na de testweek)

Wat de vier grafieken tonen:

  • Temperatuur. 's Nachts de zaagtand van de verwarming rond 16-17 °C, overdag 18-19 °C op grijze dagen. Woensdag en donderdag stijgt de lucht tot 27,1 °C: dan gaat het dak 10 en 14 keer open. De verwarming vroeg 14,0 kWh warmte van het station, van 0,8 tot 4,3 uur per dag.
  • Energie. De panelen hadden 23,9 kWh kunnen leveren, maar de regelaar nam er maar 11,4 af: op de zonnige dagen waren de batterijen voor de middag vol, en 12,4 kWh bleef ongebruikt. Het verbruik was 10,2 kWh, waarvan 8,2 kWh voor de lampen.
  • Laadtoestand. Tussen 35 en 100 %. Onder 40 % van maandagavond tot dinsdagmiddag, van dinsdagavond tot woensdagochtend en van zaterdagavond tot zondagochtend: dan kregen de lampen alleen zonne-overschot. Nooit onder 20 %.
  • Voedingsoplossing. De pH stijgt gestaag, van 5,86 naar 6,59; zondag om 10:12 passeert ze 6,5. De EC zakt langzaam, van 1,40 naar 1,31: de sla neemt verhoudingsgewijs meer zouten op dan water. Het niveau zakt van 21,9 naar 14,6 cm, met het bijvullen van woensdag ertussen.
01234567−4048121620242832dagen sinds maandag 8 maart, 0 uur (UTC+1)temperatuur (°C)dak open boven 27lucht in de module (SHT31)buiten0123456702004006008001000dagen sinds maandag 8 maart, 0 uur (UTC+1)vermogen (W)wat de panelen konden gevenzonnestroom geleverdverbruik01234567020406080100dagen sinds maandag 8 maart, 0 uur (UTC+1)laadtoestand (%)20 %40 %: lampen alleen op zonlaadtoestand (coulombteller)pH 5,5-6,5012345675,25,45,65,86,06,26,46,66,87,0dagen sinds maandag 8 maart, 0 uur (UTC+1)pH1,11,21,31,41,51,61,71,81,9EC (mS/cm)pH (linkeras)EC (rechteras)
Gemiddelden per 10 minuten uit de logbestanden (simulatie). De grijze stippellijn in de tweede grafiek is wat de panelen hadden kunnen geven.
Code · 40.20

De testweek analyseren in Python

20/28

Zeven dagbestanden van 1440 regels lees je niet met het oog. Het script leest ze met het csv-moduul (hoofdstuk 28 en 30), maakt per dag een rapport en toetst een deel van de eisen. Twee keuzes: een lege cel wordt None en telt niet mee in een minimum; en 'overdag' begint voor K1 pas om 7 uur, omdat de module om 6 uur van de nacht- naar de daginstelling springt en even moet opwarmen (dat staat zo in het programma van eisen, niet achteraf bedacht).

Pythontestweek.py64 regelsDownload
# testweek.py - de logbestanden van de klimaatmodule toetsen aan het programma van eisenimport csv DAGEN = ["20210308", "20210309", "20210310", "20210311", "20210312", "20210313", "20210314"]NAAM = ["ma", "di", "wo", "do", "vr", "za", "zo"]  def getal(tekst):    """Tekst naar kommagetal; een lege cel (geen meting) wordt None."""    return float(tekst) if tekst != "" else None  def lees(dag):    with open("LOG/" + dag + ".CSV", newline="") as f:        return [{k: (v if k == "tijdstip" else getal(v)) for k, v in r.items()} for r in csv.DictReader(f)]  def uur(r):    return int(r["tijdstip"][11:13])  def dagrapport(rijen):    dag = [r for r in rijen if 7 <= uur(r) < 22 and r["temperatuur_C"] is not None]    nacht = [r for r in rijen if not 6 <= uur(r) < 22 and r["temperatuur_C"] is not None]    par = [r["licht_lx"] / 54 + 200 * r["lampen_pwm"] / 255 for r in rijen if 6 <= uur(r) < 22]    paren = list(zip(rijen, rijen[1:]))                    # (deze minuut, volgende minuut)    return {        "regels": len(rijen),        "T_dag": (min(r["temperatuur_C"] for r in dag), max(r["temperatuur_C"] for r in dag)),        "T_nacht": min(r["temperatuur_C"] for r in nacht),        "zon": sum(r["zon_Wh"] for r in rijen) / 1000,                    # kWh        "verbruik": sum(r["verbruik_Wh"] for r in rijen) / 1000,        "soc": min(r["soc_pct"] for r in rijen),        "lichtsom": sum(p * 60 for p in par) / 1e6,                       # mol/(m² dag)        "verwarming": sum(r["verw_pct"] for r in rijen) / 100 / 60,       # uur        "starts": sum(1 for a, b in paren if a["verw_pct"] == 0 and b["verw_pct"] > 0),        "dak": sum(1 for a, b in paren if a["dak"] == 0 and b["dak"] > 0),        "pH": max(r["pH"] for r in rijen),        "EC": min(r["EC_mScm"] for r in rijen),        "niveau": min(r["niveau_cm"] for r in rijen),    }  week = [dagrapport(lees(dag)) for dag in DAGEN]print("dag regels  T overdag  nacht   zon verbr  SoC licht verw starts dak  pH   EC niveau")for naam, d in zip(NAAM, week):    print(f"{naam}  {d['regels']:5d}  {d['T_dag'][0]:4.1f}-{d['T_dag'][1]:4.1f}  {d['T_nacht']:4.1f}  "          f"{d['zon']:4.2f}  {d['verbruik']:4.2f}  {d['soc']:3.0f}  {d['lichtsom']:4.1f}  {d['verwarming']:3.1f}"          f"  {d['starts']:3d}  {d['dak']:3d} {d['pH']:4.2f} {d['EC']:4.2f}  {d['niveau']:4.1f}")  def toets(code, tekst, fout):    print(f"{code}  {tekst:38s} {'gehaald' if not fout else 'NIET: ' + ', '.join(fout)}")  print()toets("K1", "overdag (7-22 h) nooit onder 17,5 C", [n for n, d in zip(NAAM, week) if d["T_dag"][0] < 17.5])toets("K2", "'s nachts nooit onder 15,5 C", [n for n, d in zip(NAAM, week) if d["T_nacht"] < 15.5])toets("K3", "nooit boven 30 C", [n for n, d in zip(NAAM, week) if d["T_dag"][1] > 30])toets("L1", "lichtsom minstens 11,0 mol per dag", [n for n, d in zip(NAAM, week) if d["lichtsom"] < 11.0])toets("E3", "laadtoestand nooit onder 20 %", [n for n, d in zip(NAAM, week) if d["soc"] < 20])toets("H1", "EC nooit onder 1,2 mS/cm", [n for n, d in zip(NAAM, week) if d["EC"] < 1.2])toets("H2", "pH nooit boven 6,5", [n for n, d in zip(NAAM, week) if d["pH"] > 6.5])toets("D1", "1440 regels per dag", [n for n, d in zip(NAAM, week) if d["regels"] != 1440])

De uitvoer:

dag regels  T overdag  nacht   zon verbr  SoC licht verw starts dak  pH   EC niveau
ma   1440  18.0-21.4  16.0  1.47  1.94   39  10.6  2.8   48    0 5.94 1.38  20.0
di   1440  18.0-20.2  16.0  1.05  1.08   36   6.0  4.3   70    0 6.00 1.38  19.0
wo   1440  17.9-27.0  16.0  2.54  1.09   35  21.4  3.0   43   10 6.16 1.37  18.6
do   1437  18.0-27.1  16.0  1.46  1.36   67  23.6  1.7   30   14 6.29 1.35  20.1
vr   1440  18.0-25.0  16.0  1.56  1.58   65  13.4  0.8   16    0 6.40 1.34  18.0
za   1440  18.0-20.1  16.0  0.84  2.05   38   9.2  2.3   41    0 6.48 1.33  16.6
zo   1440  18.0-25.2  16.0  2.50  1.13   35  15.1  2.6   40    0 6.59 1.31  14.6

K1  overdag (7-22 h) nooit onder 17,5 C    gehaald
K2  's nachts nooit onder 15,5 C           gehaald
K3  nooit boven 30 C                       gehaald
L1  lichtsom minstens 11,0 mol per dag     NIET: ma, di, za
E3  laadtoestand nooit onder 20 %          gehaald
H1  EC nooit onder 1,2 mS/cm               gehaald
H2  pH nooit boven 6,5                     NIET: zo
D1  1440 regels per dag                    NIET: do

Lees ze eerst per kolom. regels: donderdag ontbreken er drie (de stroomtest). licht: maandag, dinsdag en zaterdag onder 11,0 mol. starts: dinsdag 70 keer verwarmen op één dag, maar in één uur nooit meer dan 6 keer (eis K6, een aparte telling per uur). dak: alleen woensdag en donderdag. pH: zondag boven 6,5.

Twee eisen zijn niet gehaald (L1 en H2), en D1 geeft 'NIET' voor donderdag: dat is geen fout van de module maar van de toets, want de stroomtest stond in het testplan. Het testrapport noteert daarom 'ja' met een verklaring. Een toets in code is streng en eerlijk; het oordeel blijft werk voor mensen.

0510152025lichtsom (mol/(m²·dag))10,6621,423,613,49,215,1madiwodovrzazo
Rood: onder 11,0 mol/(m²·dag). De zonnige dagen geven twee keer meer licht dan nodig.
01234567kWh per dagmadiwodovrzazowat de panelen konden gevenzonnestroom geleverdverbruik
Woensdag en donderdag konden de panelen 6,5 en 6,9 kWh geven; de module nam er 2,5 en 1,5 kWh van af.
Naslag · 40.21

Het testrapport van het voorbeeldteam

21/28

Per eis de toets, het resultaat en het besluit. Van de 47 moet-eisen zijn er 43 gehaald, één voorlopig (K3: de zomer komt nog), één kan pas na vijf weken getoetst worden (W5) en twee zijn niet gehaald. Van de 7 wensen zijn er 5 gehaald, één niet (H4) en één pas na een jaar te toetsen (P2).

L1, de lichtsom. Op drie grijze dagen bleef de lichtsom onder 11,0 mol. De oorzaak is geen fout maar een botsing tussen twee eisen: E3 (nooit onder 20 %) en E4 (eerst de lampen afknijpen) winnen van L1. Opvallend: dezelfde week werd 12,4 kWh zonnestroom afgeknepen. Een grotere buffer of stroom van het station zou beide eisen laten samengaan (werkboek).

H2, de pH. De waarschuwing kwam op zondag om 10:12, maar niemand zag ze tot maandag. De module deed wat het ontwerp vroeg; het ontwerp vroeg te weinig. Twee oplossingen: vrijdag de pH preventief naar 5,8 brengen (bij +0,1 à 0,15 per dag blijft ze dan tot maandag onder 6,5), of de melding naar een telefoon sturen (E37).

codeeistoetsresultaat (voorbeeldteam)besluit
K1overdag (7-22 h) minstens 17,5 °C bij de plantenlogger, testweeklaagste 17,9 °Cja
K2's nachts (22-6 h) minstens 15,5 °Clogger, testweeklaagste 16,0 °Cja
K3hoogstens 30 °Clogger, zonnige dagenhoogste 27,1 °C (do)voorlopig
K4ventilatoren vol boven 25 °C, dak open boven 27 °C; terug onder 24 en 25 °Cnaspelen, logger24 keer open (wo, do), drempels juistja
K5het dak haalt zijn eindpunt binnen 12 s, anders alarmdeeltest: blokje in de railsluit in 6,8 s; met blokje alarm na 12 sja
K6verwarming hoogstens 6 keer aan per uurlogger: starts per uurhoogstens 6 (wo 5-6 h)ja, net
K7basisventilatie overdag minstens 11 m³/hanemometer aan het rooster11,9 m³/hja
K8CO₂-klep alleen in DAG met het dak dichtnaspelen, codein ordeja
L1lichtsom op het bed minstens 11,0 mol/(m²·dag)logger: daglicht + lampenma 10,6, di 6,0, za 9,2nee
L2lampen vullen het daglicht aan tot 200 µmol/(m²·s), hoogstens 1 stap per 200 mslogger, codein ordeja
L3volle lampen: elk van 9 meetpunten ≥ 180 µmol/(m²·s)PAR-meter, 's nachts186 tot 214ja
W11,2 L/min per goot (± 20 %)maatbeker, 1 min per goot1,08 tot 1,31; na bijstellen 1,19 tot 1,21ja
W2pomp in minuut 0-9 van elk uur, extra beurt als slappe sla verwacht wordtlogger, meldingen7 extra beurtenja
W3de pomp draait nooit droogvlotter met de hand omhoogalarm na 8 s, pomp uitja
W4minstens 5 dagen zonder bijvullen bij 6 L per dagberekening, logger36 L / 6 L = 6,0 dagenja
W5reservoir lichtdicht: algen onder 5 · 10⁵ per mLtelling na 5 wekenpas na 5 wekenlater
H1EC tussen 1,2 en 1,8 mS/cm (bij 25 °C)logger1,31 tot 1,40ja
H2pH tussen 5,5 en 6,5logger5,86 tot 6,59; zo 10:12 boven 6,5nee
H3voedingsoplossing nooit boven 24 °Cloggerhoogste 23,0 °Cja
H4voedingsoplossing tussen 18 en 22 °Clogger17,1 tot 23,0 °Cnee
H5pH-sensor om de twee weken in twee punten geijkt, EC met ijkvloeistofijkverslag−0,177 V/pH; 1,42 in 1,413ja
E1van maart tot oktober genoeg zonnestroom: saldo per maand ≥ 0berekening PVGIS, testweekmaart +2,6, oktober +1,8 kWh/dagja
E2de batterijen overbruggen de nacht in de slechtste maandberekening1,84 kWh (december)ja
E3laadtoestand nooit onder 20 %loggerlaagste 35 %ja
E4energiebeheer: onder 40 % lampen op zonnestroom, onder 20 % uit, onder 10 % alarmlogger (dinsdag)dinsdag: lampen begrensdja
E5laadtoestand elk uur in het EEPROM, na een stroomuitval hersteldstekker van de regelkast uit100,0 → 100,0 %ja
E65 V-rail aan de sensorkast minstens 4,75 Vmeten: pomp aan, SD schrijft4,91 Vja
E7batterijen niet laden onder 0 °CBMS-instelling, loggerlaagste 16,0 °Cja
E8jaarverbruik hoogstens 700 kWhberekening±540 kWhja
B1na een stroomuitval: alles uit, OPSTART 5 s, dan de gewone modusstekker van de regelkast uit15:58:00 OPSTART, 15:58:06 DAGja
B2alarm bij: geen temperatuur 30 s, vlotter droog 10 s, reservoir onder 10 cm, dak-time-out, batterij onder 10 %storingstestssensor na 28 s, vlotter na 8 sja
B3zonder temperatuur verwarmt de module met de gemiddelde inschakelduurstoringstest sensorin ordeja
B4onderhoud: lange druk van 3 s; pomp uit, dak geblokkeerd, werklicht; na 60 min terugwoensdagwo 10:12 tot 10:29ja
B5waakhond: een hangende taak herstart de Mega binnen 2 sdeeltest (hoofdstuk 32)in ordeja
B6langste ronde van loop() hoogstens 100 mssimulatie, micros()48,8 msja
B7één taak per uitgangcode nalezenin orde (pomp samengevoegd)ja
D1elke minuut een CSV-regel, één bestand per daglogbestanden1440; do 1437 (stroomtest)ja
D2een ontbrekende meting geeft een lege celstoringstest sensor5 regelsja
D3minstens een jaar op de kaartberekening±121 kB per dag: 1 GB ≈ 23 jaarja
D4klok op UTC+1, hoogstens 1 min afwijking per maandreferentieklok±5 s per maand (±2 ppm)ja
D5dag- en weekrapport in Python, gekoppeld aan de eisentestweek.pyin ordeja
V1in de kweekruimte alleen 12,8 V en 5 Vchecklistin ordeja
V2zekering per tak en bij elke batterijpoolschema, keuringin ordeja
V3niemand onder een bewegend daktest in onderhoudin ordeja
V4pH-min (salpeterzuur 0,50 mol/L) gelabeld, met bril en handschoenenchecklistin ordeja
C1reservoir (65 kg vol) met zijn midden tussen 0,65 en 1,31 m van ligger Arolmeter0,98 mja
C2dakmotor trekt 120 N zonder te blokkerentrekproef met veerunster120 N bij 3,4 Aja
G1statusled: rustig normaal, snel bij alarm, vast bij onderhoudtestin ordeja
G2kasdak met de hand: korte druk op S1 naast de deurtestin ordeja
G3wekelijks onderhoud (bijvullen, EC en pH) hoogstens 20 mintijd opnemen17 minja
G4hydroponie hoogstens € 800kostenraming€ 788ja
P148 plantplaatsen, om de 8,75 dagen een goot oogstenteeltschemain ordeja
P2minstens 100 kg sla per jaarwegen, een jaar langmodel: 100 kglater
O1hoogstens 2 kg CO₂-eq per kg slalevenscyclusanalyse1,64ja
Uitgewerkt voorbeeld · 40.22

Foutzoeken met de logger: de klep klikt voortdurend

22/28

Een ander team hing de sensorkast SK-1 op 40 cm boven de convector: daar kwam de kabel van 3 m net toe. De eerste ochtend hoort een bewoner de klep van de convector aan één stuk klikken. De sla staat er goed bij, de statusled knippert rustig. Het logbestand van maandag, 7:00 tot 7:08:

tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh,licht_lx,batterij_V,soc_pct,lampen_pwm,verw_pct,dak,water_C,pH,EC_mScm,niveau_cm,modus,alarm
2021-03-08 07:00,18.7,83.5,3.51,0.04,107,12.95,46.5,252,0,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:01,18.3,83.7,3.47,0.04,110,12.95,46.4,252,0,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:02,18.1,83.9,3.53,0.04,114,12.94,46.3,252,37,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:03,18.9,83.2,3.58,0.05,117,12.94,46.2,252,47,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:04,19.0,83.3,3.47,0.05,121,12.95,46.0,252,0,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:05,18.5,83.5,3.47,0.05,124,12.95,45.9,252,0,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:06,18.2,83.8,3.47,0.05,128,12.95,45.8,252,0,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:07,18.2,83.7,3.60,0.05,131,12.94,45.7,252,70,0,16.9,5.86,1.40,21.8,1,0
2021-03-08 07:08,19.2,83.1,3.51,0.05,135,12.94,45.6,252,13,0,16.9,5.86,1.40,21.8,1,0

Waar zit de fout, hoe bevestig je ze, en hoe los je ze op?

5,05,56,06,57,07,58,08,59,0141516171819202122uur (maandag, UTC+1)temperatuur (°C)6 uur: DAG20406080100verwarming (% van de minuut)verwarming (rechteras)sensor boven de convectorlucht bij de planten
De sensor (blauw) volgt de pluim van de convector, de lucht bij de planten (groen) blijft rond 18 °C. De verwarming (rood) klapt aan en uit.
Gegeven
  • het logbestand hierboven (kolommen: blad 'Het logformaat van versie 5')
  • verwarming aan onder 18 °C, uit boven 19 °C (hoofdstuk 31); eis K6: hoogstens 6 keer aan per uur
  • een referentiethermometer bij de planten, op 1,2 m hoogte
Gevraagd
  • wat het logbestand zegt
  • een hypothese en een test die één ding verandert
  • de oplossing en de hertest
Oplossing
  1. 1
    Lees wat de module zelf vertelt. Geen alarm (kolom alarm 0, modus 1): de module denkt dat alles in orde is. Maar verw_pct springt van minuut tot minuut: 0, 37, 47, 0, 70, 13 %. De verwarming gaat binnen één minuut aan en weer uit. Geteld over een uur: 14 keer aan tussen 7 en 8 uur, tegenover ±4 op dezelfde ochtend in de testweek. Eis K6 is ruim overschreden.
  2. 2
    Vergelijk met een referentie. Tussen 7 en 9 uur meet de SHT31 gemiddeld 18,6 °C, de referentie bij de planten 18,0 °C. De sensor meet warmer dan de lucht waarin de planten staan, en de temperatuur in het logbestand springt tot 1 °C per minuut: veel sneller dan een ruimte met 80 kJ/K kan opwarmen (hoofdstuk 31).
  3. 3
    Hypothese. De sensor zit in de warme luchtstroom van de convector. Zodra die blaast, meet hij binnen een minuut 19 °C en schakelt de verwarming uit; de luchtstroom stopt, de sensor koelt af tot onder 18 °C, en de klep gaat weer open. De regeling regelt de lucht rond de sensor, niet de module.
  4. 4
    Test die één ding verandert. Hang de referentiethermometer naast de SHT31, boven de convector. Zijn ze het daar eens, dan meet de sensor juist en is de plaats fout. Hang daarna alleen de sensorkast om, midden in de ruimte op planthoogte, en laat de rest zoals het was.
  5. 5
    Oplossen en hertesten. Na het verplaatsen: een nacht loggen en tellen. In het model valt de verwarming terug naar ±4 starts per uur en verdwijnt het verschil met de referentie. Noteer de verplaatsing in de interfacetabel (I7: de plaats van de sensor hoort bij de afspraak).
Antwoord
De sensorkast hangt in de warme lucht van de convector: de verwarming schakelt 14 keer per uur en de sensor meet ±0,5 °C te warm. De sensorkast moet midden in de ruimte hangen, niet boven de warmtebron (hoofdstuk 31).
Klopt dit? Hetzelfde symptoom (veel korte beurten) kan ook een te smalle hysterese of een te grote verwarming zijn. Daarom verander je telkens maar één ding en kijk je opnieuw in het logbestand. Een minimum aantijd van 2 minuten in de code (werkboek) beschermt de klep ook tegen zo'n fout, maar lost de oorzaak niet op: de sensor zou nog altijd de verkeerde lucht meten. Het model rekent met een pluim van +3 °C boven de convector (rekenwaarde); de grafiek is dus een simulatie, zoals de testweek.
Naslag · 40.23

De foutzoektabel van de module

23/28

Per symptoom de mogelijke oorzaken, de waarschijnlijkste eerst, met een test die telkens één ding controleert. Begin altijd bij wat de module zelf vertelt: de statusled, de meldingen en de logbestanden. Voeg de fouten toe die jullie zelf vinden: zo groeit de tabel mee met de module.

symptoommogelijke oorzaak (waarschijnlijkste eerst)test (telkens één ding)oplossing
alles donker, statusled uitzekering van de omvormer (1 A); BMS schakelde af; stekker van de regelkast12,8 V op de rail? 5 V na de omvormer?oorzaak van de zekering zoeken, dan vervangen; batterijen laden
statusled knippert sneleen alarm: geen temperatuur, vlotter, niveau, dak of batterijde meldingen (#) en de kolom alarm lezende oorzaak oplossen, dan kort drukken op S1
lampen zwak op een grijze daglaadtoestand onder 40 %: het energiebeheer; LDR ziet een lamp; lamp of MOSFET defectlogger: soc_pct, lampen_pwm, licht_lx naast elkaarbij een lage laadtoestand is het een ontwerpkeuze (eis L1, werkboek)
pomp slaat om de paar seconden aan en uittwee taken schrijven naar pin 9elke plaats in de code die de pomp schakelt opzoekenéén eigenaar (versie 5)
een goot krijgt weinig waterkraantje dicht of verstopt; wortels in de verzamelbuis; pomp zuigt luchtmaatbeker aan het einde van elke goot, 1 minkraantje bijstellen, goot reinigen bij het oogsten
elk uur een niveau-alarm in minuut 1 tot 9niveau gemeten terwijl er water in de goten staatniveau_cm per minuut rond minuut 0niveau pas 2 min na de pomp (versie 5); reservoir bijvullen
pH springt als de pomp aanslaatgedeelde massadraad (hoofdstuk 21)pH-kolom rond minuut 0 en 10eigen retourdraad per tak naar het sterpunt
pH loopt op tot boven 6,5normale stijging (0,1 à 0,15 per dag); niemand stuurde bijpH per dag in de loggerpH-min na een proeftitratie; vrijdag preventief
EC zakt na het bijvullenalleen regenwater bijgevuldEC voor en na het bijvullen10 mL A en 10 mL B per liter bijgevuld water
temperatuur leeg in de loggerSHT31 los, kabel van 3 m, pull-upsI²C-scanner: staat 0x44 erbij?stekker, kabel, pull-ups nakijken (hoofdstuk 30)
klep van de convector klikt tot 14 keer per uursensorkast in de warme lucht van de convector; hysterese te smalstarts per uur; referentiethermometer bij de plantensensorkast midden in de ruimte (hoofdstuk 31); eventueel een minimum aantijd
dak blijft half open, alarmblokje of ijs in de rail; eindeloop defect; zekering 5 Amelding 'dak haalt zijn eindpunt niet'; eindeloop met de handvrijmaken, dan kort drukken: het dak sluit opnieuw
laadtoestand 100 % terwijl de spanning zaktde teller is lang niet opnieuw geijktrustspanning 's morgens tegenover soc_pctde batterijen één keer laten vollopen tot 14,2 V
logbestand ontbreekt of is leegkaart vol of weg; naam niet 8.3; stroom viel weg voor close()melding 'SD'; kaart in de laptopkaart vervangen; bestandsnaam nakijken (hoofdstuk 30)
module te warm met het dak openzon op een zomerdag groter dan dak en ventilatoren aankunnentemperatuur tegenover zonnestroomschaduwdoek of nachtscherm als zonnescherm (versie 2)
Uitleg · 40.24

Fase 5 · het technisch rapport

24/28

Een technisch rapport is geschreven voor iemand die het project niet volgde, maar er verder mee moet: een volgend team, een ingenieur van het station, de jury. Die lezer leest eerst de samenvatting, dan de figuren, en pas daarna de tekst. De opbouw volgt de fasen:

onderdeelwat erin staatbij het voorbeeldteam
titelbladtitel als boodschap, team, datum, versieEigen stroom, eigen sla: de klimaatmodule van Habitat in een testweek (versie 1.0)
samenvattingeen halve bladzijde: doel, aanpak, belangrijkste getallen, besluitzie hieronder
inleidingprobleem, doel, afbakening, spooralleen de kweekruimte, niet de woonmodule; spoor B
programma van eisende eisen per groep, met herkomst; de volledige tabel in een bijlage54 eisen, 47 moet
ontwerp per deelsysteemberekening, keuze en schema, per eigenaarenergiebudget, waterkringloop, warmtemodel, licht, voeding
integratieN²-diagram, interfacetabel, de problemen die je vond18 interfaces, 6 problemen
besturingversies, blokschema, toestandsdiagram; de code in een bijlageklimaat.ino versie 5
testentestplan, storingstests, testweek, testrapport43 van 47 moet-eisen gehaald
besluit en aanbevelingenantwoord op het doel; wat beter moet, gekoppeld aan eisenL1 en H2: twee voorstellen
bronnenalles wat je gebruikte, zo dat een ander het terugvindtPVGIS, datasheets, hoofdstukken
bijlagencode, logbestanden, tekeningen, ijkverslagenklimaat.ino, zeven logbestanden

De samenvatting van het voorbeeldteam (één alinea, alle getallen erin):

De klimaat- en energiemodule van Habitat moet 48 kroppen sla telen op eigen zonnestroom, met een geregeld klimaat en een logger. We stelden 54 eisen op, waarvan 47 moet-eisen, rekenden de energie-, water- en warmtebalans na, voegden vijf versies van de besturing samen tot klimaat.ino versie 5 en lieten de module een week alleen draaien in een simulatie met hetzelfde programma (8-14 maart 2021). 43 moet-eisen zijn gehaald, één voorlopig (de zomer komt nog) en één kan pas na vijf weken getoetst worden. Twee zijn niet gehaald: op drie grijze dagen bleef de lichtsom onder 11,0 mol/(m²·dag), omdat het energiebeheer de lampen afknijpt onder 40 % laadtoestand, terwijl op de zonnige dagen 12,4 kWh zonnestroom ongebruikt bleef; en zondag steeg de pH boven 6,5 zonder dat iemand de waarschuwing zag. We stellen een grotere buffer of stroom van het station voor, en meldingen die een telefoon bereiken.

Zinnen die iets bewijzen. Een rapport overtuigt met getallen, eenheden en criteria:

zwaksterkwaarom
De batterij is groot genoeg.In december leveren de batterijen 's nachts 1,84 kWh van de 2,46 kWh die bruikbaar is (75 %).getal, eenheid en de grens ernaast
De test was geslaagd.Met de vlotter omhoog volgde na 8 s een alarm en stopte de pomp (eis W3: binnen 10 s).wat, wanneer en tegen welk criterium
We denken dat de sensor slecht hing.Boven de convector las de SHT31 0,5 °C hoger dan de referentie bij de planten; op de nieuwe plaats verdween het verschil.een meting in plaats van een mening
Zie grafiek.Figuur 7 toont dat de laadtoestand dinsdag onder 40 % bleef: de lampen kregen alleen zonne-overschot.de tekst zegt wat de figuur bewijst
Alles werkte goed.43 van de 47 moet-eisen zijn gehaald; L1 en H2 niet (zie 6.3).eerlijk, ook over wat niet lukte

Bronnen. Vermeld alles wat je gebruikte, zo dat een ander het terugvindt: wie, wat, welke versie, wanneer geraadpleegd (hoofdstuk 2). Bijvoorbeeld: Europese Commissie, Joint Research Centre. PVGIS, versie 5.3. Brussel, 60° zuid, 1,40 kWp. Documentatie gecontroleerd op 30 september 2026; de getallen zijn rekenwaarden uit het cursusmodel. Voor een datasheet: de fabrikant, het onderdeel en de revisie. Voor dit boek: StemExpert Intermediate, hoofdstuk 20: Zonne-energie dimensioneren.

Een rapport vertelt hoe hard we gewerkt hebben

Een rapport vertelt wat er is, waarom, en hoe goed het werkt. Het logboek bewaart het verhaal van het werk; het rapport bewaart het resultaat. Wat niet lukte, hoort er wel in: met de oorzaak en een voorstel.

Uitleg · 40.25

Fase 5 · de verdediging voor een jury

25/28

De verdediging duurt twintig minuten: tien minuten presenteren, tien minuten vragen. De jury (de leraar, een collega, iemand van buiten de school) kent het programma van eisen en heeft het rapport gelezen. Ze wil drie dingen weten: begrijpen jullie je eigen ontwerp, zijn jullie keuzes onderbouwd, en zijn jullie eerlijk over de grenzen?

  • Het storyboard legt de dia's vast voor je ze maakt: één boodschap per dia, als titel geschreven ('De batterijen dekken de nacht, niet de grijze week'), met één figuur die ze bewijst.
  • Iedereen spreekt, elke eigenaar over zijn deelsysteem. De integrator opent en sluit.
  • De demo toont de module aan het werk: een hand op de SHT31 en de ventilatoren slaan aan, de vlotter omhoog en de statusled knippert snel, de logger die live een regel schrijft. Houd een plan B klaar (een filmpje, een logbestand).

Vragen die een jury stelt, en wat een sterk antwoord bevat:

vraag van de jurywaar het echt over gaatwat een sterk antwoord bevat
Waarom twee batterijen en geen drie?dimensioneren en afwegende nacht in december (1,84 kWh van 2,46); een derde zou de afgeknepen zonnestroom van een zonnige dag bewaren voor een grijze, maar kost geld en CO₂ (hoofdstuk 38)
Hoe weet je dat je simulatie klopt?model tegenover werkelijkheidde waarden komen uit hoofdstuk 19, 20 en 31; C++ en Python geven dezelfde week; valideren doe je met echte logbestanden (E36)
Wat gebeurt er als de SHT31 uitvalt?fail-safe ontwerpalarm na 30 s, noodprogramma met de gemiddelde inschakelduur (eis B2, B3), getest op donderdag
Waarom aan/uit en geen PID?regeltechniekde convector kan alleen aan of uit; met 1 °C hysterese hoogstens 6 starts per uur; PID past bij een traploze verwarming (E39)
Kan de module zonder het station?systeemgrensenergie: van februari tot november wel, in december en januari niet; warmte: nee; water: het kasdak vangt 4,0 m³ tegenover 2,2 m³ nodig
Wat hebben jullie niet getest?eerlijkheidde zomer (K3), de algen (W5), de opbrengst van een jaar (P2); en de testweek was een simulatie
Wie had zondag de pH moeten zien?eigenaarschapde eigenaar van water en voeding; het ontwerp stuurde de melding naar niemand: voorstel in de aanbevelingen
Een vraag die je niet kan beantwoorden

Zeg wat je wel weet, wat je niet weet, en hoe je het zou uitzoeken. 'Dat hebben we niet getest; de logger zou het tonen als we de sensorkast een week in de zon hangen' is een sterk antwoord. Raden is dat niet.

dia 1 · 0:00de vraag: versvoedsel in eenstationdia 2 · 1:00de module in éénbeeld: hetsysteemschemadia 3 · 2:0054 eisen, 47 moet: delatdia 4 · 3:00de drie balansen:energie, water,warmtedia 5 · 5:00één programma, vijfmodi, een loggerdia 6 · 6:30de testweek: grafieken testrapportdia 7 · 8:30wat niet lukte, enwaaromdia 8 · 9:30versie 2, en eenvraag aan de jurytien minuten presenteren, daarna tien minuten vragen van de jury; de demo tijdens dia 5 of 6
Acht dia's, tien minuten: de balansen en de testweek krijgen de meeste tijd.
De verdediging: één figuur per boodschap, en een jury die vragen stelt over de getallen.
De verdediging: één figuur per boodschap, en een jury die vragen stelt over de getallen.
Naslag · 40.26

Beoordeling: eindrubric, peer- en zelfevaluatie

26/28

De jury en de leraar beoordelen het project met de eindrubric; het team gebruikt dezelfde rubric voor de zelfevaluatie (werkboek). Per criterium kies je het niveau dat het best past, met bewijs: een berekening, een logbestand, een regel in het logboek. De eindscore is de som van niveau × gewicht, gedeeld door 4. Het voorbeeldteam haalde niveau 3 op alles en niveau 4 voor testen en data-analyse: 80 op 100.

Daarnaast beoordeelt elk teamlid zichzelf en de anderen op vijf punten (peer-evaluatie), van 1 (zelden) tot 4 (altijd). Grote verschillen tussen zelf- en peer-evaluatie bespreek je in een kort teamgesprek.

criteriumgewicht1 · begint2 · op weg3 · goed4 · uitstekend
programma van eisen en interfaces10 %eisen vaag, zonder toetsmeetbaar, maar herkomst of criterium ontbreekt vaakalle eisen meetbaar, met criterium, toets en hoofdstuk; interfacetabel volledigook: botsende eisen opgemerkt en beslist
dimensionering15 %berekeningen ontbrekenberekeningen met fouten in eenheden of aannamesenergie, water, warmte, licht en voeding juist nagerekend, met herkomstook: gevoeligheid getoond (wat als het grijs is, wat als het vriest)
bouw en veiligheid10 %niet volgens het schemawerkt, maar pas na ernstige herstellingen gekeurdvolgens het schema, zekering per tak, sterpunt, in één keer gekeurdook: nette bekabeling, alles gemeten en genoteerd
besturing en code15 %versie 5 draait nietdraait, maar niet alle situaties getestdraait, alle naspeeltests en storingstests in ordeook: een eigen uitbreiding, getest en uitgelegd
testen en data-analyse20 %geen testplantestplan, maar criteria achteraf of analyse met de handtestplan vooraf, storingstests, testweek met een script getoetstook: niet-gehaalde eisen tot op de oorzaak ontleed
technisch rapport15 %onvolledigalle delen, maar zonder getallen of bronnenvolledig, met getallen, figuren die in de tekst uitgelegd worden, bronnenook: kort, helder, klaar voor een volgend team
verdediging10 %geen presentatie of demopresentatie, maar vragen ontwekenstoryboard gevolgd, iedereen spreekt, vragen met getallen beantwoordook: eerlijk over grenzen, sterke demo met plan B
samenwerking en logboek5 %logboek leeglogboek onvollediglogboek elke les, eigenaars kennen elkaars interfacesook: conflicten opgelost en genoteerd

Peer- en zelfevaluatie

criterium1 · zelden4 · altijd
komt afspraken en deadlines nalevert te laat of nietop tijd, en meldt vooraf als het niet lukt
kwaliteit in het eigen deelsysteemberekeningen of bouw met foutenjuist, gemeten, gedocumenteerd
bewaakt de eigen interfacesverandert een pin of waarde zonder te meldenoverlegt met de andere eigenaar, past de tabel aan
helpt anderenwerkt alleenlegt uit, test mee, deelt wat hij kan
houdt het logboek mee bijnooitelke les: wie, wat, probleem, volgende stap
Uitleg · 40.27

Wat de module nog niet kan, en wat Expert toevoegt

27/28

De module werkt: ze teelt, regelt, beheert haar energie en houdt alles bij. Maar de testweek toonde ook haar grenzen. Ze reageert op wat er nu is, ze voorspelt niet; ze meldt, maar alleen aan wie in de module staat; ze vertrouwt op één sensor per grootheid; en haar gedrag is getest in een model dat nog niet op echte metingen geijkt is.

wat de module nog niet kangevolg (testweek of berekening)wat Expert toevoegt
een melding bereikt niemand buiten de modulede pH-waarschuwing van zondag werd pas maandag geziensensornetwerk en MQTT naar een centrale computer en een telefoon (E37)
aan/uit-regelingzaagtand van 1 °C, tot 6 starts per uurPID-regeling met een traploze verwarming (E39)
het energiebeheer reageert, maar voorspelt nietdinsdag lampen afgeknepen, woensdag ±4 kWh zonnestroom ongebruiktverbruik en zon voorspellen (E41, E43), opslag en het 48 V-net van het station (E19-E24, E27)
één temperatuursensorsensor los: blind verwarmensensorfusie en foutdetectie (E40), redundantie en FMEA (E46)
het model is niet geijkt op metingende testweek is een simulatieparameters schatten uit logbestanden (E17, E36), de digitale tweeling (E49)
geen noodstop in hardwarehangt de Mega, dan beslist alleen de waakhondnoodstoplogica met poorten (E23)
CO₂ niet gemetende klep gaat open op tijd, niet op concentratieeen CO₂-sensor en minuutgemiddelden (E6, E14)
de MPPT is een zwarte doosje weet niet waarom hij afknijptbuck- en boostomzetters en MPPT zelf (E24)

In Expert bouw je het brein van het station: een centrale computer die de meetkas (laag 1) en de klimaatmodule (laag 2) verbindt met de woonmodule, metingen verzamelt, een digitale tweeling meedraait (een simulatie zoals de testweek van dit hoofdstuk, maar geijkt op de echte module) en setpoints terugstuurt. De Mega blijft de module regelen, met versie 5 als basis; het brein zegt haar wat het beste setpoint is. Het ontwerpproces wordt het V-model in het groot, met een eisenboom en een FMEA (E45, E46). Het echte station EDEN ISS in Antarctica werkte zo: een serre die zichzelf regelde, bewaakt door een controlecentrum op afstand (hoofdstuk 36).

klimaatmodule (laag 2)Arduino Mega 2560,klimaat.ino versie 5,logger, alarmenmeetkas (laag 1)Arduino Uno, watergeven, dakraamhet brein van het station (laag 3): een centrale computerdigitale tweelingwarmte, energie, water alsmodel (E17, E36, E49)PID-regelingin plaats van aan/uit (E39)energiebeheerMPPT, 48 V-net, opslag(E24, E27)sensornetwerkMQTT, foutdetectie (E37,E40)voorspellenverbruik en zon van morgen(E41, E43)betrouwbaareisenboom, FMEA, noodstop(E23, E45, E46)metingensetpointsmetingen
De Mega's blijven regelen; het brein kijkt mee, rekent vooruit en stuurt setpoints terug.
Het geheel · 40.28

De tweede laag is af

28/28

De klimaat- en energiemodule is de tweede laag van Habitat. Elk deel van Intermediate leverde er iets aan, en in dit hoofdstuk kwam alles samen: meten met een onzekerheid (I1), modellen met hun geldigheidsgebied (I2), krachten op dak en vloer (I3), de chemie van de voedingsoplossing en de batterij (I4), de drie balansen (I5), de elektronica van sensor tot MOSFET (I6), Python en C++ (I7), regelen en toestanden (I8), de plant zelf (I9), en ontwerpen met data (I10).

Waar het vandaan komt. De meetkas van Fundamental (F33) was hetzelfde project in het klein: 36 eisen, één programma met tellers, een testweek met een laptop. Nu: 54 eisen, vijf versies samengevoegd, een logger en een analyse in Python, en een verdediging voor een jury.

Waar het naartoe gaat. Expert neemt de module over als bouwsteen van het brein van het station. Het warmtemodel met twee knopen wordt de kern van de digitale tweeling (E17), de aan/uit-regeling een PID-regeling (E39), het energiebeheer een voorspellend beheer met het 48 V-net van het station (E24, E41), de meldingen een sensornetwerk (E37), en het programma van eisen een eisenboom in het V-model (E45). Het integratieproject van Expert (E49) volgt dezelfde fasen, voor het hele station.

I1 · onderzoeken (1-3)meetfouten, proefopzet,ijklijnenI2 · wiskunde (4-6)kostenmodel, algengroei,paneelhoekI3 · mechanica (7-11)kasdak, dakmotor, pomp,vloer, drukI4 · chemie (12-17)voeding, EC, CO₂, pH,batterij, filamentI5 · energie en warmte (18-20)buffer, U-waarden,panelen, batterijI6 · elektronica (21-26)5 V-rail, sensoren,MOSFET, RC, PWM, motorI7 · programmeren (27-30)Python, CSV, C++, loggerI8 · regelen, robotica (31-33)hysterese, modi,inspectierobotI9 · leven (34-36)temperatuuroptimum,compost, hydroponieI10 · ontwerpen, data (37-39)regelkast, levenscyclus,beslisboomde klimaatmodulehoofdstuk 40
Tien delen, negenendertig hoofdstukken, één module.

Het eerste integratieproject: dezelfde fasen, in het klein.

Het verslag en de bronvermelding van het technisch rapport.

Het werkpunt van de pomp en de druksensor in het reservoir.

De EC van de voedingsoplossing en de temperatuurcompensatie.

De pH, de tweepuntsijking en het bijsturen met pH-min.

De LiFePO4-batterijen en de coulombteller.

Het warmteverlies van 20,2 W/K.

Panelen, batterijen en energiebeheer: het budget dat hier herrekend is.

Dimmen met PWM en het daglicht in µmol.

Versie 1, pinnen.h en taken met millis().

De logger, I²C en de klok van versie 2.

Hysterese, het warmtemodel met twee knopen en het noodprogramma.

De modi en het dak als toestandsmachines: het kader van versie 5.

Het NFT-rek, de lichtsom en de opbrengst.

De voetafdruk van de module en de keuze van de batterijen.

De extra pompbeurt uit de beslisboom, en grafieken die niet misleiden.

Het warmtemodel van het station: de kern van de digitale tweeling.

Meldingen die iemand bereiken: een sensornetwerk met MQTT.

Van aan/uit naar PID.

Het verbruik en de zon van morgen voorspellen.

Het V-model en de eisenboom voor het hele station.

Het integratieproject van Expert: het brein van het station.

HabitatDe tweede laag van Habitat is af. Nieuw in het stationsdossier: het programma van eisen van de module (54 eisen, 47 moet), 18 interfaces, klimaat.ino versie 5 met een logformaat van 17 kolommen, het testrapport van een testweek, en de eindbalans: met dimmen ±540 kWh per jaar (tekort alleen in december en januari), ±2,2 m³ water per jaar (het kasdak vangt er 4,0), en warmte van het station (±2 kWh per maartdag).
Samenvatting

In het kort

Begrippen

Wat je nu kent

integrator
Het teamlid dat bewaakt dat de deelsystemen op elkaar passen: programma van eisen, interfaces, planning en testrapport.
interfacetabel
Lijst van alle plaatsen waar twee deelsystemen elkaar raken, met per interface de afspraak (waarde, eenheid, pin, adres), de eigenaar en de test.
N²-diagram
Vierkante tabel met de deelsystemen op de diagonaal; het vakje in rij A en kolom B zegt wat A aan B levert.
deeltest
Test van één onderdeel of deelsysteem apart, zodra het klaar is (een sensor, een tak, de pomp).
integratietest
Test van de samenwerking tussen deelsystemen: werkt de interface zoals afgesproken?
storingstest
Test waarbij je bewust een fout veroorzaakt (sensor los, vlotter omhoog, stroom eraf) om na te gaan of het systeem zoals ontworpen reageert.
testweek
Systeemtest waarin het systeem een week alleen draait, terwijl de logger alles bijhoudt.
lichtsom
Het aantal mol lichtdeeltjes (PAR) dat op één dag op een vierkante meter valt, daglicht en lampen samen: DLI, in mol/(m²·dag).
afknijpen
Wat een laadregelaar doet als de batterij vol is: hij neemt minder zonnestroom af dan de panelen kunnen leveren.
één eigenaar per uitgang
Ontwerpregel: één enkele taak in het programma beslist over een pin; andere taken vragen, ze schakelen niet zelf.
technisch rapport
Verslag van een ontwerp: van eisen over berekeningen en keuzes tot tests en besluit, zo dat een ander het kan nagaan en verderzetten.
verdediging
Presentatie van een ontwerp voor een jury, gevolgd door vragen, waarin je je keuzes met getallen onderbouwt.
Aan de slag in het werkboek28 opdrachten, van oefenen tot uitdagen