Measure Temperature and Humidity using DHT11 sensor and PIC micro-controller

Published by MKDas on

When you need to measure humidity, one sensor that comes to mind first is DHT11. This sensor also provides temperature data. Using DHT11, we can measure humidity and temperature but as it is a digital sensor, interfacing is not linear like an analog sensor. Here in this article, we are going to learn how to interface a DHT11 sensor and PIC micro-controller and measure humidity and temperature.

Disclaimer: Electricity is always dangerous. Skill required to work with electricity. Do work at your own risk. The author will not be responsible for any misuse or harmful act. This website contents are also copyright protected. Anything copied and directly posted on your website and claiming it as yours is prohibited and nonsensical. The author published all the articles as open source to help you to make your project and learning purpose only. Learn and make one for yourself. If need any help feel free to ask the author. The author will be helpful to you. Thanks.

About DHT11 sensor:

The DHT11 measures relative humidity. The relative humidity is the amount of water vapor in air vs the saturation point of water vapor in the air. At the saturation point, water vapor starts to condense and accumulate on surfaces forming dew.

The saturation point changes with air temperature. Cold air can hold less water vapor before it becomes saturated, and hot air can hold more water vapor before it becomes saturated.

The formula to calculate relative humidity is:

RH = (\frac{\rho_{w}}{\rho_{s}}) \ x \ 100 \% \\ \\ RH: \ Relative \ Humidity \\ \rho_{w}: \ Density \ of \ water \ vapor\\ \rho_{s}: \ Density \ of \ water \ vapor \ at \ saturation

The relative humidity is expressed as a percentage. At 100% RH, condensation occurs, and at 0% RH, the air is completely dry.

Pin Configuration of DHT11

Technical Specification of DHT11:

  • Low cost
  • 3 to 5V power and I/O
  • 2.5mA max current use during conversion (while requesting data)
  • Good for 20-80% humidity readings with 5% accuracy
  • Good for 0-50°C temperature readings ±2°C accuracy
  • No more than 1 Hz sampling rate (once every second)
  • Body size 15.5mm x 12mm x 5.5mm
  • 4 pins with 0.1″ spacing

Interfacing DHT11 with MCU:

According to the datasheet of DHT11, the recommended connection diagram is:

This pin is bi-directional. It sends and receives data. The communication between MCU and DHT11 is:

Communication signal pattern
Signal pattern

So we have to draw our circuit according to the datasheet of DHT11.

You can read this article too: How to interface DHT22 with PIC microcontroller

Circuit diagram:

Here is the circuit diagram for interfacing DHT11 sensor and PIC micro-controller:

DHT11 sensor and PIC micro-controller
Circuit Diagram

Coding:

/*******************************************************************************
Program for, "DHT11 interfacing with PIC16F877A"
Program written by_ Engr. Mithun K. Das
MCU: PIC16F877A; X-tal: 8MHz; mikroC pro for PIC v7.6.0
Date: 15-05-2020
*******************************************************************************/

// LCD module connections
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 of LCD initialization

sbit Data at RB1_bit;
sbit DataDir at TRISB1_bit;

char message[] = "00.0";
unsigned short TOUT = 0, CheckSum, i;
unsigned int humidity,value;
unsigned int T_Byte1, T_Byte2, RH_Byte1, RH_Byte2;

void StartSignal()
{
  DataDir = 0;     // Data port is output
  Data    = 0;
  Delay_ms(25);
  Data    = 1;
  Delay_us(30);
  DataDir = 1;     // Data port is input
}

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

unsigned short ReadByte()
{
  unsigned short num = 0, t;
  DataDir = 1;
  for (i=0; i<8; i++)
  {
    while(!Data);
    Delay_us(40);
    if(Data) num |= 1<<(7-i);
    while(Data);
  }
  return num;
}

void Interrupt() iv 0x0004 ics ICS_AUTO
{
  if(PIR1.TMR2IF)
  {
     TOUT = 1;
     T2CON.TMR2ON = 0; // stop timer
     PIR1.TMR2IF  = 0; // Clear TMR0 interrupt flag
  }
}


void main()
{
  // port initialization
  TRISB = 0b00000010;
  PORTB = 0;

  CMCON = 7;// comparator off
  ADCON1 = 0x07;// ADC off
  
  INTCON.GIE = 1;    //Enable global interrupt
  INTCON.PEIE = 1;   //Enable peripheral interrupt
  // Configure Timer2 module
  PIE1.TMR2IE = 1;  // Enable Timer2 interrupt
  T2CON = 0;        // Prescaler 1:1, and Timer2 is off initially
  PIR1.TMR2IF =0;   // Clear TMR INT Flag bit
  TMR2 = 0;
  
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);
  Lcd_Out(1,1,"DHT11 WITH");
  Lcd_Out(2,1,"PIC16F877A");
  Delay_ms(2000);
  Lcd_Cmd(_LCD_CLEAR);

  while(1)
  {

    unsigned short check;
    PIE1.TMR2IE = 1;  // Enable Timer2 interrupt
    ADCON1 = 0x07; // all digital selected
    StartSignal();
    check = CheckResponse();
    if (!check)
    {
       Lcd_Cmd(_LCD_CLEAR);
       Lcd_Out(1, 1, "No response");
       Lcd_Out(2, 1, "from the sensor");
    }
    else
    {
       RH_Byte1 = ReadByte();
       RH_Byte2 = ReadByte();
       T_Byte1 = ReadByte();
       T_Byte2 = ReadByte();
       CheckSum = ReadByte();
       // Check for error in Data reception
       if (CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF))
       {
          Lcd_Out(1,1,"HUMIDITY:");
          Lcd_Out(2,1,"TEMP:");
          
          message[0] = RH_Byte1/10 + 48;
          message[1] = RH_Byte1%10 + 48;
          message[3] = RH_Byte2%10 + 48;
          Lcd_Out(1,11, message);
          Lcd_Out(1,16,"%");
          
          message[0] = T_Byte1/10 + 48;
          message[1] = T_Byte1%10 + 48;
          message[3] = T_Byte2%10 + 48;
          Lcd_Out(2,11, message);
          Lcd_Chr_CP(223);
          Lcd_Out(2,16,"C");
          
          Delay_ms(2000);
       }
       else
       {
           Lcd_Cmd(_LCD_CLEAR);
           Lcd_Out(1, 1, "Checksum Error!");
           Lcd_Out(2, 1, "Trying Again...");
       }
    }
    PIE1.TMR2IE = 0;  // disable Timer2 interrupt

  }// while(1)
}// void

Code Explanation:

void StartSignal()
{
  DataDir = 0;     // Data port is output
  Data    = 0;
  Delay_ms(25);
  Data    = 1;
  Delay_us(30);
  DataDir = 1;     // Data port is input
}

To start communication, a pulse is required. This pulse of 30 microseconds dipped by 25ms before activates DHT11. Then this pin is configured as input to read reply from DHT11.

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

The first signal from DHT11 is a response signal of our first start signal. Here we used Timer2 to measure the signal width. If it is found, then we can declare that DHT11 is responding.

unsigned short ReadByte()
{
  unsigned short num = 0, t;
  DataDir = 1;
  for (i=0; i<8; i++)
  {
    while(!Data);
    Delay_us(40);
    if(Data) num |= 1<<(7-i);
    while(Data);
  }
  return num;
}

When the response signal is ok, then we have to read the data signals. We read 8bit data serially of 5 different parameters. The first one is RH_byte1, then RH_byte2. These are for humidity. Then T_byte1 and T_byte2. These are for temperature. And finally the checksum byte.

       RH_Byte1 = ReadByte();
       RH_Byte2 = ReadByte();
       T_Byte1 = ReadByte();
       T_Byte2 = ReadByte();
       CheckSum = ReadByte();

When CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF), then we can say it as a successful reading.

The rest of the coding is simple and I think there is no need to explain those. But if you need to know something, comment below.

Test result:

Test Result in Proteus Simulation

Conclusion:

DHT11 can be interfaced with other similar micro-controllers. You just need to understand the concept and apply that concept in another coding. Timing is very important for successful reading. Otherwise, you’ll get no response from the DHT11 sensor.

I hope this project was helpful to you. If you make one for yourself, it will be a great pleasure for me. Anywhere you need help, let me know. Please share this project and subscribe to my blog. Thank you.


MKDas

I'm Mithun K. Das; B.Sc. in EEE from KUET, Bangladesh. Blog: https://labprojectsbd.com. "First, electronics was my passion, then it was my education, and finally, electronics is now my profession." I run my own electronics lab, M's Lab (https://mlabsbd.com). Where I work with the creation of new products from ideas to something in real life. Besides this is my personal blog where I write for hobbyists and newcomers in the electronics arena. I also have a YouTube channel where I publish other helpful videos, you can find the link inside the articles. I always try to keep it simple so that it becomes easy to understand. I hope these will help them to learn electronics and apply the knowledge in their real life.

1 Comment

enrique · January 1, 2021 at 10:55 pm

excelente trabajo ,desde Colombia muchas gracias

Leave a Reply

Avatar placeholder

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