Arduino: Read DHT22/AM2302 Temperature and Humidity Sensor Using Interrupts

Electronics Micro-controller Software Development

[toc]

There are many sites where you can find Arduino schematics and code to read a temperature and humidity sensor then display that data on the Serial Monitor.

I have not worked with the (more accurate) DHT22/AM2302 sensors and wanted to test them. In addition, I will be demonstrating how to use interrupts (instead of delay) to read sensor in the Arduino.

In this article, I will be demonstrating the following techniques:

  • How to connect a temperature/humidity sensor, such as the DHT22, to an Arduino.
  • Download and install libraries required to support the devices we are using.
  • Initialize TIMER1 for 1 second interrupt
  • Initialize DHT temperature/humidity sensor data.
  • Read DHT sensor via interrupt instead of loop().
  • Write all changed data to the Serial Monitor.

Parts Used in this Test

The parts list below links to the items I purchased for this test. Feel free to substitute if needed. If you have any questions about substitutions, please leave a comment below and I will help you out.

Arduino UNO Rev 3$22
Adafruit AM2302 Temperature Humidity Sensor

There are many sources to purchase this sensor from. The primary requirement is it’s a DHT22 or a AM2302 sensor.
$15
Breadboard$2

This project can be completed for around $40 total.


Arduino UNO Rev 3

The Arduino UNO Rev 3 is more than powerful enough for this demonstration. However, everything being used here (including the code) will run on virtually any Ardino board that has the required inputs and outputs.

DHT22/AM2302 Sensor

The DHT22 and AM2302 sensors are very basic and slow, but are great for the learning. I’ve found Adafruit has the best overview and explanation for these sensors. If you’d like to learn more, please visit the following.

Wiring the DHT22/AM2302 Sensor

Wiring the DHT22/AM2302 sensor to your Arduino is very simple. The sensor has three connection points VDD, DATA and GND. VDD and GND are 5 vdc and ground respectively. The DATA connection is wired to the Digital/PWM pin 5 on your Arduino; see below.

DHT22/AM2302 Sensor Wired to Arduino UNO R3

Note, you can use any of the Digital/PWM pins you have available in your environment. If you change the pin, make sure to change it in the example Sketch too.

Arduino Code

Before we jump in to writing our Sketch, you will need to download and install (2) libraries; Adafruit Unified Sensor Library and the , Adafruit DHT Sensor Library.

Open your Arduino IDE and create a new project then follow the steps below to install these libraries.

Adafruit Unified Sensor Library

The core Adafruit Unified Sensor Library is required for all Adafruit sensor libraries. Follow the steps below to download and install the Adafruit Unified Sensor Library.

Adafruit Unified Sensor Library here: https://github.com/adafruit/Adafruit_Sensor
  • In your Arduino IDE, add the downloaded Adafruit_Sensor-master.zip file to your project.
  • Click the Sketch menu option then select Include Library then Adafruit Unified Sensor.

The Adafruit Unified Sensor library is now installed and ready to be used. Notice, in the below image, the Adafruit_Sensor.h file has been included in your Sketch.

Adafruit_Sensor.h file included in Sketch.

Adafruit DHT Sensor Library

Installing the Adafruit DHT Sensor Library uses the same basic steps as above. Follow the steps below to download and install the Adafruit DHT Sensor Library.

Adafruit DHT Sensor Library here: https://github.com/adafruit/DHT-sensor-library
  • In your Arduino IDE, add the downloaded DHT-sensor-library-master.zip file to your project.
  • Click the Sketch menu option then select Include Library then DHT Sensor Library.

Now that you’ve added both the Adafruit Unified Sensor and DHT libraries, your Arduino Sketch should have the following header files included.

I make it a habit to verify and compile my code on a fairly regular basis. Now would be a good time to do this. If you encounter any errors, go back to the top and make sure you have both required DHT libraries installed.

Arduino Sketch to Read DHT Sensor Data

The Sketch below will read the DHT22/AM2302 sensor, using an interrupt, and write data only as it changes. In cases where you wish to write this data to an LCD, only writing changes will reduce flicker. I will write an article describing how to write this data to a 20×2 LCD (without flicker).

The Sketch below will read the DHT sensor and write the information to the Serial Monitor. You may copy this and paste it into your Arduino IDE and run it. Below I will explain what each section does.

// Example Sketch Demonstrating the Use of Interrupts to Read a DHT Sensor
// Written by: Bob Mixon
//

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

// TIMER1 used for 2 second interrupt. The interrupt calls 
// ISR(TIMER1_COMPA_vect) where DHT data is checked/retrieved.
boolean bInterrupt1Toggle = 0;

// DHT pin and type.
#define DHTPIN      5
#define DHTTYPE     DHT22

// Declare all DHT variables.
DHT   oDHT(DHTPIN, DHTTYPE);
float fHumidity = 0;
float fTemperatureC = 0;
float fTemperatureF = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("DHT22 test!");
  Serial.println();
  Serial.print(F("Initializing DHT... "));
  oDHT.begin();
  Serial.println(F("complete..."));

  Serial.print(F("Initializing TIMER1 interrupt..."));
  cli();

  //set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();
  Serial.println(F("complete..."));
  Serial.println();
}

void loop()
{
}

// This is the timer interrupt (called approx. every 2 seconds)
// Here we check the DHT sensor and determine if anything has changed.
ISR(TIMER1_COMPA_vect)
{
  boolean bNewDataArrived = false;
  
  if (bInterrupt1Toggle){
    Serial.println(F("TIMER1 interrupt raised, check for new DHT data."));

    // See if new humidity data is available.
    float h = oDHT.readHumidity();          // Read DHT humidity data.
    if(!isnan(h) && h != fHumidity)
    {
      // New humidity data has arrived, write it to the serial console.
      fHumidity = h;
      Serial.print(F("Humidity: "));
      Serial.print(h);
      Serial.println(F("%"));
      bNewDataArrived = true;
    }

    // See if new temperature C data is available.
    float c = oDHT.readTemperature();       // Read DHT temperature C data.
    if(!isnan(c) && c != fTemperatureC)
    {
      // New temperature C data has arrived, write it to the serial console.
      fTemperatureC = c;
      Serial.print(F("Temperature: "));
      Serial.print(c);
      Serial.println(F(" C"));
      bNewDataArrived = true;
    }

    // See if new temperature F data is available.
    float f = oDHT.readTemperature(true);   // Read DHT temperature F data.
    if(!isnan(f) && f != fTemperatureF)
    {
      // New temperature F data has arrived, write it to the serial console.
      fTemperatureF = f;
      Serial.print(F("Temperature: "));
      Serial.print(f);
      Serial.println(F(" F"));
      bNewDataArrived = true;
    }
  
    bInterrupt1Toggle = 0;

    if(bNewDataArrived){Serial.println();}
    else{Serial.println(F("no new data.")); Serial.println();}
  }
  else{bInterrupt1Toggle = 1;}
}

The first part of this code includes the Adafruit DHT Sensor library header files. These files contain class definitions that make coding for the DHT sensor much easier on us.

// Example Sketch Demonstrating the Use of Interrupts to Read a DHT Sensor
// Written by: Bob Mixon
//

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

Next you see the bInterruptToggle variable declared. This is used in our interrupt function as basically a 1 second flip-flop.

// TIMER1 used for 2 second interrupt. The interrupt calls 
// ISR(TIMER1_COMPA_vect) where DHT data is checked/retrieved.
boolean bInterrupt1Toggle = 0;

Next all DHT specific constants and variables are declared. The default DHT data is wired to pin 5 in my environment. If you have used a different pin, update the DHTPIN constant accordingly.

The variables declared include the DHT class instance (oDHT) and buffers for storing the last values read from the DHT sensor. I’m storing the last DHT values read in these variables so we can decide when to update the Serial Monitor.

// DHT pin and type.
#define DHTPIN      5
#define DHTTYPE     DHT22

// Declare all DHT variables.
DHT   oDHT(DHTPIN, DHTTYPE);      // DHT object.
float fHumidity = 0;              // Buffer to save the last humidity reading.
float fTemperatureC = 0;          // Buffer to save the last temperature C reading.
float fTemperatureF = 0;          // Buffer to save the last temperature F reading.

In the next section is the setup() function. This function runs once, when your Arduino boots and is used to initialize everything needed to support your running (loop) code.

In the setup() function we initialize the Serial Monitor, the oDHT object and the interrupt.

void setup()
{
  Serial.begin(9600);
  Serial.println("DHT22 test!");
  Serial.println();
  Serial.print(F("Initializing DHT... "));
  oDHT.begin();
  Serial.println(F("complete..."));

  Serial.print(F("Initializing TIMER1 interrupt..."));
  cli();

  //set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();
  Serial.println(F("complete..."));
  Serial.println();
}

Next is the loop() function. You will notice there isn’t any code. It is here where most examples with have the code to read the sensor, write it to the Serial Monitor then use the delay() function.

void loop()
{
}

Lastly, is the interrupt function. This function is called every 1 second and will read the DHT sensor, check to see if the data has changed and, if so, write it to the Serial Monitor.

// This is the timer interrupt (called approx. every 1 seconds)
// Here we check the DHT sensor and determine if anything has changed.
ISR(TIMER1_COMPA_vect)
{
  boolean bNewDataArrived = false;
  
  if (bInterrupt1Toggle){
    Serial.println(F("TIMER1 interrupt raised, check for new DHT data."));

    // See if new humidity data is available.
    float h = oDHT.readHumidity();          // Read DHT humidity data.
    if(!isnan(h) && h != fHumidity)
    {
      // New humidity data has arrived, write it to the serial console.
      fHumidity = h;
      Serial.print(F("Humidity: "));
      Serial.print(h);
      Serial.println(F("%"));
      bNewDataArrived = true;
    }

    // See if new temperature C data is available.
    float c = oDHT.readTemperature();       // Read DHT temperature C data.
    if(!isnan(c) && c != fTemperatureC)
    {
      // New temperature C data has arrived, write it to the serial console.
      fTemperatureC = c;
      Serial.print(F("Temperature: "));
      Serial.print(c);
      Serial.println(F(" C"));
      bNewDataArrived = true;
    }

    // See if new temperature F data is available.
    float f = oDHT.readTemperature(true);   // Read DHT temperature F data.
    if(!isnan(f) && f != fTemperatureF)
    {
      // New temperature F data has arrived, write it to the serial console.
      fTemperatureF = f;
      Serial.print(F("Temperature: "));
      Serial.print(f);
      Serial.println(F(" F"));
      bNewDataArrived = true;
    }
  
    bInterrupt1Toggle = 0;

    if(bNewDataArrived){Serial.println();}
    else{Serial.println(F("no new data.")); Serial.println();}
  }
  else{bInterrupt1Toggle = 1;}
}

Run the Sketch and open your Serial Monitor. You will see the humidity, temperature C and temperature F data written once. From that point forward, only data that changes will be written to the Serial Monitor. Consider if you were writing this data to an LCD it would be virtually flicker-free.

Serial Monitor – Initializing and First Reading

Now hold your thumb over the sensor. You will begin to see the humidity and temperature rising.

Serial Monitor – DHT Sensor Data Changing

Conclusion

The TIMER1 interrupt initialization and function can be used for many different projects. If you find a need to have a process run as an interrupt, this could work for you!

Please share how it worked for you and if you have other project ideas where the interrupts can be used.

Until next time!

Bob Mixon

My primary goal in life is to support my family, be a friend and enjoy each day as it may be my last. For work, I am a Senior SharePoint Solution Architect, Senior Information Architect and Microsoft SharePoint MVP. You can read my entire profile here.

More Posts - Website

Follow Me:
LinkedIn

Advertisements
Tagged

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.