Wat je nodig hebt
-
Je 1.44" TFT-scherm, aangesloten zoals in project 01. Laat het gewoon zitten.
-
Je 0.96" OLED-schermpje, aangesloten zoals in de OLED-start — vier draadjes via I2C. Laat het gewoon zitten.
-
De DHT11: het printje met het lichtblauwe blokje met gaatjes.
Drie pinnen: VCC · DAT · GND. -
Drie dupont-draadjes. Meer heb je niet nodig.
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.
- 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%.
delay(2000) — en dat is deze keer geen luiheid maar een eis van de sensor.
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.
| Sensor | Betekenis | Naar je Arduino | Draad |
|---|---|---|---|
| VCC | Voeding | 5V | rood |
| DAT | Data (heen én terug) | D4 | amber |
| GND | 0 volt | GND | zwart |
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.
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.
Ga in de Arduino IDE naar Sketch → Include Library → Manage Libraries… en installeer:
- DHT sensor library van Adafruit.
- De IDE vraagt daarna of hij Adafruit Unified Sensor mag meenemen — zeg ja. Zonder die tweede werkt de eerste niet.
DHT sensor library. De andere doen ongeveer hetzelfde,
maar de code hieronder is voor deze geschreven.
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.
#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
}
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.
DHTPIN echt op 4 staat, en wacht na het
uploaden even een paar seconden — de eerste meting mislukt vaak.
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.
#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.
#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);
}
, 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.
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.
verloop[0] is het eerste hokje.#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);
}
#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);
}
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.
Zelf uitbreiden
Kleine uitdagingen om zelf te proberen, van makkelijk naar wat pittiger:
- Laat de grafiek langzamer lopen: zet
delay(2000)opdelay(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.
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.