Digital ChallengeWorkshop · Arduino × Processing
L01Workshop lab

Climate Station — DHT11

Measure the air. Stream it. Draw it.

Wire a DHT11, send temperature and humidity as one CSV line, and build a live Processing dashboard with bars and threshold alerts — your first two-value serial system.

2 × 45 min difficultyPhysicsComputer ScienceMathematics
Climate Station — DHT11
LibrariesCSV over serialisnan()map()Thresholds
01Before you start

What you’ll learn

By the end of this lab you can…
  • 1Install an Arduino library (Adafruit DHT) and explain why libraries exist.
  • 2Wire a digital sensor and name the job of a pull-up resistor.
  • 3Define relative humidity in one sentence a classmate would understand.
  • 4Send two numbers on one serial line and parse them in Processing.
  • 5Add a colour-coded alarm when a reading crosses a threshold.
Key vocabulary
DHT11
A low-cost digital sensor for temperature (0–50 °C, ±2 °C) and relative humidity (20–90 % RH, ±5 %).
Relative humidity (RH)
How much water vapour the air holds compared with the maximum it could hold at that temperature, in %.
Library
Ready-made code you include so you do not have to speak the sensor’s protocol yourself.
Pull-up resistor
A resistor that keeps a signal line HIGH when nothing is pulling it LOW. Needed on a bare 3-pin DHT11.
NaN
“Not a Number” — what dht.readTemperature() returns when the read failed. Test with isnan().
CSV
Comma-separated values. One line, two numbers: 24.5,61.
serialEvent()
A Processing function that runs when a full serial line arrives. Safer than reading inside draw().
02Kit list

Required equipment

ComponentQtyPurpose
Arduino Uno1Microcontroller
DHT11 sensor1Temperature + humidity
10 kΩ resistor1Pull-up (bare 3-pin sensor only)
Breadboard + jumpers1Prototyping
USB cable1Power + serial
Arduino IDE + Processing1Firmware + visualisation
03Theory

What you are actually measuring

The DHT11 is a digital sensor. Inside it sits a tiny humidity cell and a thermistor. A chip on the package converts both readings into a timed pulse train. You do not read a voltage on A0 — you ask a library to decode that pulse train on a digital pin.

Relative humidity, in human words

Warm air can hold more water vapour than cold air. Relative humidity is “how full is the air’s water tank right now?” That is why a cold bottle from the fridge sweats: the air next to the glass cools, its tank shrinks, and leftover water condenses.

Formula
RH = (actual water vapour ÷ maximum possible at this temperature) × 100 %
Accuracy, honestly
±2 °C and ±5 % RH. Good enough to see “the room got warmer” or “someone opened a window”. Not good enough for a weather station exam. Treat the numbers as trends, not laboratory truth.

The serial contract

Arduino and Processing must agree on a format. In this lab the contract is one line, two floats, comma in the middle, newline at the end:

serial lineText
24.50,61.00
01
Sense
DHT11 on D2
02
Print
temp,hum + newline
03
Parse
split on comma
04
Draw
text, bars, alerts
InteractiveClimate benchDrag the sliders. Watch how a dashboard turns numbers into bars and warnings.
Serial line → 24.0,55.0
Temperature: 24.0 °C
Humidity: 55.0 %
Alert
OK
CSV
24.0,55
04Hands-on

Wire the sensor

DHT11 to Arduino Uno — from the workshop handbook.
DHT11 to Arduino Uno — from the workshop handbook.
DHT11 pinArduino pin
VCC5V
GNDGND
DATADigital pin 2
The figure is incomplete
The original Tinkercad drawing shows the sensor floating — DATA is not drawn to pin 2. Trust the table, not the floating icon. On a bare 3-pin sensor add a 10 kΩ resistor between VCC and DATA. A 3-pin module (small PCB) already has that resistor.

Close the Arduino Serial Monitor before you run Processing. Only one program can own the COM port.

  1. 01In the Arduino IDE open Sketch → Include Library → Manage Libraries.
  2. 02Search for “DHT sensor library” by Adafruit.
  3. 03Install it. Accept Adafruit Unified Sensor when asked.
05Firmware

Arduino — read and send

DHT11_Serial.inoArduino · C++
#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
}

void loop() {
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature(); // Celsius

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Serial.print(temperature);
  Serial.print(",");
  Serial.println(humidity);
  delay(2000);
}
UpdatedReads both values, rejects NaN, sends one CSV line every 2 s. The original handbook pasted this sketch twice.
Tip
Serial.println() adds the newline. Processing will wait for that newline before it tries to parse. Never put a space after the comma unless you also trim it on the other side.
06Visualise

Processing — a live dashboard

The original sketch read serial inside `draw()`. That works until a half-line arrives and float() blows up. The version below uses bufferUntil('\n') and serialEvent() — the same pattern you will reuse in every later lab.

ClimateDashboard.pdeProcessing · Java
import processing.serial.*;

Serial myPort;
float temperature, humidity;

void setup() {
  size(640, 360);
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600); // change index if needed
  myPort.bufferUntil('\\n');
}

void draw() {
  background(16);
  fill(240);
  textSize(22);
  text("Temperature: " + nf(temperature, 0, 1) + " °C", 40, 60);
  text("Humidity: " + nf(humidity, 0, 1) + " %", 40, 96);

  fill(255, 92, 77);
  rect(40, 140, map(temperature, 0, 50, 0, 520), 28, 4);
  fill(62, 232, 216);
  rect(40, 184, map(humidity, 0, 100, 0, 520), 28, 4);

  if (temperature > 30) {
    fill(255, 80, 80);
    text("HIGH TEMPERATURE", 40, 260);
  } else if (humidity < 30) {
    fill(80, 160, 255);
    text("LOW HUMIDITY", 40, 260);
  }
}

void serialEvent(Serial p) {
  String data = p.readStringUntil('\\n');
  if (data == null) return;
  data = trim(data);
  String[] values = split(data, ",");
  if (values.length == 2) {
    temperature = float(values[0]);
    humidity = float(values[1]);
  }
}
UpdatedImport added. Serial moved to serialEvent(). Bars + high-temp / low-humidity alerts included.
COM port
Serial.list()[0] is whoever Windows listed first — often not the Arduino. Read the printed list. If Processing says the port is busy, close the Arduino Serial Monitor.
07From the workshop

Student tasks

Basic
Wire the DHT11 and print temp,humidity to Serial Monitor.
You see two numbers updating every ~2 s.
Basic
Show both values as text in Processing.
The window tracks the room.
Intermediate
Add two bars with `map()` and `rect()`.
Bars grow as the room changes.
Intermediate
Colour-coded alerts above 30 °C or below 30 % RH.
A warning appears when you breathe on the sensor or warm it in your hand.
Advanced
Log every reading to a .csv file.
You can open the file in a spreadsheet.
Challenge
Plot both values over time with `beginShape()`.
A live chart, not just a bar.
08When it doesn’t work

Troubleshooting

ProblemLikely causeFix
“Failed to read from DHT sensor!”Wrong pin, missing pull-up, or you asked the sensor faster than every 1–2 s.Check VCC/GND/DATA. Add 10 kΩ on a bare sensor. Keep delay(2000).
Processing window stays at 0.Wrong COM port, or Serial Monitor still open.Close the Monitor. Change Serial.list()[n].
float() errors / flickering text.Half a line arrived, or a failed-read message was parsed as numbers.Use serialEvent, trim, and check values.length == 2.
Golden rule
Check the physical connections first, then the code. If nothing works, unplug, close both programs, reconnect and try again.
09Student edition

Exercises

Basic · 2Intermediate · 2Advanced · 1Challenge · 1
L01-E1BasicPredict 5 min

What does the line look like?

Arduino prints Serial.print(temperature); Serial.print(","); Serial.println(humidity); with temperature = 22.4 and humidity = 48. Write the exact characters that travel over USB, including the invisible ones.

println adds a newline (\n). There is no space after the comma.
22.40,48.00 followed by \n. (Arduino may print extra zeros — the important part is number,comma,number,newline.)
L01-E2BasicExplain 8 min

Why a pull-up?

A classmate uses a bare 3-pin DHT11 with only three wires: 5V, GND, DATA. Readings fail at random. Explain, in 4–6 sentences, what a pull-up resistor does on the DATA line and why the module version often works without an extra resistor.

The DATA pin is open-drain. When nobody is driving it, it would float.
The DHT11 DATA pin is open-drain: it can pull the line LOW but cannot push it HIGH. A 10 kΩ resistor to 5 V holds the line HIGH between pulses. Without it the pin floats and the library sees garbage. A DHT11 module already has that resistor soldered on the PCB, so three wires are enough.
L01-E3IntermediateCalculate 8 min

Map a bar

Processing window is 640 px wide. You draw a bar starting at x = 40, and you want 50 °C to fill 520 px. What is map(28, 0, 50, 0, 520)? How wide is the bar at 28 °C?

map(value, fromLow, fromHigh, toLow, toHigh) = toLow + (value−fromLow)/(fromHigh−fromLow) × (toHigh−toLow).
28/50 × 520 = 291.2 px. The bar is 291 px wide (Processing will draw it as a float).
L01-E4IntermediateDebug 10 min

The NaN trap

This sketch sometimes prints nan,nan and Processing’s bars vanish. Find two bugs and write the corrected loop().

buggy.inoArduino · C++
void loop() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  Serial.print(t);
  Serial.print(",");
  Serial.println(h);
  delay(200);
}
DHT11 needs ≥ 1 s between reads. Failed reads return NaN.
Bug 1: no isnan() guard. Bug 2: 200 ms is too fast. Guard and wait 2 s.
loop()Arduino · C++
void loop() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    delay(2000);
    return;
  }
  Serial.print(t);
  Serial.print(",");
  Serial.println(h);
  delay(2000);
}
L01-E5AdvancedCode 15 min

Log to CSV

Extend the dashboard so every accepted reading is appended to climate.csv as millis,temp,hum. Create the file in setup() with a header row.

In Processing: PrintWriter log = createWriter("climate.csv"); then log.println(...) and log.flush().
Create the writer in setup(), write a header, then in serialEvent after a successful parse write millis()+","+temperature+","+humidity and flush().
logging fragmentProcessing · Java
PrintWriter log;

void setup() {
  // ... serial setup ...
  log = createWriter("climate.csv");
  log.println("millis,temp,hum");
}

void serialEvent(Serial p) {
  String data = trim(p.readStringUntil('\\n'));
  String[] v = split(data, ",");
  if (v.length != 2) return;
  temperature = float(v[0]);
  humidity = float(v[1]);
  log.println(millis() + "," + temperature + "," + humidity);
  log.flush();
}
L01-E6ChallengeDesign 20 min

A chart, not a bar

Design (on paper or in code) a 2-minute scrolling chart of temperature. List: the data structure you store, how many points, how you map time to x and temperature to y, and what happens when the array is full.

A fixed-size array used as a ring buffer, or append() + subset() to drop the oldest point.
Store ~60 floats (one every 2 s for 2 min). Each frame, x = map(i, 0, n-1, 40, width-40), y = map(values[i], 10, 40, height-40, 40). When full, shift left (for i in 0..n-2: a[i]=a[i+1]) and write the new sample at the end. Draw with beginShape() / vertex() / endShape().
10Check yourself

Self-check quiz

Progress
0/6 answered · 0 correct
  1. Q01

    The DHT11 talks to Arduino on…

  2. Q02

    Relative humidity is 100 %. What does that mean?

  3. Q03

    Why check isnan()?

  4. Q04

    Which serial line matches the contract of this lab?

  5. Q05

    Processing should read serial in…

  6. Q06

    A 3-pin DHT11 **module** usually does not need an extra 10 kΩ because…

11Beyond the classroom

Real world & extensions

Where this is used
Classroom weather stationGreenhouse monitorServer-room heat alarmMuseum humidity log
Extension ideas
  • +Save a line to data/log.csv every time serialEvent fires.
  • +Draw a 2-minute scrolling chart with beginShape() / endShape().
  • +Add a third “feels like” line using a simple heat-index formula.
Cross-curricular connections
SubjectConnection
PhysicsPhase changes, saturation vapour pressure, why dew forms.
Mathematicsmap() is a linear function: y = y0 + (x−x0)·(y1−y0)/(x1−x0).
CSProtocols: two programs agree on a byte format before they talk.
12Think about it

Reflection & conclusion

?1

If you breathed on the sensor, which number moved first — temperature or humidity? Why?

?2

What would break if Arduino printed “24.5 °C, 60 %” instead of “24.5,60”?

?3

Name one place in your school that should have a humidity alarm, and pick the threshold.

Conclusion

You built a two-sensor pipeline: a digital chip, a one-line protocol, and a dashboard. Every later lab is the same idea with a different sensor.