Build a Humidity-to-Color Display
4-Hour Hardware Camp
by Brendon Thiede
Today you build a real circuit with a real microcontroller…
…and you take it home.
By the end of camp, this is yours.
Name one thing in your home you wish was smarter or did something automatically.
| 0:00–0:45 | Welcome + what is home automation? |
| 0:45–1:10 | Meet the hardware |
| 1:10–1:45 | 🔧 Build & upload your first code |
| 1:45–2:00 | ☕ Break |
| 2:00–3:30 | 🔧 Sensor → LED → full project |
| 3:30–3:40 | ☕ Break |
| 3:40–4:00 | 🔧 Make it yours + show & tell |
Most of today is hands-on building.
Making things in your home sense, decide, and act — without you doing it by hand.
What do these all have in common?
Sensor → Logic → Output
Something it can feel → a rule → something it does.
💧 DHT22 sensor (humidity/temperature)
↓
🧠 ESP32 brain
↓
🔴🟢🔵 RGB LED output
Pick up each part as we talk about it — but don't wire anything yet.
No soldering — parts just push in. The rows secretly connect for you.
A tiny, cheap, programmable computer — about $6.
Reads humidity (and temperature too) — breathe on it and the humidity jumps.
Three colors can be blended. Legs (left to right): Red, GND (longest leg), Green, Blue.
Resistors slow electricity down so we don't burn parts out.
Resistors slow electricity down so we don't burn parts out, decreasing current while increasing voltage.
Join at learning-check.web.app
Enter the code on the screen.
Phone, tablet, or laptop — whatever you've got.
In order to send a program to the ESP32, we need to connect it to our computer via USB using a data cable (not a charging-only cable).
No external wires for this step — the LED we blink is already on the board (GPIO 2).
onboard-LED-blink project under home-automationplatformio.ini and src/main.cpp
const int LED_PIN = 2; // the LED already on the board
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(LED_PIN, HIGH); // on
Serial.println("LED ON");
delay(500);
digitalWrite(LED_PIN, LOW); // off
Serial.println("LED OFF");
delay(500);
}
Everyone's onboard LED is blinking and Serial Monitor scrolls "LED ON / LED OFF".
Stuck? Wrong COM port, missing CP210x driver, or baud rate not 115200.
Join at learning-check.web.app
Enter the code on the screen.
Phone, tablet, or laptop — whatever you've got.
Stretch, water, walk around.
Leave your board plugged in and happy.
| DHT22 pin | Connects to |
|---|---|
| VCC | 3V3 |
| DATA | GPIO 4 + 10 kΩ pull-up to 3V3 |
| NC | leave empty |
| GND | GND |
Our bare DHT22 has no built-in pull-up. Without that 10 kΩ bridge from DATA to 3V3, you'll get read errors.
It keeps the data line "held high" so the sensor's signal is clear.
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
float humidity = dht.readHumidity();
float tempC = dht.readTemperature();
if (isnan(humidity) || isnan(tempC)) {
Serial.println("Read failed - check wiring!");
return;
}
Serial.print("Humidity: "); Serial.print(humidity);
Serial.print("% Temp: "); Serial.print(tempC);
Serial.println("C");
delay(2000);
}
Real humidity & temperature numbers scroll in Serial Monitor.
Breathe on the sensor — watch humidity jump!
Join at learning-check.web.app
Enter the code on the screen.
Phone, tablet, or laptop — whatever you've got.
| LED leg | Connects to |
|---|---|
| Red | 220 Ω → GPIO 18 |
| Common cathode (longest) | GND |
| Green | 220 Ω → GPIO 19 |
| Blue | 220 Ω → GPIO 23 |
Resistor goes in series with each color leg — never on the cathode/GND leg.
const int RED_PIN = 18, GREEN_PIN = 19, BLUE_PIN = 23;
void setColor(int red, int green, int blue) {
ledcWrite(0, red); // 0–255 brightness per channel
ledcWrite(1, green);
ledcWrite(2, blue);
}
void setup() {
ledcSetup(0, 5000, 8); ledcAttachPin(RED_PIN, 0);
ledcSetup(1, 5000, 8); ledcAttachPin(GREEN_PIN, 1);
ledcSetup(2, 5000, 8); ledcAttachPin(BLUE_PIN, 2);
}
PWM = blinking faster than your eye can see, to fake "half brightness."
Before mixing — prove each channel works:
setColor(255, 0, 0); delay(700); // red only
setColor(0, 255, 0); delay(700); // green only
setColor(0, 0, 255); delay(700); // blue only
The starter firmware runs this R→G→B self-test on startup for you.
Red, green, and blue each light up on their own.
Green/blue look dim? That's expected — we can swap them to 150 Ω later.
Join at learning-check.web.app
Enter the code on the screen.
Phone, tablet, or laptop — whatever you've got.
Sensor reading → color logic → glowing LED, in one loop.
Reference schematic. Yours can look different — as long as the connections match!
float humidity = dht.readHumidity();
if (humidity < 30) {
setColor(255, 0, 0); // Red - very dry
} else if (humidity < 50) {
setColor(255, 255, 0); // Yellow - dry side
} else if (humidity < 70) {
setColor(0, 255, 0); // Green - comfortable
} else {
setColor(0, 0, 255); // Blue - very humid
}
Humidity is the default — you can change it instantly by breathing on the sensor.
| Humidity | Color | Vibe |
|---|---|---|
| Below 30% | 🔴 Red | Very dry |
| 30–50% | 🟡 Yellow | Dry side |
| 50–70% | 🟢 Green | Comfortable |
| Above 70% | 🔵 Blue | Very humid |
One line switches it to temperature mode instead.
NaN → check the 10 kΩ pull-upBreathe on the sensor → your LED changes color.
🎉 You built a working sensor-driven device.
Join at learning-check.web.app
Enter the code on the screen.
Phone, tablet, or laptop — whatever you've got.
Stretch, water, walk around. Almost there.
Pick one (or more!) to experiment with.
"Maya's room: HUMID"
setColor(255, 128, 0); // orange
setColor(128, 0, 255); // purple
setColor(0, 255, 255); // teal/cyan
setColor(255, 255, 255); // white-ish
One last challenge — everything you built today.
Join at learning-check.web.app and enter the code.
Who wants to demo their color map?
Check the Next Steps page for project ideas, and the Glossary if a word was new.