This post shows how to interface DHT22 (AM2302, RHT03 …) digital temperature and humidity sensor with PIC16F887 8-bit microcontroller where the values of temperature and relative humidity are displayed on 1602 LCD screen.
The compiler used in this example is Microchip MPLAB XC8 (MPLAB X IDE with MPLAB XC8 compiler).
Related Projects:
Interfacing LCD with PIC microcontroller | MPLAB Projects
Interfacing DHT11 sensor with PIC microcontroller | MPLAB Projects
Hardware Required:
- PIC16F887 microcontroller
- DHT22 sensor
- 1602 (16×2) LCD screen
- 4.7k ohm resistor
- 10k ohm variable resistor or potentiometer
- 330 ohm resistor
- 5V Power source
- Breadboard
- Jumper wires
Interfacing DHT22 sensor with PIC microcontroller circuit:
The following image shows project circuit schematic diagram.
(All grounded terminals are connected together)
The DHT22 sensor has 4 pins (from left to right): VCC (+5V), data pin, NC (not connected pin) and GND. The data pin is connected to pin RB0 of the PIC16F887 microcontroller. A pull-up resistor of 4.7k ohm is required for the data pin.
The 16×2 LCD screen is connected to the PIC16F887 microcontroller as follows:
RS —> RD0 pin
E —> RD1 pin
D4 —> RD2 pin
D5 —> RD3 pin
D6 —> RD4 pin
D7 —> RD5 pin
VSS, RW, D0, D1, D2, D3 and K are connected to circuit GND (ground)
VEE to the variable resistor (or potentiometer) output pin
VDD to +5V and A to +5V through 330 ohm resistor
VEE pin is used to control the contrast of the LCD. A (anode) and K (cathode) are the back light LED pins.
In this project the PIC16F887 microcontroller runs with its internal oscillator @ 8 MHz, MCLR pin is configured as an input pin.
Interfacing DHT22 sensor with PIC microcontroller C code:
The C code below is for MPLAB XC8 compiler, it was tested with version 2.00 installed on MPLAB X IDE version 5.05
To be able to compile the C code, a small LCD library for MPLAB XC8 compiler is required which can be downloaded from the following link:
MPLAB XC8 LCD Library
after the download, add the library file (LCD_Lib.c) to project folder.
Functions used in the code:
Start_Signal(): this function sends the start signal to the sensor, it sends a logic low for 25 ms and a logic high for 30 us.
Check_Response(): this function checks if there is a response from the sensor (after sending the start signal using the previous function), returns 1 (true) if ok and 0 (false) if error (for example a connection problem).
Read_Data(*dht_data): this function reads temperature and humidity data from the sensor (4 bytes), it also reads an other byte (5th byte) which is used as a checksum. This function returns 0 (false) if data read was ok and 1 (true) if there was a time out problem.
As shown in the circuit diagram above, the DHT22 data pin is connected to pin RB0, this connection is defined as follows:
1 2 3 | // DHT22 sensor connection (here data pin is connected to RB0) #define DHT22_PIN RB0 #define DHT22_PIN_DIR TRISB0 |
In this project I used Timer1 module to measure signal widths (logic 1 and logic 0 widths), it is configured to increment every 1 us (MCU speed is 8MHz (2 MIPS) and Timer1 prescaler is 1:2 —> Timer1 input clock frequency = 1MHz).
The microcontroller used in this example is PIC16F887, configuration words are:
1 2 | #pragma config CONFIG1 = 0x2CD4 #pragma config CONFIG2 = 0x0700 |
Where:
- In-Circuit Debugger disabled
- Low voltage programming disabled
- Fail-Safe Clock Monitor enabled
- Internal/External Switchover mode enabled
- Brown-out Reset (BOR) disabled
- Data memory code protection disabled
- Program memory code protection disabled
- RE3/MCLR pin function is digital input, MCLR internally tied to VDD
- Power-up Timer (PWRT) disabled
- Watchdog Timer (WDT) disabled
- INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN
- Flash Program Memory Self Write disabled
- Brown-out Reset set to 4.0V
Full MPLAB XC8 code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | /* * Interfacing DHT22 (AM2302) sensor with PIC16F887 * C Code for MPLAB XC8 compiler * Internal oscillator used @ 8MHz * This is a free software with NO WARRANTY * http://simple-circuit.com/ */ // set configuration words #pragma config CONFIG1 = 0x2CD4 #pragma config CONFIG2 = 0x0700 // DHT22 sensor connection (here data pin is connected to RB0) #define DHT22_PIN RB0 #define DHT22_PIN_DIR TRISB0 //LCD module connections #define LCD_RS RD0 #define LCD_EN RD1 #define LCD_D4 RD2 #define LCD_D5 RD3 #define LCD_D6 RD4 #define LCD_D7 RD5 #define LCD_RS_DIR TRISD0 #define LCD_EN_DIR TRISD1 #define LCD_D4_DIR TRISD2 #define LCD_D5_DIR TRISD3 #define LCD_D6_DIR TRISD4 #define LCD_D7_DIR TRISD5 //End LCD module connections #include <xc.h> #define _XTAL_FREQ 8000000 #include "LCD_Lib.c" // include LCD driver source file // variables declaration char Temperature[] = "Temp = 00.0 C "; char Humidity[] = "RH = 00.0 % "; unsigned char T_Byte1, T_Byte2, RH_Byte1, RH_Byte2, CheckSum ; unsigned int Temp, RH; // send start signal to the sensor void Start_Signal(void) { DHT22_PIN_DIR = 0; // configure DHT22_PIN as output DHT22_PIN = 0; // clear DHT22_PIN output (logic 0) __delay_ms(25); // wait 25 ms DHT22_PIN = 1; // set DHT22_PIN output (logic 1) __delay_us(30); // wait 30 us DHT22_PIN_DIR = 1; // configure DHT22_PIN as input } // Check sensor response __bit Check_Response() { TMR1H = 0; // reset Timer1 TMR1L = 0; TMR1ON = 1; // enable Timer1 module while(!DHT22_PIN && TMR1L < 100); // wait until DHT22_PIN becomes high (checking of 80µs low time response) if(TMR1L > 99) // if response time > 99µS ==> Response error return 0; // return 0 (Device has a problem with response) else { TMR1H = 0; // reset Timer1 TMR1L = 0; while(DHT22_PIN && TMR1L < 100); // wait until DHT22_PIN becomes low (checking of 80µs high time response) if(TMR1L > 99) // if response time > 99µS ==> Response error return 0; // return 0 (Device has a problem with response) else return 1; // return 1 (response OK) } } // Data read function __bit Read_Data(unsigned char* dht_data) { *dht_data = 0; for(char i = 0; i < 8; i++) { TMR1H = 0; // reset Timer1 TMR1L = 0; while(!DHT22_PIN) // wait until DHT22_PIN becomes high if(TMR1L > 100) { // if low time > 100 ==> Time out error (Normally it takes 50µs) return 1; } TMR1H = 0; // reset Timer1 TMR1L = 0; while(DHT22_PIN) // wait until DHT22_PIN becomes low if(TMR1L > 100) { // if high time > 100 ==> Time out error (Normally it takes 26-28µs for 0 and 70µs for 1) return 1; // return 1 (timeout error) } if(TMR1L > 50) // if high time > 50 ==> Sensor sent 1 *dht_data |= (1 << (7 - i)); // set bit (7 - i) } return 0; // return 0 (data read OK) } // main function void main(void) { OSCCON = 0X70; // set internal oscillator to 8MHz ANSELH = 0; // configure all PORTB pins as digital T1CON = 0x10; // set Timer1 clock source to internal with 1:2 prescaler (Timer1 clock = 1MHz) TMR1H = 0; // reset Timer1 TMR1L = 0; __delay_ms(1000); // wait 1 second LCD_Begin(); // initialize LCD module while(1) { Start_Signal(); // send start signal to the sensor if(Check_Response()) // check if there is a response from sensor (If OK start reading humidity and temperature data) { // read (and save) data from the DHT22 sensor and check time out errors if(Read_Data(&RH_Byte1) || Read_Data(&RH_Byte2) || Read_Data(&T_Byte1) || Read_Data(&T_Byte2) || Read_Data(&CheckSum)) { LCD_Cmd(LCD_CLEAR); // clear LCD LCD_Goto(5, 1); // go to column 5, row 2 LCD_Print("Time out!"); // display "Time out!" } else // if there is no time out error { if(CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF)) { // if there is no checksum error RH = RH_Byte1; RH = (RH << 8) | RH_Byte2; Temp = T_Byte1; Temp = (Temp << 8) | T_Byte2; if (Temp > 0X8000) { // if temperature < 0 Temperature[6] = '-'; // put minus sign '-' Temp = Temp & 0X7FFF; } else // otherwise (temperature > 0) Temperature[6] = ' '; // put space ' ' Temperature[7] = (Temp / 100) % 10 + '0'; Temperature[8] = (Temp / 10) % 10 + '0'; Temperature[10] = Temp % 10 + '0'; Temperature[11] = 223; // put degree symbol (°) if(RH == 1000) // if the relative humidity = 100.0 % Humidity[6] = 1 + '0'; // put 1 of hundreds else Humidity[6] = ' '; // put space ' ' Humidity[7] = (RH / 100) % 10 + '0'; Humidity[8] = (RH / 10) % 10 + '0'; Humidity[10] = RH % 10 + '0'; LCD_Goto(1, 1); // go to column 1, row 1 LCD_Print(Temperature); LCD_Goto(1, 2); // go to column 1, row 2 LCD_Print(Humidity); } // if there is a checksum error else { LCD_Cmd(LCD_CLEAR); // clear LCD LCD_Goto(1, 1); // go to column 1, row 1 LCD_Print("Checksum Error!"); } } } // if there is a response (from the sensor) problem else { LCD_Cmd(LCD_CLEAR); // clear LCD LCD_Goto(3, 1); // go to column 3, row 1 LCD_Print("No response"); LCD_Goto(1, 2); // go to column 1, row 2 LCD_Print("from the sensor"); } TMR1ON = 0; // disable Timer1 module __delay_ms(1000); // wait 1 second } } // End of code. |
Proteus simulation of the project should give a result similar to what’s shown in the following video (connections between the PIC16F887 and the 1602 LCD are not the same):
Discover more from Simple Circuit
Subscribe to get the latest posts sent to your email.