ARDUINO WERKPLAATS
◂ bouwt voort op Project 02 · de afstandssensor Project 03 · temperatuur & vochtigheid

Je eigen
weerstation.

Deze sensor meet twee dingen tegelijk: hoe warm het is én hoe vochtig de lucht is. Nieuw is dat we hem niet zelf uitlezen — daar gebruiken we een library voor. En op het eind tekenen we een echte grafiek die je ziet bewegen als je op de sensor ademt.

Sensor: DHT11 Meet: °C én % Nieuw: library + grafiek ~35 min
Welk bord gebruik je?
De sensorpin is op beide borden hetzelfde; alleen je scherm blijft aangesloten zoals je het al had.
Welk scherm gebruik je?
Alle sketches op deze pagina wisselen mee naar het scherm dat jij hebt.
0

Wat je nodig hebt

  • 1.44 inch TFT-scherm Je 1.44" TFT-scherm, aangesloten zoals in project 01. Laat het gewoon zitten.
  • 0.96 inch OLED-schermpje Je 0.96" OLED-schermpje, aangesloten zoals in de OLED-start — vier draadjes via I2C. Laat het gewoon zitten.
  • DHT11 temperatuur- en vochtigheidssensor De DHT11: het printje met het lichtblauwe blokje met gaatjes. Drie pinnen: VCC · DAT · GND.
  • dupont-draadjes Drie dupont-draadjes. Meer heb je niet nodig.
Wat er nieuw is in dit project Twee dingen. Ten eerste praat deze sensor in een eigen taaltje dat te ingewikkeld is om zelf uit te lezen — daar bestaat een kant-en-klare library voor. Ten tweede gaan we meetwaarden onthouden om er een grafiek van te tekenen. Dat is precies één stapje verder dan project 02, waar je steeds maar één meting tegelijk liet zien.
1

Wat de DHT11 meet

In dat lichtblauwe blokje zitten twee meetdingetjes verstopt, en daarom kun je er twee antwoorden uit halen. Het rooster van vierkante gaatjes is er zodat de lucht er echt bij kan — plak het dus nooit af en houd er geen duim op.

DHT11 lucht een thermometertje → hoe warm is het? (°C) een vochtplaatje → hoeveel water zit in de lucht? (%)
Eén sensor, twee antwoorden — daarom haal je er straks ook twee getallen uit.
Temperatuur
In graden Celsius. De DHT11 kan van 0 tot 50 °C en zit er ongeveer 2 graden naast. Prima voor in huis.
Vochtigheid
In procent. 40% is lekker droog kamerklimaat, 80% voelt klam. Adem je erop, dan schiet hij richting de 90%.
Deze sensor heeft rust nodig De DHT11 is traag: hij wil hooguit één meting per twee seconden. Vraag je vaker, dan geeft hij rommel of niets terug. Daarom staat er in alle sketches hieronder delay(2000) — en dat is deze keer geen luiheid maar een eis van de sensor.
2

De sensor aansluiten

Drie draadjes, klaar. We gebruiken D4 voor de datalijn: die is vrij, ook als je scherm en de afstandssensor van project 02 nog aangesloten zitten.

DHT11 Arduino Uno R4 VCC5V DATD4 GNDGND drie draadjes — op beide borden hetzelfde
De middelste pin is de datalijn: daarover stuurt de sensor allebei zijn getallen.
SensorBetekenisNaar je ArduinoDraad
VCCVoeding5Vrood
DATData (heen én terug)D4amber
GND0 voltGNDzwart
Kijk naar de lettertjes, niet naar de plek Niet elk DHT11-printje heeft de pinnen in dezelfde volgorde! Op sommige is het VCC · DAT · GND, op andere GND · DAT · VCC. Lees dus wat er naast de pinnetjes op het printje staat en ga niet op het plaatje af. VCC en GND verwisselen maakt de sensor warm — meteen loskoppelen als dat gebeurt.
Botst dit met je scherm? Nee. Je TFT gebruikt D8/D9/D10 plus de klok/data-pinnen — op de R4 zijn dat D13/D11. D4 blijft daarnaast gewoon vrij.
Botst dit met je scherm? Nee. Je OLED gebruikt alleen de I2C-pinnen SDA/SCL (of A4/A5) plus 5V en GND. D4 blijft daarnaast gewoon vrij.
3

Een library erbij installeren

Tot nu toe deed je alle sensorwerk zelf: bij de HC-SR04 stuurde je een piepje en mat je een tijd. Bij de DHT11 kan dat niet. Hij stuurt zijn twee getallen als een reeks razendsnelle pulsjes over dat ene datadraadje — miljoenste seconden uit elkaar. Dat uitpluizen is onbegonnen werk. Gelukkig heeft iemand dat al voor je gedaan en in een library gestopt.

Een library, dat ken je al Voor je scherm gebruik je er ook twee: GFX (tekenen) en de driver van je scherm. Een library is gewoon een doos met kant-en-klare code die iemand anders schreef. Nieuw is alleen dat het deze keer om een sensor gaat in plaats van een scherm.

Ga in de Arduino IDE naar Sketch → Include Library → Manage Libraries… en installeer:

  1. DHT sensor library van Adafruit.
  2. De IDE vraagt daarna of hij Adafruit Unified Sensor mag meenemen — zeg ja. Zonder die tweede werkt de eerste niet.
Welke van de zoekresultaten? Typ je "DHT" in, dan krijg je een hele lijst. Je moet die van Adafruit hebben, met precies de naam DHT sensor library. De andere doen ongeveer hetzelfde, maar de code hieronder is voor deze geschreven.
4

Eerst meten in de Serial Monitor

Zoals altijd: eerst kijken of de sensor überhaupt praat, vóór we het scherm erbij halen. Upload dit en open Tools → Serial Monitor. Adem eens op de sensor en kijk wat er gebeurt.

01_weer_serial.ino
#include <DHT.h>          // de library die de sensor voor ons uitleest

#define DHTPIN 4          // de datalijn zit op D4
#define DHTTYPE DHT11     // welk type sensor: een DHT11 (niet de DHT22)

DHT dht(DHTPIN, DHTTYPE); // maak "dht" aan: onze sensor

void setup() {
  Serial.begin(9600);
  dht.begin();            // start de sensor op
}

void loop() {
  float temp  = dht.readTemperature();   // graden Celsius
  float vocht = dht.readHumidity();      // procent

  // Soms lukt een meting niet. De library geeft dan "geen getal" terug:
  // dat heet NaN (Not a Number). Daar moet je altijd op controleren.
  if (isnan(temp) || isnan(vocht)) {
    Serial.println("Meting mislukt - ik probeer het zo weer");
  } else {
    Serial.print(temp);
    Serial.print(" C   ");
    Serial.print(vocht);
    Serial.println(" %");
  }

  delay(2000);            // de DHT11 wil twee seconden rust tussen metingen
}
Nieuw woord: float Tot nu toe gebruikten we int: hele getallen. Een float is een getal met cijfers achter de komma, zoals 21.30. Temperatuur is nu eenmaal zelden precies rond.
Zie je alleen "Meting mislukt"? Dan komt er geen antwoord van de sensor. Loop de drie draadjes na (klopt de volgorde op jouw printje?), controleer of DHTPIN echt op 4 staat, en wacht na het uploaden even een paar seconden — de eerste meting mislukt vaak.
5

Twee getallen op het scherm

Werken de metingen? Dan zetten we ze groot in beeld: de temperatuur in geel, de vochtigheid in cyaan. De vaste woordjes tekenen we één keer in setup() — alleen de getallen veranderen straks.

WEERSTATION temperatuur 21 C vochtigheid 48 %
Twee metingen, netjes onder elkaar op je 128 × 128 scherm.
02_weerstation.ino
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <DHT.h>

#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#define DHTPIN 4
#define DHTTYPE DHT11

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  dht.begin();
  tft.initR(INITR_144GREENTAB);
  tft.fillScreen(ST77XX_BLACK);

  // de vaste tekst: die tekenen we maar een keer
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_WHITE);
  tft.setCursor(6, 6);    tft.print("WEERSTATION");
  tft.setCursor(6, 22);   tft.print("temperatuur");
  tft.setCursor(6, 72);   tft.print("vochtigheid");
}

void loop() {
  float temp  = dht.readTemperature();
  float vocht = dht.readHumidity();

  if (isnan(temp) || isnan(vocht)) {   // mislukt? sla deze ronde over
    delay(2000);
    return;
  }

  // --- temperatuur (geel) ---
  tft.fillRect(0, 32, 128, 34, ST77XX_BLACK);   // wis alleen dit vak
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(4);
  tft.setCursor(6, 34);   tft.print(temp, 0);   // 0 = geen cijfers achter de komma
  tft.setTextSize(2);
  tft.setCursor(64, 50);  tft.print("C");

  // --- vochtigheid (cyaan) ---
  tft.fillRect(0, 82, 128, 34, ST77XX_BLACK);
  tft.setTextColor(ST77XX_CYAN);
  tft.setTextSize(4);
  tft.setCursor(6, 84);   tft.print(vocht, 0);
  tft.setTextSize(2);
  tft.setCursor(64, 100); tft.print("%");

  delay(2000);
}

Werken de metingen? Dan zetten we ze op je OLED. Kleur heb je niet, dus zetten we er woordjes bij: zo zie je meteen welk getal wat is. En omdat je met een kladblok werkt, teken je gewoon élke ronde alles opnieuw — dat scheelt gepriegel met wissen.

WEERSTATION 21C 48% temp vocht
Naast elkaar in plaats van onder elkaar — 64 pixels hoog is niet veel.
02_weerstation_oled.ino
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define DHTPIN 4
#define DHTTYPE DHT11

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  dht.begin();
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);   // adres 0x3C (soms 0x3D)
  oled.setTextColor(SSD1306_WHITE);
}

void loop() {
  float temp  = dht.readTemperature();
  float vocht = dht.readHumidity();

  if (isnan(temp) || isnan(vocht)) {
    delay(2000);
    return;
  }

  oled.clearDisplay();        // kladblok leeg

  oled.setTextSize(1);
  oled.setCursor(0, 0);
  oled.print("WEERSTATION");

  // twee grote getallen naast elkaar (textSize 2 = 12 px per teken)
  oled.setTextSize(2);
  oled.setCursor(0, 22);   oled.print(temp, 0);  oled.print("C");
  oled.setCursor(70, 22);  oled.print(vocht, 0); oled.print("%");

  // kleine woordjes eronder, zodat je weet wat wat is
  oled.setTextSize(1);
  oled.setCursor(0, 48);   oled.print("temp");
  oled.setCursor(70, 48);  oled.print("vocht");

  oled.display();             // alles in een keer tonen
  delay(2000);
}
Wat doet die , 0 achter print? Bij een float mag je erbij zetten hoeveel cijfers je achter de komma wilt. print(temp, 0) geeft 21, print(temp, 1) geeft 21.3. Op een klein schermpje is afronden een stuk rustiger — en de DHT11 is toch niet nauwkeuriger dan een graad of twee.
6

Een grafiek van het verloop

Nu het mooiste stuk. Eén getal vertelt je hoe het nu is; een grafiek vertelt je wat er gebeurt. We tekenen het verloop van de vochtigheid, want die reageert razendsnel: adem op de sensor en je ziet de lijn omhoogschieten.

Het nieuwe idee: een rij hokjes om dingen te onthouden

Om een lijn te kunnen tekenen moet je oude metingen bewaren. Daarvoor gebruik je een array: één naam voor een hele rij hokjes, genummerd vanaf 0. Elke nieuwe meting gaat in het laatste hokje, en alles schuift een plekje op — net als een rij mensen bij de kassa waar er vooraan eentje weggaat.

de rij is vol — er komt een nieuwe meting bij: 444547 5261 012 34 oudste valt eraf nieuwe meting komt er achteraan bij …en dan teken je gewoon een lijntje van hokje naar hokje.
Een array is een rij hokjes met één naam. verloop[0] is het eerste hokje.
61 vocht 4 min
Elke twee seconden komt er rechts een puntje bij; links valt het oudste eraf.
03_grafiek.ino
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <DHT.h>

#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#define DHTPIN 4
#define DHTTYPE DHT11

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
DHT dht(DHTPIN, DHTTYPE);

const int PUNTEN = 120;     // zoveel metingen passen er naast elkaar
byte verloop[PUNTEN];       // de rij hokjes met oude metingen
int aantal = 0;             // hoeveel hokjes al gevuld zijn

const int LAAG = 20;        // onderkant van de grafiek (%)
const int HOOG = 90;        // bovenkant van de grafiek (%)

// zet een nieuwe meting achteraan in de rij
void onthoud(byte waarde) {
  if (aantal < PUNTEN) {
    verloop[aantal] = waarde;
    aantal++;
  } else {
    for (int i = 0; i < PUNTEN - 1; i++) {
      verloop[i] = verloop[i + 1];      // alles een plekje naar links
    }
    verloop[PUNTEN - 1] = waarde;       // de nieuwe komt achteraan
  }
}

// reken een meting om naar een hoogte op het scherm
int naarY(byte waarde) {
  int y = map(waarde, LAAG, HOOG, 122, 44);
  return constrain(y, 44, 122);
}

void tekenGrafiek() {
  tft.fillRect(0, 38, 128, 90, ST77XX_BLACK);   // grafiekvlak wissen
  tft.drawRect(3, 40, 122, 88, ST77XX_WHITE);   // het kader

  for (int i = 1; i < aantal; i++) {            // lijntje van hokje naar hokje
    tft.drawLine(4 + i - 1, naarY(verloop[i - 1]),
                 4 + i,     naarY(verloop[i]), ST77XX_CYAN);
  }
}

void setup() {
  dht.begin();
  tft.initR(INITR_144GREENTAB);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_WHITE);
  tft.setCursor(74, 8);   tft.print("vocht");
  tft.setCursor(74, 20);  tft.print("4 min");
}

void loop() {
  float vocht = dht.readHumidity();
  if (isnan(vocht)) { delay(2000); return; }

  onthoud((byte)vocht);

  // het huidige getal groot linksboven
  tft.fillRect(0, 0, 70, 34, ST77XX_BLACK);
  tft.setTextColor(ST77XX_CYAN);
  tft.setTextSize(3);
  tft.setCursor(4, 8);
  tft.print(vocht, 0);

  tekenGrafiek();
  delay(2000);
}
61% vocht 4 min
Zelfde grafiek, alleen wit-op-zwart en wat platter.
03_grafiek_oled.ino
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define DHTPIN 4
#define DHTTYPE DHT11

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
DHT dht(DHTPIN, DHTTYPE);

const int PUNTEN = 120;     // zoveel metingen passen er naast elkaar
byte verloop[PUNTEN];       // de rij hokjes met oude metingen
int aantal = 0;

const int LAAG = 20;        // onderkant van de grafiek (%)
const int HOOG = 90;        // bovenkant van de grafiek (%)

// zet een nieuwe meting achteraan in de rij
void onthoud(byte waarde) {
  if (aantal < PUNTEN) {
    verloop[aantal] = waarde;
    aantal++;
  } else {
    for (int i = 0; i < PUNTEN - 1; i++) {
      verloop[i] = verloop[i + 1];      // alles een plekje naar links
    }
    verloop[PUNTEN - 1] = waarde;
  }
}

int naarY(byte waarde) {
  int y = map(waarde, LAAG, HOOG, 61, 23);
  return constrain(y, 23, 61);
}

void setup() {
  dht.begin();
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextColor(SSD1306_WHITE);
}

void loop() {
  float vocht = dht.readHumidity();
  if (isnan(vocht)) { delay(2000); return; }

  onthoud((byte)vocht);

  oled.clearDisplay();

  // het huidige getal linksboven
  oled.setTextSize(2);
  oled.setCursor(0, 2);
  oled.print(vocht, 0);
  oled.print("%");

  // labeltjes rechts
  oled.setTextSize(1);
  oled.setCursor(74, 0);  oled.print("vocht");
  oled.setCursor(74, 10); oled.print("4 min");

  // het kader en de lijn
  oled.drawRect(0, 21, 128, 43, SSD1306_WHITE);
  for (int i = 1; i < aantal; i++) {
    oled.drawLine(4 + i - 1, naarY(verloop[i - 1]),
                  4 + i,     naarY(verloop[i]), SSD1306_WHITE);
  }

  oled.display();
  delay(2000);
}
Waarom byte en niet int? Een byte kan getallen van 0 tot 255 onthouden en kost maar één plekje geheugen; een int kost er twee. Vochtigheid komt nooit boven de 100, dus een byte is ruim genoeg — en 120 stuks passen zo makkelijk in het geheugen van je Arduino.
Even geduld bij het opstarten De grafiek begint leeg en vult zich van links naar rechts. Na twee seconden heb je één puntje, na vier minuten is het beeld vol en begint hij op te schuiven. Adem er tussendoor eens op — dán zie je pas hoe leuk het is.
7

Zelf uitbreiden

Kleine uitdagingen om zelf te proberen, van makkelijk naar wat pittiger:

  • Laat de grafiek langzamer lopen: zet delay(2000) op delay(10000) en je ziet tien minuten in plaats van vier.
  • Onthoud de hoogste en laagste temperatuur van de dag en zet die in een hoekje.
  • Teken de temperatuur er als tweede lijn bij — je hebt een tweede array nodig en een tweede kleur, en om ze uit elkaar te houden bijvoorbeeld een gestippelde lijn.
  • Maak een comfortmeter: onder de 30% "te droog", boven de 70% "te klam", daartussen "lekker".
  • Gevorderd: zet de sensor met langere draadjes buiten het raam en vergelijk binnen met buiten.

Wat nu?

Volgende stap: alles combineren

Je kunt nu een scherm aansturen, afstand meten, een sensor met een eigen library uitlezen én metingen onthouden om er een grafiek van te tekenen. In project 04 gebruiken we de afstandssensor als besturing en bouwen we een spel dat je met je hand in de lucht speelt.

← Project 02  ·  Project 04 →  ·  Alle projecten