Learning Goals 5 min
- Wire a DHT11 sensor module (3 pins on the breakout, 4 pins on the bare chip) and explain why it talks a custom one-wire protocol — not analog, not I²C, not serial.
- Install your first third-party library through the Arduino IDE Library Manager, and understand what a library actually does for you.
- Read both temperature and humidity in one sketch and print them, formatted nicely, every two seconds — using
millis()rather thandelay()so future you can add more work.
Warm-Up 10 min
Up until now everything has read straight off an analog or digital pin. The DHT11 is different: it's a digital sensor that uses its own custom protocol on a single wire. The chip sends pulses of various widths down that wire, and the receiver (your Arduino) decodes them into bits. Writing the decoder by hand would take an entire lesson on its own. Instead — for the first time in this course — we'll install a library that someone else has written.
Why libraries exist
A library is just a bundle of .h and .cpp files that gives you ready-made functions. We've already been using libraries: Serial is built into the IDE; so are tone() and analogRead(). A third-party library is one we have to install ourselves because it's not in the box.
Today: install the DHT library, write three lines, get temperature and humidity. The protocol still happens — we just don't have to write it.
New Concept · Installing and using a library 20 min
What the DHT11 module looks like
Most classrooms have the 3-pin module — the DHT11 chip soldered onto a small blue board with a pull-up resistor already built in. The three pins are labelled + (or VCC), OUT (or DATA or S) and − (or GND). If you have the bare 4-pin sensor instead, pin 3 is unused; you also need a 10 kΩ pull-up between DATA and +5 V.
| Module pin | Connect to |
|---|---|
| + (VCC) | +5 V |
| OUT (DATA) | D2 (any digital pin) |
| − (GND) | GND |
Installing the library — step by step
- Open the Arduino IDE.
- Open Tools → Manage Libraries… (or press
Ctrl/Cmd + Shift + I). - In the search box, type DHT sensor library.
- Find "DHT sensor library" by Adafruit in the list.
- Click Install. If it asks to install dependencies (Adafruit Unified Sensor), click Install all.
You only need to do this once per computer. The library is now available to every sketch you write.
The minimum-viable sketch
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT11
DHT dht(DHT_PIN, DHT_TYPE);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float t = dht.readTemperature(); // °C by default
float h = dht.readHumidity(); // %RH
Serial.print("T: "); Serial.print(t, 1);
Serial.print(" °C H: "); Serial.print(h, 0);
Serial.println(" %");
delay(2000); // DHT11 needs ~1 s between reads
}Three new ideas:
#include <DHT.h>— pull in the library's declarations.DHT dht(pin, type)— create a sensor object calleddhttied to pin 2 and type DHT11.dht.readTemperature()/dht.readHumidity()— ask the object for the values. The library handles the protocol, decoding, error checking, everything.
Why the 2-second delay
The DHT11 is slow. The chip needs about a second between measurements to settle. Read it faster than that and you'll get repeated old values or NaN (Not a Number — the library's way of saying "the read failed"). For DHT11 use 2 s; for the faster DHT22 you can drop to 1 s.
Worked Example · Robust temperature + humidity logger 20 min
Step 1 — wiring
Three wires from the DHT11 module to the UNO:
+→ +5 V rail.OUT→ D2.−→ GND rail.
That's the entire circuit. No partner resistors, no soldering.
Step 2 — the sketch
Save as dht11-log.ino:
// L02-14: DHT11 → T + H every 2 s, non-blocking, NaN-safe
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT11
DHT dht(DHT_PIN, DHT_TYPE);
const unsigned long READ_INTERVAL = 2000;
unsigned long lastRead = 0;
void setup() {
Serial.begin(9600);
dht.begin();
Serial.println("time_s,temp_C,humidity_pct"); // CSV header
}
void loop() {
if (millis() - lastRead < READ_INTERVAL) return;
lastRead = millis();
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
Serial.println("read failed — check wiring");
return;
}
Serial.print(millis() / 1000); Serial.print(",");
Serial.print(t, 1); Serial.print(",");
Serial.println(h, 0);
}Four upgrades over the minimum-viable version:
- Non-blocking timer. Using
millis()means the loop is free to do other work while we wait — the foundation for everything in Cluster F. - CSV output. Each line is comma-separated, perfect for pasting into a spreadsheet later.
- CSV header. Printed once in
setup()so the columns are labelled. - NaN guard. If the read fails we print a friendly error and bail out of this loop iteration; we don't pretend the bad value is real.
Step 3 — upload and observe
Open Serial Monitor at 9600. After the header line, you'll get a new reading every two seconds:
time_s,temp_C,humidity_pct 2,27.0,68 4,27.0,69 6,27.0,68 8,27.0,69
Typical indoor Malaysia: 26–29 °C, 65–80% humidity. Air-con rooms are drier (40–55%); a rainy afternoon outdoors can push humidity above 90%.
Step 4 — log to a spreadsheet
Let it run for 5 minutes. Then in the Serial Monitor, select all the lines (Ctrl/Cmd + A), copy, paste into a new Google Sheet or Excel file. Data → Split text to columns (or just import as CSV). You now have ~150 data points you can chart. That's already a basic data logger — and we haven't even touched SD cards yet.
Step 5 — breathe on the sensor
Cup your hand over the DHT11 and exhale slowly for 10–15 seconds. Humidity should jump from ~70% to ~95% within two reads, and temperature might tick up 1 °C. Lift your hand — humidity drops back over the next 30 seconds as the moisture evaporates from the sensor surface.
Try It Yourself 20 min
Goal: Print a friendly comfort label alongside the readings: dry (< 40%), comfortable (40–60%), humid (60–80%), tropical (≥ 80%). Just like the personal thermometer's status string from L02-12.
Hint
const char* comfortFor(float h) {
if (h < 40) return "dry";
if (h < 60) return "comfortable";
if (h < 80) return "humid";
return "tropical";
}Goal: Light an LED when the humidity is "tropical" (≥ 80%). Use pin 9 with a 220 Ω resistor. Useful as a quick visual signal that you should switch on the dehumidifier or fan.
Hint
Add pinMode(9, OUTPUT) in setup, and after the NaN guard:
digitalWrite(9, (h >= 80) ? HIGH : LOW);The condition ? a : b form is the ternary operator — shorthand for an if/else that returns a value. Cleaner than four lines of if.
Goal: Compute the heat index — "feels like" temperature — and print it too. The Adafruit DHT library has a built-in dht.computeHeatIndex(t, h, false) (false = °C). It combines temperature and humidity to estimate how warm the air actually feels to a person — relevant in muggy Malaysian afternoons where 30 °C with 90% humidity feels like 38 °C.
Hint
float hi = dht.computeHeatIndex(t, h, false);
Serial.print(t, 1); Serial.print(" °C ");
Serial.print(h, 0); Serial.print(" %RH feels: ");
Serial.print(hi, 1); Serial.println(" °C");Notice how on a cool dry day the heat index is close to the air temperature, but on a hot humid day it can be 5–8 °C higher. That's the "feels like" number you see on phone weather apps.
Mini-Challenge · Comfort dashboard 15 min
Combine the DHT11 with three LEDs to build a simple comfort dashboard. Use:
- Green LED on D9 — comfortable (40–60% humidity, 22–28 °C).
- Amber/yellow LED on D10 — borderline (anything outside the green band but not red).
- Red LED on D11 — uncomfortable (humidity ≥ 80% or temperature ≥ 30 °C).
It works if:
- In a normal air-conditioned classroom (26 °C, 55%RH) → green is on.
- Breathe heavily near the sensor for 30 s → amber, then red.
- Step away → it returns to green within a minute.
- Only one LED is ever on at a time.
Reveal one valid sketch
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT11
const int GREEN = 9;
const int AMBER = 10;
const int RED = 11;
DHT dht(DHT_PIN, DHT_TYPE);
unsigned long lastRead = 0;
const unsigned long READ_INTERVAL = 2000;
void setColour(int g, int a, int r) {
digitalWrite(GREEN, g);
digitalWrite(AMBER, a);
digitalWrite(RED, r);
}
void setup() {
pinMode(GREEN, OUTPUT);
pinMode(AMBER, OUTPUT);
pinMode(RED, OUTPUT);
Serial.begin(9600);
dht.begin();
}
void loop() {
if (millis() - lastRead < READ_INTERVAL) return;
lastRead = millis();
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) return;
bool red = (h >= 80) || (t >= 30);
bool green = (h >= 40 && h < 60) && (t >= 22 && t < 28);
bool amber = !red && !green;
setColour(green, amber, red);
Serial.print(t, 1); Serial.print(" °C ");
Serial.print(h, 0); Serial.print(" %RH ");
Serial.println(red ? "RED" : green ? "GREEN" : "AMBER");
}The setColour(g, a, r) helper guarantees only one LED can be on by passing three booleans — the lazy way to encode "exactly one of these". Try changing the bands: maybe your bedroom likes 24–26 °C; maybe your studio wants 45–55%RH.
Recap 5 min
The DHT11 is a digital sensor that returns both temperature (°C, integer) and humidity (%RH, integer-ish) over a single custom-protocol wire. The protocol is awkward enough that we use a third-party library — Adafruit's DHT sensor library — to handle the decoding for us. Three new patterns came out of this lesson: installing a library through Library Manager, instantiating a sensor object (DHT dht(pin, type)), and guarding against failed reads with isnan(). We also stepped up from delay() to a millis()-based read interval — a habit you'll keep for the rest of the course.
- DHT11 / DHT22
- A pair of cheap combined temperature + humidity sensors. DHT11 = ±2 °C / ±5%RH, integer values, slow. DHT22 = ±0.5 °C / ±2%RH, decimal values, faster, costs more.
- Library
- A bundle of code someone else wrote and packaged so you can
#includeit and use its functions in one line each. Saves you from re-implementing protocols from scratch. - Library Manager
- The Arduino IDE tool (Tools → Manage Libraries…) that searches, installs and updates third-party libraries from a central index.
- Sensor object
- An instance of a library's class — e.g.
DHT dht(2, DHT11)— that holds the sensor's configuration and gives you methods likereadTemperature(). - NaN (Not a Number)
- A special
floatvalue the library returns when a read fails. Detect withisnan(x); never let it slip into downstream maths. - Heat index
- The "feels like" temperature that combines air temperature with humidity. The DHT library exposes it as
computeHeatIndex(t, h, false). - %RH
- Relative humidity: the percentage of moisture the air is holding compared to the maximum it could hold at that temperature. 100% = saturated, 0% = bone dry.
- Non-blocking read
- Using
millis()rather thandelay()to decide when to take the next reading — keeps the loop free to do other work in parallel.
Homework 5 min
Indoor vs outdoor humidity log. Take your DHT11 sketch and run it for 30 minutes in two locations:
- Inside your air-conditioned bedroom (or any aircon room).
- Outside on a balcony or porch (out of direct sun and out of rain).
For each location, copy 15 lines from the Serial Monitor and paste into a spreadsheet. Make a chart with two lines (T and H over time) for each location. Then answer:
- Which location had higher humidity? By how much on average?
- Which location had more stable readings (smaller swings)? Why might that be?
- If you were designing a weather station, which sensor reading would you trust more — DHT11 indoor or DHT11 outdoor? Why?
Bring back next class:
- Your two spreadsheet charts (printed or on a phone).
- Your three written answers.
- Your
hw-l02-14.inosketch — tomorrow we add a light meter so you've got three readings going at once.