Code Along - Chapter 17

Temperature & Humidity (DHT11)

Optional practice: read a DHT11, print temperature and humidity, catch failed readings with isnan(), and make a broken sensor switch the alarm on.

Estimated time 40-60 min, optionalExercises passed 0 / 5

Optional practice: a DHT11 on the virtual Uno

This chapter is optional. Do it after Lesson 25 if you have time, or to revise before the environment monitor. Nothing in class depends on it.

The virtual board has a DHT11 wired to D2, just like the lesson. While a sketch runs you can:

  • drag the Temperature and Humidity sliders - the air around the sensor changes
  • tick Sensor fault - that is the data wire coming loose, so every reading fails and comes back as NaN (not a number)

Three things behave exactly like the Adafruit library on a real board. A DHT11 reports whole numbers, so 21.6 °C reads as 22.0. A reading within 2 seconds of the last one just repeats the last values - which is why the sketches wait 2 s between reads. And dht.begin() must run in setup() first, or every read fails.

What the simulator does not model: the DHT11's own error (about ±2 °C and ±5 %RH), how slowly a real sensor follows a change of air, and the pull-up resistor a bare sensor needs. Those are what the bench is for.

Worked example

The lesson's sketch

Press Run, then move the sliders and tick Sensor fault. Watch how long it takes for each change to reach the Serial Monitor.

#include <DHT.h>

const byte dhtPin = 2;
DHT dht(dhtPin, DHT11);  // use DHT22 if that is the part fitted

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

void loop() {
  delay(2000);
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("DHT read failed");
    return;
  }
  Serial.print(temperature, 1);
  Serial.print(" C  ");
  Serial.print(humidity, 1);
  Serial.println(" %RH");
}

Turn on JavaScript to edit, run and test this code in the browser.

Expected output
22.0 C  50.0 %RH
22.0 C  50.0 %RH
22.0 C  50.0 %RH
  • return; inside loop() ends this pass early - the next pass starts with the next delay(2000).
  • A change can take up to 2 s to show, because the sketch only asks every 2 s. That is fine for room air.
Exercise 17.1

Read the temperature

Not started

Everything is set up. In loop(), read the temperature into a float and print it like this, every 2 seconds:

Temperature: 22.0 C

Print the number with 1 decimal place. The test warms the air to 26 °C after 3 seconds, so the second line should change.

Sample output
Temperature: 22.0 C
Temperature: 26.0 C
#include <DHT.h>

const byte dhtPin = 2;
DHT dht(dhtPin, DHT11);

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

void loop() {
  delay(2000);
  // Read the temperature into a float, then print "Temperature: ", the value and " C"

}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 17.2

Temperature and humidity on one line

Not started

Add the humidity. Each line should read like the lesson's sketch:

22.0 C 50.0 %RH

Read it with dht.readHumidity() and print it with 1 decimal place. The test makes the air damper (65 %) after 3 seconds.

Sample output
22.0 C  50.0 %RH
22.0 C  65.0 %RH
#include <DHT.h>

const byte dhtPin = 2;
DHT dht(dhtPin, DHT11);

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

void loop() {
  delay(2000);
  float temperature = dht.readTemperature();
  // Read the humidity too

  Serial.print(temperature, 1);
  Serial.print(" C  ");
  // Print the humidity with 1 decimal place, then " %RH" to end the line

}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 17.3

Catch a failed reading

Not started

This sketch prints whatever the sensor gives it - so when the data wire comes loose it prints nan C nan %RH. Press Run and tick Sensor fault to see it.

Change it so that when either reading failed it prints Sensor error instead of the numbers. isnan(value) is true when a value is NaN. The test unplugs the sensor between 3 and 5 seconds.

Sample output
22.0 C  50.0 %RH
Sensor error
22.0 C  50.0 %RH
#include <DHT.h>

const byte dhtPin = 2;
DHT dht(dhtPin, DHT11);

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

void loop() {
  delay(2000);
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  // If either reading failed, print "Sensor error" instead of the line below
  Serial.print(temperature, 1);
  Serial.print(" C  ");
  Serial.print(humidity, 1);
  Serial.println(" %RH");
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 17.4

Too hot or broken: the alarm goes on

Not started

The alarm LED on D8 must be on when the temperature is 30 °C or more, and off otherwise.

There is a catch. Every comparison with NaN is false, so temperature >= TOO_HOT on its own leaves the alarm off when the sensor is unplugged - a broken monitor that says all is well. The course rule is fail safe: a sensor fault switches the alarm on. It is the same rule Practical Task B marks.

The test warms the air to 32 °C, cools it to 24 °C, then unplugs the sensor.

#include <DHT.h>

const byte dhtPin = 2;
const int ALARM_PIN = 8;
const float TOO_HOT = 30.0;

DHT dht(dhtPin, DHT11);

void setup() {
  pinMode(ALARM_PIN, OUTPUT);
  dht.begin();
}

void loop() {
  delay(2000);
  float temperature = dht.readTemperature();

  // Alarm ON if the reading failed OR it is too hot - otherwise OFF

}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 17.5

On the LCD, every 2 s, keeping the last good values

DeeperNot started

This is the lesson's challenge. Show the readings on the I2C LCD, refreshed every 2 s with a millis() timer - no delay(), because the onboard LED's blink (already written) must keep going.

  • line 1: Temp: 22.0 C (1 decimal place)
  • line 2: Hum: 50 % (no decimals - note the two spaces)

When a read fails, leave the last good values on the screen instead of showing nan. The test warms the air to 25 °C, then unplugs the sensor.

#include <DHT.h>
#include <LiquidCrystal_I2C.h>

const byte dhtPin = 2;
DHT dht(dhtPin, DHT11);
LiquidCrystal_I2C lcd(0x27, 16, 2);

unsigned long lastRead = 0;
unsigned long lastBlink = 0;
bool blinkOn = false;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  dht.begin();
  lcd.init();
  lcd.backlight();
}

void loop() {
  if (millis() - lastBlink >= 500) {
    lastBlink += 500;
    blinkOn = !blinkOn;
    digitalWrite(LED_BUILTIN, blinkOn);
  }

  // Every 2000 ms: read both values, and if neither failed, show them on the LCD

}

Turn on JavaScript to edit, run and test this code in the browser.

Try it on a real Uno

Wire the DHT11 as in Lesson 25 - DATA to D2, and a 4.7-10 kΩ pull-up if it is a bare sensor - and upload Catch a failed reading. Breathe on the sensor: humidity jumps within a few seconds, temperature creeps up much more slowly. Then pull the data wire out and check you get Sensor error, not a number.

Too hot or broken is the heart of the alarm in Lesson 27, so it is worth having in your fingers before you start that build.