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 ⚠️

Working with electricity involves serious risk. Ensure you have the necessary skills and take proper safety precautions before attempting any electrical projects. Proceed at your own risk — the author assumes no responsibility for any damage, injury, or issues resulting from the use or misuse of the information provided.

Advertisements

All content on this website is original and protected by copyright. Please do not copy or reproduce content without permission. While most of the resources shared here are open-source and freely accessible for your learning and benefit, your respect for our intellectual effort is appreciated.

If you find our tutorials helpful, consider supporting us by purchasing related materials or sharing our work — it helps keep the content flowing.

Need help or have questions? Leave a comment below — the author is always happy to assist!

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.

Liked this article? Subscribe to our newsletter:

Loading

or,

Visit LabProjectsBD.com for more inspiring projects and tutorials.

Thank you!

Check this out: 5 coolest multimeters you can buy


MKDas

Mithun K. Das. B.Sc. in Electrical and Electronic Engineering (EEE) from KUET. Senior Embedded Systems Designer at a leading international company. Welcome to my personal blog! I share articles on various electronics topics, breaking them down into simple and easy-to-understand explanations, especially for beginners. My goal is to make learning electronics accessible and enjoyable for everyone. If you have any questions or need further assistance, feel free to reach out through the Contact Us page. Thank you for visiting, and happy learning!

3 Comments

enrique · 01/01/2021 at 10:55 pm

excelente trabajo ,desde Colombia muchas gracias

Anitha · 02/02/2023 at 9:09 pm

Can I get the code for the Timer and LCD?
Kindly expect a response.

    MKDas · 03/02/2023 at 12:05 pm

    send details in whatsapp.

Leave a Reply

Avatar placeholder

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