DHT22 Temperature and Humidity Sensor Interfacing with Pic Microcontroller

In this tutorial, we will learn to interface DHT22 temperature and humidity sensor with pic microcontroller. We will begin with an introduction of DHT22, its pinout diagram, Features, internal circuit. After that we will discuss interfacing circuit diagram. At the end of tutorial, we see programming examples in MPLAB compiler and MikroC Pro for pic.

DHT22 Introduction

The DHT-22 is a sensor which measures relative humidity and temperature sensor and provides a calibrated digital output. It is an inexpensive sensor that is almost similar to the DHT11 but measures temperature and humidity with higher accuracy and wider range. You don’t need extra components for operation. It is pre-calibrated, and you can directly connect it to obtain the output. The DHT22 sensor is composed of a humidity sensing sensor and a thermistor. These two components measure the humidity and temperature and send out a digital signal on the data pin.

Pin Configuration Diagram

This figure shows the pinout diagram of DHT22 humidity and temperature sensor. It consists of three pins.

DHT22 pinout diagram

Pin Description

The DHT22 sensor is very simple and easy to use. It has only four pins.

  • Vcc is the power pin. Apply voltage in a range of 3.5 V to 5.0 V at this pin.
  • Data Out is the digital output pin. It sends out the value of measured temperature and humidity in the form of serial data.
  • N/C is a not connect pin.
  • GND: Connect the GND pin to main ground.

Features

The important features of DHT22 sensor are:

  • The range of operating voltage () is 3 V to 5 V power.
  • It measures temperature in a range of -40°C to +125°C with an accuracy of ± 0.5 degrees.
  • The measuring range for humidity is from 0 to 100% with an accuracy of 2-5%.
  • The maximum operating current for DHT22 sensor is 2.5mA.
  • The sampling rate for DHT22 sensor is 0.5 Hz. It takes measurement once every 2 seconds.
  • The sensor has four pins with 0.1″ spacing and a size of body is 15.1mm x 25mm x 7.7mm.

Where to use it?

It is small in size and utilizes low power. It has a long transmission distance of about 20m. Normally, we use DHT22 sensor in applications for measuring ambient temperature and humidity. You can also use DHT11 sensor as it has same function but DHT22 sensor is more reliable as compared to DHT11 sensor. It is pre-calibrated and it has internal temperature compensation.

These sensors are well suited for use in all kinds of harsh applications and you can interface this device with microcontrollers easily. If you need a sensor for measuring temperature in a range of -40°C to +125°C or you need to measure humidity, then this sensor would be ideal for use in such an application.

Connection Diagram with any Microcontroller

The connections are simple as it does not require any external electrical components. It has only four pins in which one is a not connect pin. You can directly connect the other three pins with any microcontroller. The DHT22 sensor does not have any clock pin that means it operates in serial asynchronous mode. It needs a pull-up resistor between and data line to keep it in High logic. This pull-up resistor is essential for communication between the sensor and a microcontroller. Figure (3) shows the basic connection diagram for connecting this sensor.

Internal Circuit Diagram

Interfacing with Pic Microcontroller

The breakout board of this sensor has an onboard pull-up resistor hence you can directly connect its breakout board with PIC microcontroller or Arduino.

In this example, we have used PIC18F25K20 microcontroller and used the RA0 pin to receive data from DHT22. We use a pull-up resistor of value 4.7 kΩ or 10 kΩ. Connect the data output pin to the RA0 pin of PIC18F25K20. The figure below shows the connections of a DHT22 sensor with Pic microcontroller.

DHT22 interfacing with Pic Microcontroller

Apply 5V power to the sensor. In some applications, we connect a 100nF capacitor between ground and power in which provides wave filtering. After applying power, don’t send any instructions withing 1 second because the sensor takes one second to give stable output values of temperature and humidity.

We have used 16×2 LCD with PORTB of PIC18F25K20 microcontroller. If you didn’t work with LCD before, you can read this post:

16X2 LCD Interfacing with Pic Microcontroller

MPLAB XC8 Code

This code is for MPLAB XC8 Compiler. If you don’t know how to use MPLAB and XC8 compiler, you can read this complete in-depth guide:

#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ   4E6

#pragma config IESO = OFF, FOSC = INTIO67, FCMEN = OFF
#pragma config BOREN = OFF, PWRT = OFF
#pragma config WDTEN = OFF
#pragma config CCP2MX = PORTC, PBADEN = OFF, MCLRE = ON
#pragma config DEBUG = OFF, STVREN = ON, XINST = OFF, LVP = OFF
#define LCD_EN       PORTBbits.RB3
#define LCD_RS       PORTBbits.RB2
#define LCD_DATA     PORTB
#define LCD_STROBE() (LCD_EN=1), (LCD_EN=0)


// write a byte to the LCD in 4 bit mode
void lcd_write(unsigned char c)
 { __delay_us(40);
   LCD_DATA &= 0x0f;
   LCD_DATA |= (c & 0xf0);
   LCD_STROBE();
   LCD_DATA &= 0x0f; 
   LCD_DATA |= ((c<<4) & 0xf0);
   LCD_STROBE();
 }

// Clear and home the LCD
void lcd_clear(void)
 { LCD_RS = 0;
   lcd_write(0x1);
   __delay_ms(2);
 }

// write a string of chars to the LCD
void lcd_puts(const char * s)
 { LCD_RS = 1;     // write characters
   while(*s)
      lcd_write(*s++);
 }

// write one character to the LCD
void lcd_putch(char c)
 { LCD_RS = 1;     // write characters
   lcd_write( c );
 }

// Go to the specified position
void lcd_goto(unsigned char pos)
 { LCD_RS = 0;
   lcd_write(0x80+pos);
 }
        
// initialise the LCD - put into 4 bit mode
void lcd_init(void)
 { char init_value;
   
   init_value = 0x3;
   LCD_RS = 0;
   LCD_EN = 0;
        
   __delay_ms(15);     // wait 15mSec after power applied,
   LCD_DATA &= 0x0f;
   LCD_DATA |= (init_value<<4) & 0xf0 ;
   LCD_STROBE();
   __delay_ms(5);
   LCD_STROBE();
   __delay_us(200);
   LCD_STROBE();
   __delay_us(200);
   LCD_DATA &= 0x0f; 
   LCD_DATA |= (2<<4) & 0xf0;   // Four bit mode
   LCD_STROBE();

   lcd_write(0x28);  // Set interface length
   lcd_write(0xc);   // Display On, Cursor Off, Cursor Blink off
   lcd_clear();      // Clear screen
   lcd_write(0x6);   // Set entry Mode
 }

#define Data      PORTAbits.RA0
#define DataDir   TRISAbits.TRISA0

char message1[] = "Temp = 00.0 C";
char message2[] = "RH   = 00.0 %";
unsigned short TOUT = 0, CheckSum, i;
unsigned short T_Byte1, T_Byte2, RH_Byte1, RH_Byte2;

// Function Prototypes 
void lcd_out (char row, char col, const char * s1);
void delay_1s(void);

void start_signal()
 { DataDir = 0;     // Data port is output
   Data    = 0;
   __delay_ms(18);
   DataDir = 1;     // Data port is input
   __delay_us(30);
 }

unsigned short check_response()
 { TOUT = 0;
   TMR2 = 0;
   TMR2ON = 1;                // start timer
   while (!Data && !TOUT);
   if (TOUT) 
      return 0;
   else 
    { TMR2 = 0;
      while (Data && !TOUT);
      if (TOUT) 
         return 0;
      else 
       { TMR2ON = 0;
         return 1;
       }
    }
 }

unsigned short read_byte()
 { unsigned short num = 0;
   DataDir = 1;
   for (i=0; i<8; i++)
    { while (!Data);
      TMR2 = 0;
      TMR2ON = 1;
      while (Data);
      TMR2ON = 0;
      if (TMR2 > 40) 
         num |= 1<<(7-i);  // If time > 40us, Data is 1
    }
   return num;
 }

void interrupt tc_int(void)
 { if (TMR2IF)
    { TOUT = 1;
      TMR2ON = 0; // stop timer
      TMR2IF = 0; // Clear TMR0 interrupt flag
    }
 }


void main(void)
 { unsigned short check, sign;
   unsigned int rh, temp;
   
   // Internal oscillator frequency to 4MHz. 
   OSCCON = 0b01010000;

   TRISB = 3;
   PORTB = 0;
   TRISA = -1;
   
   // RA0 Digital input buffer is enabled. 
   // NOTE: PORTB digital input buffers are enabled by CONFIG default (PBADEN=OFF)
   ANSELbits.ANS0 = 0;        

   GIE = 1;          // Enable global interrupt
   PEIE = 1;         // Enable peripheral interrupt
   TMR2IE = 1;       // Enable Timer2 interrupt
   T2CON = 0;        // Prescaler 1:1, and Timer2 is off initially  
   TMR2IF = 0;       // Clear TMR INT Flag bit
   TMR2 = 0;

   lcd_init();   
   lcd_clear();

   // Main loop
   while (1)
    { delay_1s();
      start_signal();
      check = check_response();
      if (!check) 
       { lcd_clear();
         lcd_out(1, 1, "No response");
         lcd_out(2, 1, "from the sensor");
       }
      else
       { RH_Byte1 = read_byte();
         RH_Byte2 = read_byte();
         T_Byte1  = read_byte();
         T_Byte2  = read_byte();
         CheckSum = read_byte();
         
         // From RHT03 (DHT22 equivalent) datasheet:
         // Example: MCU has received 40 bits data from RHT03 as
         // 0000 0010 1000 1100   0000 0001 0101 1111   1110 1110
         // 16 bits RH data       16 bits T data        check sum
         // Check sum=0000 0010+1000 1100+0000 0001+0101 1111=1110 1110
         // RH= (0000 0010 1000 1100)/10=65.2%RH
         // T=(0000 0001 0101 1111)/10=35.1 DEG
         // When highest bit of temperature is 1, it means the temperature is below 0 degree Celsius.
         // Example: 1000 0000 0110 0101, T= minus 10.1 DEG
         //             16 bits T data
         rh   = RH_Byte2 | (RH_Byte1<<8);
         temp = T_Byte2  | (T_Byte1<<8);
         sign = 0;
         if (temp>0x8000)
          { temp &= 0x0fff;
            sign = 1;
           }
         
         unsigned char rh_buf[5], temp_buf[5];
         sprintf (rh_buf,   "%03u", rh);
         sprintf (temp_buf, "%03u", temp);
         
         // Check for error in Data reception
         if (CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF))
          { message2[7]  = rh_buf[0];
            message2[8]  = rh_buf[1];
            message2[10] = rh_buf[2];
            
            if (sign)
               message1[6] = '-';
            else
               message1[6] = ' ';
            message1[7]  = temp_buf[0];
            message1[8]  = temp_buf[1];
            message1[10] = temp_buf[2];
            message1[11] = 223;     // Degree symbol
            lcd_clear();
            lcd_out(1, 1, message1);
            lcd_out(2, 1, message2);
          }
         else
          { lcd_clear();
            lcd_out(1, 1, "Checksum Error!");
            lcd_out(2, 1, "Trying Again ...");
          }
       }
    }
 }

void lcd_out (char row, char col, const char * s1)
 { if (row==1)
      lcd_goto(0x00+col-1);    
   else
      lcd_goto(0x40+col-1);    
      
   lcd_puts(s1);
 }   

void delay_1s (void)
 { for (short i=0; i<10; i++)
      __delay_ms(100);   
 }

Proteus Simulation Result

DHT22 interfacing with Pic Microcontroller simulation results

MikroC Code

This code is written using MikroC for Pic compiler.  Create a new project with MikroC compiler by selecting PIC16F877A microcontroller and set frequency to 8MHz. If you don’t know how create new project in mikroC, we suggest you read this post:

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// end LCD module connections

// DHT22 pin connection (here data pin is connected to pin RB0)
#define DHT22_PIN         RA0_bit
#define DHT22_PIN_DIR     TRISA0_bit

char dht22_read_byte()
{
  char i = 8, dht22_byte = 0;

  while(i--)
  {
    while( !DHT22_PIN );

    delay_us(40);

    if( DHT22_PIN )
    {
      dht22_byte |= (1 << i);   // set bit i
      while( DHT22_PIN );
    }
  }
  return(dht22_byte);
}

// read humidity (in hundredths rH%) and temperature (in hundredths °Celsius) from sensor
void dht22_read(int *dht22_humi, int *dht22_temp)
{
  // send start signal
  DHT22_PIN     = 0;   // connection pin output low
  DHT22_PIN_DIR = 0;   // configure connection pin as output
  delay_ms(25);        // wait 25 ms
  DHT22_PIN     = 1;   // connection pin output high
  delay_us(30);        // wait 30 us
  DHT22_PIN_DIR = 1;   // configure connection pin as input

  // check sensor response
  while( DHT22_PIN );
  while(!DHT22_PIN );
  while( DHT22_PIN );

  // read data
  *dht22_humi = dht22_read_byte();  // read humidity byte 1
  *dht22_humi = (*dht22_humi << 8) | dht22_read_byte();  // read humidity byte 2
  *dht22_temp = dht22_read_byte();  // read temperature byte 1
  *dht22_temp = (*dht22_temp << 8) | dht22_read_byte();  // read temperature byte 2
  dht22_read_byte();               // read checksum (skipped)

  if(*dht22_temp & 0x8000) {      // if temperature is negative
    *dht22_temp &= 0x7FFF;
    *dht22_temp *= -1;
  }

}
void main()
{
  OSCCON = 0x70;            // set internal oscillator to 8MHz
  //ANSELH = 0;               // configure all PORTB pins as digital
  delay_ms(1000);           // wait a second

  Lcd_Init();               // initialize LCD module
  Lcd_Cmd(_LCD_CURSOR_OFF); // cursor off
  Lcd_Cmd(_LCD_CLEAR);      // clear LCD
  lcd_out(1, 1, "Temp =");
  lcd_out(2, 1, "Humi =");

  while(1)
  {
    int humidity, temperature;
    char temp_a[8], humi_a[8];

    // read humidity (in hundredths rH%) and temperature (in hundredths °C) from the DHT22 sensor
    dht22_read(&humidity, &temperature);

    if(temperature < 0)
      sprinti(temp_a, "-%02u.%01u%cC", abs(temperature)/10, abs(temperature) % 10, 223);
    else
      sprinti(temp_a, " %02u.%01u%cC", temperature/10, temperature % 10, 223);

    if(humidity >= 1000)     // if humidity >= 100.0 rH%
      sprinti(humi_a, "%03u.%01u %%", humidity/10, humidity % 10);
    else
      sprinti(humi_a, " %02u.%01u %%", humidity/10, humidity % 10);

    lcd_out(1, 7, temp_a);
    lcd_out(2, 7, humi_a);

    //delay_ms(1000);  // wait a second

  }

}

Applications

  • Weather station for measuring temperature and monitoring environment
  • Automatic climate control
  • Humidity controller for measuring relative humidity
  • Test and detection device

Leave a Comment

3 × two =