← Back to CoursesStemExpert
StemExpert
Intermediate · Oplossingen · 30. Datalogging en communicatie
StemExpert · Brecht Corbeel · schoolium.me
StemExpert
I30. Datalogging en communicatie — oplossingen
IIntermediate · deel I7 · Programmeren

Oplossingen · hoofdstuk 30Datalogging en communicatie

Een logboek dat zichzelf schrijft: van bits op een draad tot een grafiek in Python

Uitgewerkte oplossingen bij de 16 opdrachten van het werkboek. Voor de leerkracht, en voor wie zichzelf wil verbeteren nadat hij het eerst zelf probeerde.

5× oefenen7× toepassen4× uitdagen± 441 min
Elke minuut een regel op de kaart: het logboek van de klimaatmodule.
Elke minuut een regel op de kaart: het logboek van de klimaatmodule.
Voor de leerkrachtDeze pagina bevat de antwoorden. Druk het werkboek af zonder deze pagina.
Oefenen

Oefenen

één stap, direct toepassen
30.1

Een teken van de draad lezen

Oefenen3Analyseren12 min
Een logicanalysator toont de TX-lijn van de Mega op 9600 baud (8N1). Elke bit duurt 104 µs.
TX025050075010001250t (µs)
Eén teken: vóór en na het teken is de lijn in rust.
  1. a
    Waar begint het teken? Schrijf de acht databits in de volgorde waarin ze verstuurd worden.
    Het teken begint waar de lijn voor het eerst laag wordt (startbit, bij 208 µs). Daarna: 1, 1, 0, 1, 0, 0, 1, 0 (b0 tot b7), en een hoge stopbit.
  2. b
    Zet ze om naar een byte (b7 … b0), in hexadecimaal en decimaal. Welk teken is het (ASCII)?
    Van b7 naar b0: 0100 1011 = 0x4B = 75: de letter 'K'.
  3. c
    Teken hoe het teken 'A' (65) eruitziet, met startbit en stopbit.
    65 = 0x41 = 0100 0001. Na de rust: startbit 0, dan b0 tot b7 = 1, 0, 0, 0, 0, 0, 1, 0, en de stopbit 1.
30.2

Tekens per seconde

Oefenen3Rekenen12 min
Een seriële verbinding gebruikt 8N1: 10 bits per teken.
  1. a
    Hoeveel tekens per seconde bij 9600, 19 200 en 115 200 baud?
    960, 1920 en 11 520 tekens per seconde.
  2. b
    Het programma serieel_csv.ino stuurt om de 2 s een regel van ongeveer 20 tekens. Welk deel van de tijd is de lijn bezig bij 9600 baud?
    20 tekens duren per 2 s: ongeveer 1 %.
  3. c
    Iemand wil om de 10 ms een regel van 50 tekens sturen. Welke baudrates kunnen dat?
    100 regels per seconde × 50 tekens = 5000 tekens per seconde = 50 000 baud. 9600 en 19 200 zijn te traag; 57 600 en 115 200 volstaan.
30.3

De scanner lezen

Oefenen3Begrijpen12 min
Drie leerlingen draaien de I²C-scanner op hun opstelling. Ze hebben een SHT31, een DS3231-moduletje en een INA226 aangesloten.
  1. a
    Leerling A ziet: 0x40, 0x44, 0x57, 0x68. Welke chip is welk adres? Waarom vier adressen voor drie moduletjes?
    0x40 INA226 (A0 en A1 aan GND), 0x44 SHT31, 0x68 DS3231; 0x57 is het geheugenchipje dat op het klokmoduletje zit.
  2. b
    Leerling B ziet: 0 apparaten gevonden. Noem drie mogelijke oorzaken.
    SDA en SCL verwisseld; geen gemeenschappelijke GND; de moduletjes krijgen geen voeding; een losse draad; bij een Uno de verkeerde pinnen (A4/A5).
  3. c
    Leerling C wil een tweede SHT31 toevoegen (in de meetkas). Kan dat op dezelfde bus? Hoe?
    Ja: de SHT31 heeft twee adressen. Verbind de pin ADDR van de tweede met VDD, dan antwoordt hij op 0x45. Een derde zou niet gaan zonder een I²C-multiplexer.
30.4

BCD lezen

Oefenen4Rekenen15 min
De registers 0x00 tot 0x06 van een DS3231 geven, in hexadecimaal: 07 59 23 07 18 10 26. Register 0x03 is de dag van de week (RTClib: maandag = 1).
  1. a
    Welke datum en tijd staan er? Welke dag van de week?
    Zondag 18 oktober 2026, 23:59:07.
  2. b
    Schrijf 0x59 binair. Waarom is BCD handig voor een klok, en waarom wat verspillend?
    0x59 = 0101 1001: het cijfer 5 en het cijfer 9 elk in 4 bits. Handig: je leest de cijfers zo af en toont ze op een display zonder te rekenen. Verspillend: met 8 bits kan je 256 waarden maken, BCD gebruikt er maar 100 (00 tot 99).
  3. c
    Welke bytes schrijf je naar de registers 0x00 tot 0x02 voor 14:05:00?
    0x00 (seconden), 0x05 (minuten), 0x14 (uren, 24-uursmodus).
30.5

Wat is er mis met deze regels?

Oefenen4Begrijpen15 min
De kop van een logbestand is tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh,licht_lx,batterij_V. Beoordeel deze zes regels.
  1. a
    Welke regel is in orde, en wat is er mis met de andere? Hoe zou je ze voorkomen in de logger?
    • 08:00: in orde.
    • 08:01: decimale komma's: de regel heeft negen velden in plaats van zeven. Voorkomen: Serial.print zet altijd een punt; niet via een rekenblad met Belgische instellingen gaan.
    • 08:02: datum in dd/mm/jjjj: sorteert verkeerd en is dubbelzinnig (12 oktober of 10 december?). Voorkomen: jjjj-mm-dd uu:mm.
    • 08:03: 0 °C en 0 % in een kas zijn meetfouten die als echte waarden meetellen. Voorkomen: bij een mislukte meting een lege cel.
    • 08:04: nan: de meting mislukte, maar Serial.print(NAN) schrijft 'nan'. Python leest dat met float() als een getal (NaN), wat berekeningen stilletjes bederft. Voorkomen: eerst testen met isnan() en dan leeg laten.
    • 08:05: een halve regel (stroomonderbreking of volle kaart). Voorkomen kan niet altijd; het leesprogramma moet regels met te weinig velden overslaan.
Toepassen

Toepassen

meerdere stappen, in een context
30.6

Een SHT31 narekenen

Toepassen4Rekenen20 min
De SHT31 stuurt zes bytes. Twee metingen: 64 29 59 9C ED F5 en 64 3C 2B 9C 6A 18. Gebruik de formules en de CRC uit het handboek.
  1. a
    Reken beide metingen om naar °C en % (zonder de CRC te controleren).
    0x6429 = 25 641: °C; 0x9CED = 40 173: %. Tweede: 0x643C = 25 660 geeft 23,52 °C; 0x9C6A = 40 042 geeft 61,1 %.
  2. b
    Schrijf in Python een functie crc8(data) en test ze met het voorbeeld uit de datasheet (0xBE 0xEF geeft 0x92). Welke meting is beschadigd?

    Getest:

    # sht31_bytes.py - zes bytes van de SHT31 omrekenen en controleren
    def crc8(data):
        """CRC-8 zoals in de datasheet: veelterm 0x31, beginwaarde 0xFF."""
        crc = 0xFF
        for b in data:
            crc ^= b
            for _ in range(8):
                if crc & 0x80:
                    crc = ((crc << 1) ^ 0x31) & 0xFF
                else:
                    crc = (crc << 1) & 0xFF
        return crc
    
    
    print("test:", hex(crc8([0xBE, 0xEF])), "(datasheet: 0x92)")
    for b in ([0x64, 0x29, 0x59, 0x9C, 0xED, 0xF5], [0x64, 0x3C, 0x2B, 0x9C, 0x6A, 0x18]):
        ruw_t = b[0] * 256 + b[1]
        ruw_rv = b[3] * 256 + b[4]
        goed = crc8(b[0:2]) == b[2] and crc8(b[3:5]) == b[5]
        print(f"T = {-45 + 175 * ruw_t / 65535:.2f} °C, RV = {100 * ruw_rv / 65535:.1f} %, CRC {'in orde' if goed else 'FOUT'}"
              f" (berekend {crc8(b[0:2]):02X} en {crc8(b[3:5]):02X})")
    test: 0x92 (datasheet: 0x92)
    T = 23.47 °C, RV = 61.3 %, CRC in orde (berekend 59 en F5)
    T = 23.52 °C, RV = 61.1 %, CRC FOUT (berekend EF en 18)

    In de tweede meting klopt de CRC van de temperatuur niet: de sensor stuurde 0x2B, maar uit 0x64 0x3C volgt 0xEF. Er is onderweg een bit omgevallen (0x38 werd 0x3C).

  3. c
    Waarom gooit de logger een beschadigde meting weg in plaats van ze te gebruiken? Het verschil met de eerste meting is maar 0,05 °C.
    Je weet niet wélk bit omviel. Hier was het een klein bit en scheelde het 0,05 °C, maar het had evengoed het hoogste bit kunnen zijn (±85 °C verschil). Een meting die je niet kan vertrouwen, is erger dan geen meting: een lege cel is eerlijk.
30.7

Pull-ups voor een langere kabel

Toepassen5Rekenen20 min
De sensorkast moet 5 m van de Mega komen. De kabel heeft 100 pF per meter; de chips en de Mega samen 50 pF. Op de bus zitten de 10 kΩ van de Mega, en het SHT31-bordje heeft zelf ook 10 kΩ. Grenzen: stijgtijd 0,85 · R · C hoogstens 1 µs, R minstens 1,53 kΩ.
  1. a
    Bereken C en de stijgtijd met de twee pull-ups die er al zijn.
    . 10 ∥ 10 kΩ = 5 kΩ: : te traag.
  2. b
    Tussen welke grenzen moet de totale pull-up liggen? Kies een extra weerstand uit de E12-reeks (1,0 - 1,2 - 1,5 - 1,8 - 2,2 - 2,7 - 3,3 - 3,9 - 4,7 kΩ).
    Hoogstens , minstens 1,53 kΩ. Met 3,3 kΩ extra: 5 ∥ 3,3 = 1,99 kΩ, : net goed. (2,7 kΩ geeft 1,75 kΩ en 0,82 µs: ook goed, met meer marge.)
  3. c
    En bij 10 m kabel?
    : meer dan de 400 pF die de norm toelaat, en R zou kleiner moeten zijn dan , onder de grens van 1,53 kΩ. Het lukt niet meer met pull-ups: gebruik een I²C-busversterker, of zet de sensor dichter bij en breng de gegevens anders over (bv. seriëel, of een tweede microcontroller).
30.8

Seriële regels die niet kloppen

Toepassen5Programmeren25 min
Over de seriële poort komen soms rare regels binnen: een half bericht na het openen van de poort, een melding, 'nan', een regel met een decimale komma. lees_serieel.py mag daar niet van crashen.
  1. a
    Schrijf een functie verwerk(regel, kop) die een woordenboek met getallen teruggeeft (None voor een lege cel of nan), of None als de regel onbruikbaar is.
    # verwerk.py - een regel van de seriële poort omzetten, zonder dat een rare regel het programma laat crashen
    KOP = ["tijd_s", "temperatuur_C", "vocht_pct", "licht_ruw"]
    
    
    def verwerk(regel, kop=KOP):
        """Een woordenboek met getallen (None voor een lege cel), of None als de regel niet bruikbaar is."""
        regel = regel.strip()
        if regel == "" or regel.startswith("#"):
            return None
        velden = regel.split(",")
        if len(velden) != len(kop):
            return None
        uit = {}
        for naam, tekst in zip(kop, velden):
            if tekst == "" or tekst.lower() == "nan":
                uit[naam] = None
                continue
            try:
                uit[naam] = float(tekst)
            except ValueError:                       # bv. '482x' of '23 5'
                return None
        return uit
    
    
    testregels = ["2,23.50,64.0,477", "4,23,61,63.8,478", "# SD-kaart klaar", "6,nan,63.6,479",
                  "8,,,480", "10,23.9", "12,24.01,63.0,482x", ""]
    for r in testregels:
        print(f"{r!r:24} -> {verwerk(r)}")
  2. b
    Test ze met deze regels: 2,23.50,64.0,477 · 4,23,61,63.8,478 · # SD-kaart klaar · 6,nan,63.6,479 · 8,,,480 · 10,23.9 · 12,24.01,63.0,482x · een lege regel.

    Uitvoer:

    '2,23.50,64.0,477'       -> {'tijd_s': 2.0, 'temperatuur_C': 23.5, 'vocht_pct': 64.0, 'licht_ruw': 477.0}
    '4,23,61,63.8,478'       -> None
    '# SD-kaart klaar'       -> None
    '6,nan,63.6,479'         -> {'tijd_s': 6.0, 'temperatuur_C': None, 'vocht_pct': 63.6, 'licht_ruw': 479.0}
    '8,,,480'                -> {'tijd_s': 8.0, 'temperatuur_C': None, 'vocht_pct': None, 'licht_ruw': 480.0}
    '10,23.9'                -> None
    '12,24.01,63.0,482x'     -> None
    ''                       -> None

    try/except vangt de ValueError van float() op: een regel met rommel wordt overgeslagen in plaats van het programma te stoppen.

30.9

Vind de fouten in de eerste logger

Toepassen5Programmeren25 min
Een leerling schrijft een eerste logger. Hij compileert zonder klagen en de seriële monitor toont iets, maar na een dag staat er niets op de kaart.
// logger_fout.ino - een eerste poging tot datalogger (er zitten vier fouten in)
#include <Wire.h>
#include <SD.h>

File bestand;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  SD.begin(53);
  bestand = SD.open("LOG/2026-10-12.CSV", FILE_WRITE);
  bestand.println("tijd_ms,temperatuur_C");
}

void loop() {
  Wire.beginTransmission(0x44);
  Wire.write(0x24);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(20);
  Wire.requestFrom(0x44, 6);
  unsigned int ruw = (Wire.read() << 8) | Wire.read();
  float t = -45 + 175.0 * ruw / 65535;
  char regel[40];
  sprintf(regel, "%lu,%.1f", millis(), t);
  bestand.println(regel);
  Serial.println(regel);
  delay(60000);
}
  1. a
    Waarom staat er niets op de kaart? Er zijn twee redenen in setup().
    (1) 2026-10-12.CSV is geen 8.3-naam (tien tekens voor de punt), en (2) de map LOG bestaat niet: SD.open mislukt en bestand is ongeldig. Omdat niemand de terugkeerwaarde controleert, schrijft println in het niets. Zelfs als het bestand wel openging: zonder flush() of close() komt de nieuwe lengte nooit in de map, en na het uittrekken van de kaart is het bestand leeg. In de simulatie: 0 bestanden op de kaart.
  2. b
    Wat is er mis met (Wire.read() << 8) | Wire.read()?
    C++ legt niet vast welke van de twee Wire.read()'s eerst uitgevoerd wordt: de compiler mag de lage byte eerst lezen, en dan zijn hoog en laag verwisseld. Lees ze in twee aparte regels (byte hoog = Wire.read(); byte laag = Wire.read();).
  3. c
    De seriële monitor toont bij de temperatuur een vraagteken. Waarom?
    sprintf op de Arduino kan standaard geen kommagetallen (%f): het schrijft '?'. Schrijf het getal met print(t, 1) of zet het om met dtostrf.
  4. d
    Noem nog twee zwakke punten van dit programma.
    Geen enkele controle: niet of de SHT31 antwoordde (Wire.read() geeft dan −1, de 'temperatuur' 130 °C), niet of de CRC klopt, niet of de kaart er is. delay(60000) legt alles een minuut stil, en millis() als tijdstip verliest alles bij een reset: gebruik de RTC.
30.10

Van minuten naar blokken van drie uur

Toepassen6Programmeren30 min
De programma's van hoofdstuk 28 werken met blokken van drie uur. Maak uit de testweek (logboek.py) een bestand in dat formaat: tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh, het tijdstip het begin van het blok, temperatuur met één decimaal, vocht als geheel getal, energie in hele Wh. Een blok krijgt alleen een temperatuur als minstens de helft van de 180 minuten geldig is.
  1. a
    Schrijf het programma.
    # per_blok.py - de minuten van de logger samenvatten in blokken van 3 uur (het formaat van hoofdstuk 28)
    import csv
    
    from logboek import lees_week, opschonen
    
    rijen = lees_week()
    opschonen(rijen)
    blokken = {}                                     # begin van het blok -> de regels van dat blok
    for r in rijen:
        t = r["tijd"]
        begin = t.replace(hour=t.hour - t.hour % 3, minute=0)
        if begin not in blokken:
            blokken[begin] = []
        blokken[begin].append(r)
    
    with open("klimaatmodule_oktober.csv", "w", newline="", encoding="utf-8") as bestand:
        schrijver = csv.writer(bestand)
        schrijver.writerow(["tijdstip", "temperatuur_C", "vocht_pct", "verbruik_Wh", "zon_Wh"])
        for begin in sorted(blokken):
            rs = blokken[begin]
            t = [r["T"] for r in rs if r["T"] is not None]
            rv = [r["RV"] for r in rs if r["RV"] is not None]
            genoeg = len(t) >= 90                    # minstens de helft van de 180 minuten geldig
            rij = [begin.strftime("%Y-%m-%d %H:%M"),
                   f"{sum(t) / len(t):.1f}" if genoeg else "",
                   f"{sum(rv) / len(rv):.0f}" if genoeg else "",
                   round(sum(r["verbruik"] for r in rs)),
                   round(sum(r["zon"] for r in rs))]
            schrijver.writerow(rij)
            if begin.day == 14:                      # woensdag tonen
                print(rij, len(rs), "minuten")
    print("blokken:", len(blokken))

    Uitvoer:

    ['2026-10-14 00:00', '18.0', '84', 22, 0] 180 minuten
    ['2026-10-14 03:00', '18.0', '84', 22, 0] 180 minuten
    ['2026-10-14 06:00', '19.4', '82', 545, 78] 180 minuten
    ['2026-10-14 09:00', '19.4', '82', 272, 464] 180 minuten
    ['2026-10-14 12:00', '20.3', '80', 219, 547] 180 minuten
    ['2026-10-14 15:00', '20.3', '80', 475, 183] 180 minuten
    ['2026-10-14 18:00', '19.4', '82', 570, 0] 180 minuten
    ['2026-10-14 21:00', '18.0', '84', 22, 0] 180 minuten
    blokken: 56
  2. b
    Bekijk de blokken van woensdag. Waarom is het blok van 21 uur maar 22 Wh, terwijl het op heldere dagen rond de 200 Wh ligt?
    Om 20:51 gingen de lampen uit door het energiebeheer (laadtoestand onder 40 %); van 21 tot 22 uur branden ze normaal nog. Het blok bevat dan alleen de basis: 3,5 W + 2 W ventilatie + 20 minuten pomp, ongeveer 22 Wh. Precies de 22 Wh die je 's nachts ook in hoofdstuk 28 zag.
  3. c
    Waarom de regel 'minstens de helft geldig'? Wat had je gekregen zonder die regel als de sensor een heel blok los had gezeten?
    Zonder regel deelt Python door len(t) = 0 en stopt met een ZeroDivisionError; met een halve regel zou een gemiddelde van twee minuten er even betrouwbaar uitzien als een van 180. Met de regel blijft zo'n blok leeg, net als woensdagmiddag in de week van hoofdstuk 28.
30.11

Uurgemiddelden van één dag

Toepassen5Programmeren20 min
Gebruik logboek.py. Je wil voor woensdag 14 oktober de gemiddelde temperatuur per uur, met het aantal geldige minuten erbij.
  1. a
    Schrijf het programma. Toon de uren 10 tot 14.
    # per_uur.py - de temperatuur van woensdag 14 oktober per uur
    from logboek import lees_week, opschonen
    
    rijen = lees_week(14, 14)                        # alleen woensdag
    opschonen(rijen)
    uren = {}                                        # uur -> geldige temperaturen
    for r in rijen:
        if r["T"] is not None:
            uur = r["tijd"].hour
            if uur not in uren:
                uren[uur] = []
            uren[uur].append(r["T"])
    for uur in range(10, 15):
        t = uren[uur]
        print(f"{uur:02d}:00  {sum(t) / len(t):5.2f} °C  ({len(t)} minuten)")

    Uitvoer:

    10:00  19.41 °C  (60 minuten)
    11:00  19.76 °C  (48 minuten)
    12:00  20.07 °C  (60 minuten)
    13:00  20.39 °C  (60 minuten)
    14:00  20.57 °C  (60 minuten)
  2. b
    Het uur van 11 heeft minder geldige minuten. Is het gemiddelde van dat uur daardoor fout?
    Niet fout, wel iets minder zeker: het is het gemiddelde van 48 in plaats van 60 minuten, en de 12 ontbrekende minuten liggen allemaal aan het eind van het uur. Als de temperatuur in die minuten sterk veranderde, mis je dat. Vermeld het aantal minuten erbij, dan kan de lezer oordelen.
30.12

Wat zie je in de grafiek?

Toepassen5Analyseren20 min
Twee grafieken uit de testweek: het vermogen op woensdagavond en de zonnestroom met het verbruik op maandagvoormiddag (zie het handboek). En de dagtabel van per_dag.py:
datum       T gem  T min  T max  geldig  verbruik   zon  saldo (kWh)
2026-10-12   20.0   17.7   24.7    1438      1.50  1.74  +0.23
2026-10-13   19.4   17.6   22.4    1438      1.67  1.71  +0.03
2026-10-14   19.1   17.6   21.0    1428      2.15  1.27  -0.88
2026-10-15   19.2   17.7   21.4    1440      1.46  2.43  +0.98
2026-10-16   19.7   17.7   23.7    1440      1.54  1.69  +0.14
2026-10-17   19.6   17.8   22.9    1440      1.61  1.66  +0.05
2026-10-18   19.2   17.7   21.2    1440      2.02  1.89  -0.13
8910111213140100200300400500600700800900uur (maandag 12 oktober)vermogen (W)batterij volzonverbruik
Maandag 12 oktober, van 8 tot 14 uur.
  1. a
    Waarom daalt de zonnestroom op maandag om 10:55 plots tot het verbruik, terwijl het de helderste dag van de week is?
    De batterij is vol. De laadregelaar knijpt de panelen af tot wat de module verbruikt; de INA226 meet alleen wat er echt stroomt.
  2. b
    Op welke dag denk je dat de laadtoestand het laagst was? Onderbouw met de tabel.
    Woensdagavond: de enige dag met een groot negatief saldo (−0,88 kWh), na een dag met weinig zon. Daardoor zakte de laadtoestand onder 40 % en gingen de lampen om 20:51 uit.
  3. c
    Een klasgenoot besluit: 'Op maandag leverde de zon maar 1,74 kWh, dus de panelen zijn te klein.' Wat is er mis met die redenering?
    zon_Wh is wat er geleverd werd, niet wat de panelen konden leveren. Op maandag was de batterij vanaf de voormiddag vol: de rest van de zon ging verloren. Om de panelen te beoordelen, moet je de dagen bekijken waarop de batterij niet vol raakte (zoals woensdag), of het licht (licht_lx) gebruiken om te schatten wat er beschikbaar was.
Uitdagen

Uitdagen

transfer, open problemen, leerlijnen combineren
30.13

Habitat: het logboek van de klimaatmodule

Uitdagen6Habitat50 min
Je ontwerpt het logboek voor een teeltseizoen van maart tot oktober (245 dagen). De module heeft een Mega met klimaat.ino versie 2, een microSD-kaart van 8 GB, en een 5 V-omvormer met een rendement van 83 %. Gebruik de getallen uit het handboek.
  1. a
    De beheerder wil elke 10 s een regel in plaats van elke minuut. Hoeveel ruimte kost een seizoen dan, en hoeveel bestanden? Is dat een probleem?
    Zes keer zoveel regels: per dag, over 245 dagen . Op 8 GB is dat ongeveer 1,3 %. Nog altijd 245 bestanden in de map LOG (één per dag). Geen probleem voor de kaart; wel worden de bestanden groot om in te lezen (8640 regels per dag), en de SHT31 meet om de 2 s, dus een regel per 10 s is een gemiddelde van maar 5 metingen.
  2. b
    Schat het eigen verbruik van de logger over een seizoen in Wh, en vergelijk met het basisverbruik van de module (230 Wh per dag).
    ±55 mW op 5 V, aan de 12 V-kant: per seizoen, tegenover basisverbruik: 0,7 %. (Met een schrijfinterval van 10 s schrijft de kaart vaker, maar de gemiddelde stroom blijft van dezelfde orde.)
  3. c
    Welke drie extra kolommen zou jij toevoegen voor de teelt (hoofdstuk 13, 15, 16)? Waar komen ze in de regel, en waarom daar?
    Bijvoorbeeld pH (hoofdstuk 15), EC_mS_cm (hoofdstuk 13, gecorrigeerd naar 25 °C) en soc_pct (hoofdstuk 16). Achteraan, na batterij_V: dan blijven alle bestaande programma's werken, ook die met kolomnummers.
  4. d
    Stel een plan op: hoe controleer je elke week of de logger nog werkt, en hoe bewaar je de gegevens veilig?
    Bijvoorbeeld: elke maandag de seriële monitor of het laatste bestand bekijken (loopt de tijd, zijn er lege cellen of gaten, is de spanning plausibel); elke maand de kaart uitlezen en de bestanden op twee plaatsen bewaren (computer en schijf of wolk); de klok controleren tegen de computer (±1 minuut per jaar is normaal); de knoopcel elk jaar nakijken. logboek.py geeft meteen het aantal regels, lege cellen en gaten.
Zo wordt dit beoordeeld
RekenwerkRegellengte, regels per dag, bytes per seizoen en aantal bestanden juist; eenheden.
EnergieStroom per onderdeel, rendement van de omvormer, Wh per seizoen, vergelijking in procent.
KolommenRelevante grootheden met eenheid in de naam, achteraan toegevoegd, met motivatie.
PlanConcreet en haalbaar: wat, wanneer, door wie; back-up en controle op gaten en lege cellen.
30.14

Ontwerp: de klok zetten vanaf de computer

Uitdagen6Ontwerpen40 min
logger.ino aanvaardt de opdracht T2026-10-11 20:00:00. Je wil een Python-programma dat de klok zet op de tijd van de computer, in wintertijd, en controleert of het gelukt is.
  1. a
    Waarom de tijd van de computer in wintertijd omzetten, en niet gewoon de tijd tonen die op je scherm staat?
    In België geeft de computer in de zomer UTC+2. De logger loopt het hele jaar op UTC+1, zodat er nooit een uur dubbel voorkomt of ontbreekt; zet je hem op de zomertijd van je scherm, dan loopt hij een uur voor tot hij in de winter weer 'juist' lijkt.
  2. b
    Schrijf klok_zetten.py met pyserial en datetime. Denk aan de herstart van de Mega bij het openen van de poort.

    Getest tegen de simulatie van logger.ino met een stilgevallen klok:

    # klok_zetten.py - de klok van de logger zetten op de tijd van de computer, in wintertijd (UTC+1)
    import time
    from datetime import datetime, timedelta, timezone
    
    import serial
    
    WINTERTIJD = timezone(timedelta(hours=1))        # het hele jaar: nooit een uur dubbel of kwijt
    poort = serial.Serial("COM3", 115200, timeout=2)
    time.sleep(2)                                    # het openen van de poort herstart de Mega: even wachten
    nu = datetime.now(WINTERTIJD)
    opdracht = nu.strftime("T%Y-%m-%d %H:%M:%S")
    poort.write((opdracht + "\n").encode("ascii"))
    print("verstuurd:", opdracht)
    for _ in range(6):                               # de logger antwoordt met een regel die met # begint
        antwoord = poort.readline().decode("utf-8", errors="replace").strip()
        if antwoord.startswith("#"):
            print("logger:", antwoord)
    poort.close()
    verstuurd: T2026-10-11 20:00:00
    logger: # de klok heeft stilgestaan: stuur T jjjj-mm-dd uu:mm:ss
    logger: # SD-kaart klaar
    logger: # klok gezet

    De Mega herstart bij het openen van de poort en stuurt eerst zijn meldingen; daarna komt het antwoord op de opdracht.

  3. c
    Wat gebeurt er in logger.ino met de minuut die bezig was toen de klok verzet werd? Waarom is dat een goede keuze?
    Die minuut wordt weggegooid (wisSommen en bezig = false): ze hoorde bij de oude tijd. Zou de logger ze bewaren, dan kwam er een regel met een verkeerd tijdstip in een verkeerd dagbestand (bv. 2000-01-01).
  4. d
    Stel twee uitbreidingen van het protocol voor (bv. om de tijd op te vragen) en zeg hoe de Mega moet antwoorden.
    Bijvoorbeeld: '?' geeft de huidige tijd terug als '# 2026-10-11 20:00:05'; 'I' geeft de status ('# SD ok, SHT31 ok, 2 INA226'); een fout geeft '# onbekende opdracht'. Elk antwoord begint met #, zodat een programma dat de logregels leest, het niet verwart met metingen.
Zo wordt dit beoordeeld
TijdTijdzone expliciet (UTC+1), onafhankelijk van zomertijd op de computer.
ProgrammaPoort openen, 2 s wachten, opdracht met regelovergang als bytes, antwoord lezen en tonen, poort sluiten.
RobuustheidHet antwoord van de Mega wordt gecontroleerd; andere regels (logregels) storen niet.
ProtocolUitbreidingen met een vaste vorm, een antwoord dat met # begint, en wat er bij een fout gebeurt.
30.15

Labo: log het klaslokaal

Uitdagen6Labo90 min
Bouw de datalogger uit de proef van het handboek en laat hem een schooldag loggen. Analyseer daarna met Python.
  1. a
    Teken het aansluitschema (I²C met pull-ups, SPI, voeding) en noteer de adressen die de scanner vond.
    Zoals in het handboek: SDA en SCL naar 20 en 21 (Uno A4 en A5), 5V en GND, eventueel extra pull-ups; SD op 50 tot 53 (Uno 10 tot 13). Adressen 0x44, 0x57, 0x68.
  2. b
    Noteer tijdens de dag de gebeurtenissen (lesbegin, pauzes, ramen open en dicht).
    Bijvoorbeeld 8:25 lesbegin, 10:15 pauze (ramen open), 12:05 middag, 13:00 les, 15:55 einde.
  3. c
    Maak een grafiek van temperatuur en vochtigheid en zet de gebeurtenissen erbij. Wat zie je?
    Typisch: temperatuur en vochtigheid stijgen tijdens de les, dalen snel bij open ramen, en vlakken af in de pauzes. Zonder mensen blijft het lokaal stil.
  4. d
    Controleer je gegevens: hoeveel regels, lege cellen, gaten? Hoe groot is het bestand, en klopt dat met je verwachting?
    Voor een dag van 8 uur: 480 regels; met regels van ±45 bytes ongeveer 22 kB. Gaten door een reset of een losse draad zie je met logboek.gaten(); lege cellen als de SHT31 even wegviel.
Zo wordt dit beoordeeld
OpstellingCorrect schema; scanner vindt alle chips; klok gezet in wintertijd.
MetingenEen volledige dag, een logboek van gebeurtenissen met tijden.
AnalyseGrafiek met assen en eenheden, gebeurtenissen aangeduid, verbanden beschreven.
KwaliteitAantal regels, lege cellen en gaten gecontroleerd en verklaard; bestandsgrootte berekend.
30.16

Het meetbereik van de stroommeting

Uitdagen7Analyseren35 min
In hoofdstuk 16 telt de Mega de laadtoestand met een ACS712-20A op A4: 2,50 V bij 0 A en 0,100 V per ampère; de uitgang kan niet boven ±5 V gaan. De logger gebruikt twee INA226 met een shunt van 100 A / 75 mV. Op een heldere middag leveren de panelen tot 1000 W; de rail staat dan op 13,3 V en de module verbruikt 20 W.
  1. a
    Hoe groot is de laadstroom van de batterij dan? Wat geeft de ACS712 bij die stroom, en wat doet de ADC ermee?
    . De ACS712-20A zou moeten geven (laden is negatief): dat kan niet. Hij is maar gemaakt voor ±20 A (0,5 tot 4,5 V); daarbuiten blijft zijn uitgang tegen de ondergrens hangen, en de coulombteller ziet ongeveer −20 A.
  2. b
    De coulombteller telt elke 2 s de gemeten stroom op. Een helder uur lang laadt de batterij met de stroom uit (a). Hoeveel procent laadtoestand mist de teller dan (240 Ah)?
    Reken dat de teller 20 A telt in plaats van 74 A: per uur 54 Ah te weinig, of % laadtoestand. Na een paar heldere uren denkt de Mega dat de batterij bijna leeg is, terwijl ze vol zit (tot de herijking bij 14,2 V ze weer op 100 % zet).
  3. c
    Hoeveel stappen van de INA226 is die stroom, en hoeveel warmte ontwikkelt de shunt?
    , of stappen (van de 32 767). Warmte: : een shunt van 100 A is daarvoor gemaakt.
  4. d
    Stel een verbetering voor de laadtoestand voor, met de chips die de module nu heeft.
    Bereken de batterijstroom als I zon − I verbruik uit de twee INA226's (knooppuntwet) en tel die op in de coulombteller, in plaats van de ACS712. Of zet een derde INA226 met een eigen shunt in de batterijleiding (adres 0x42). De ACS712 kan dan weg, of blijven als controle voor kleine stromen.