Saturday, October 17, 2015

DHT22 (AM2302) Digital Humidity and Temperature Sensor Proteus Simulation

Interfacing PIC Microcontroller With DHT22 (AM2302) Sensor

Like the DHT11, the DHT22 is a digital humidity and temperature sensor which has more benefits than DHT11 like: High precision and range.
If we want to understand this topic we have to read the DHT22 datasheet and see how this device works and its characteristics.
Note that the DHT22 is available only on Proteus version 8.1 or higher, version 8.0 or later will not work therefore you have to update your version.
From the datasheet:
1-wire bus is used for communication between MCU and DHT22, which means that the sensor communicates over only one-wire with the master device (microprocessor or microcontroller), by this wire the DHT22 sends/receives data to/from the master device.
Illustration of our 1-wire bus:
DATA=16 bits RH data+16 bits Temperature data+8 bits check-sum
Example: MCU has received 40 bits data from AM2302 as
0000 0010 1000 1100 0000 0001 0101 1111 1110 1110
16 bits RH data 16 bits T data check sum
Here we convert 16 bits RH data from binary system to decimal system,
0000 0010 1000 1100 → 652
Binary system Decimal system
RH=652/10=65.2%RH
Here we convert 16 bits T data from binary system to decimal system,
0000 0001 0101 1111 → 351
Binary system Decimal system
T=351/10=35.1℃
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℃
16 bits T data
Sum=0000 0010+1000 1100+0000 0001+0101 1111=1110 1110
Check-sum=the last 8 bits of Sum=1110 1110
When MCU send start signal, DHT22 change from standby-status to running-status. When MCU finishes sending the start signal, DHT22 will send response signal of 40-bit data that reflect the relative humidity and temperature to MCU. Without start signal from MCU, DHT22 will not give response signal to MCU. One start signal for one
response data from DHT22 that reflect the relative humidity and temperature. DHT22 will change to standby status when data collecting finished if it don't receive start signal from MCU again.

Interfacing PIC18F4550 with DHT22 (AM2302) Proteus simulation:
The picture below shows a Proteus circuit diagram of the simulation:
Internal oscillator is used at 8MHz and MCLR pin is disabled.
Interfacing PIC18F4550 with DHT22 using DHT22 mikroC library

 Interfacing PIC18F4550 with DHT22 mikroC code:

//Interfacing DHT22 with PIC18F4550
//Internal oscillator used @ 8MHz
//Written by: BENCHEROUDA Okba
//http://www.elecnote.blogspot.com
//electronnote@gmail.com
//Use at your own risk

// LCD module connections
 sbit LCD_RS at RB0_bit;
 sbit LCD_EN at RB1_bit;
 sbit LCD_D4 at RB2_bit;
 sbit LCD_D5 at RB3_bit;
 sbit LCD_D6 at RB4_bit;
 sbit LCD_D7 at RB5_bit;
 sbit LCD_RS_Direction at TRISB0_bit;
 sbit LCD_EN_Direction at TRISB1_bit;
 sbit LCD_D4_Direction at TRISB2_bit;
 sbit LCD_D5_Direction at TRISB3_bit;
 sbit LCD_D6_Direction at TRISB4_bit;
 sbit LCD_D7_Direction at TRISB5_bit;
 // End LCD module connections
 unsigned char  Check, T_byte1, T_byte2,
                RH_byte1, RH_byte2, Ch ;
 unsigned Temp, RH, Sum ;
 //////////////////////////////
 void StartSignal(){
 TRISD.F0 = 0;    //Configure RD0 as output
 PORTD.F0 = 0;    //RD0 sends 0 to the sensor
 delay_ms(18);
 PORTD.F0 = 1;    //RD0 sends 1 to the sensor
 delay_us(30);
 TRISD.F0 = 1;    //Configure RD0 as input
  }
 //////////////////////////////
 void CheckResponse(){
 Check = 0;
 delay_us(40);
 if (PORTD.F0 == 0){
 delay_us(80);
 if (PORTD.F0 == 1)   Check = 1;   delay_us(40);}
 }
 //////////////////////////////
 char ReadData(){
 char i, j;
 for(j = 0; j < 8; j++){
 while(!PORTD.F0); //Wait until PORTD.F0 goes HIGH
 delay_us(30);
 if(PORTD.F0 == 0)
       i&= ~(1<<(7 - j));  //Clear bit (7-b)
 else {i|= (1 << (7 - j));  //Set bit (7-b)
 while(PORTD.F0);}  //Wait until PORTD.F0 goes LOW
 }
 return i;
 }
 //////////////////////////////
 void main() {
 OSCCON =  0X70;       // Set internal oscillator at 8MHz
 ADCON1 = 0x0F;        // Configure AN pins as digital
 Lcd_Init();
 Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
 Lcd_Cmd(_LCD_CLEAR);             // clear LCD
 while(1){
  StartSignal();
  CheckResponse();
  if(Check == 1){
  RH_byte1 = ReadData();
  RH_byte2 = ReadData();
  T_byte1 = ReadData();
  T_byte2 = ReadData();
  Sum = ReadData();
  if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF)){
  Temp = T_byte1;
  Temp = (Temp << 8) | T_byte2;
  RH = RH_byte1;
  RH = (RH << 8) | RH_byte2;
  Lcd_Out(1, 6, "Temp:   . C");
  Lcd_Out(2, 2, "Humidity:   . %");
  if (Temp > 0X8000){
  Lcd_Out(1, 11, "-");
  Temp = Temp & 0X7FFF; }
  LCD_Chr(1, 12, 48 + ((Temp / 100) % 10));
  LCD_Chr(1, 13, 48 + ((Temp / 10) % 10));
  LCD_Chr(1, 15, 48 + (Temp % 10));
  LCD_Chr(2, 12, 48 + ((RH / 100) % 10));
  LCD_Chr(2, 13, 48 + ((RH / 10) % 10));
  LCD_Chr(2, 15, 48 + (RH % 10));
  }
  else{
  Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  Lcd_Out(1, 1, "Check sum error");}
  }
  else {
  Lcd_Out(1, 3, "No response");
  Lcd_Out(2, 1, "from the sensor");
  }
  delay_ms(1000);
  }
  }

Interfacing PIC18F4550 with DHT22 Proteus simulation video:


Interfacing PIC16F887 with DHT22 (AM2302) Proteus simulation:
For this microcontroller the internal oscillator is used at 8MHz and the MCLR pin is disabled.
Proteus circuit schematic is shown below:
Interfacing PIC16F887 with DHT22 AM2302 using DHT22 mikroC library

 Interfacing PIC16F887 with DHT22 MikroC code:

//Interfacing DHT22 with PIC16F887
//Internal oscillator used @ 8MHz
//Written by: BENCHEROUDA Okba
//http://www.elecnote.blogspot.com
//electronnote@gmail.com
//Use at your own risk

// LCD module connections
 sbit LCD_RS at RB0_bit;
 sbit LCD_EN at RB1_bit;
 sbit LCD_D4 at RB2_bit;
 sbit LCD_D5 at RB3_bit;
 sbit LCD_D6 at RB4_bit;
 sbit LCD_D7 at RB5_bit;
 sbit LCD_RS_Direction at TRISB0_bit;
 sbit LCD_EN_Direction at TRISB1_bit;
 sbit LCD_D4_Direction at TRISB2_bit;
 sbit LCD_D5_Direction at TRISB3_bit;
 sbit LCD_D6_Direction at TRISB4_bit;
 sbit LCD_D7_Direction at TRISB5_bit;
 // End LCD module connections
 unsigned char  Check, T_byte1, T_byte2,
                RH_byte1, RH_byte2, Ch ;
 unsigned Temp, RH, Sum ;
 //////////////////////////////
 void StartSignal(){
 TRISD.F0 = 0;    //Configure RD0 as output
 PORTD.F0 = 0;    //RD0 sends 0 to the sensor
 delay_ms(18);
 PORTD.F0 = 1;    //RD0 sends 1 to the sensor
 delay_us(30);
 TRISD.F0 = 1;    //Configure RD0 as input
  }
 //////////////////////////////
 void CheckResponse(){
 Check = 0;
 delay_us(40);
 if (PORTD.F0 == 0){
 delay_us(80);
 if (PORTD.F0 == 1)   Check = 1;   delay_us(40);}
 }
 //////////////////////////////
 char ReadData(){
 char i, j;
 for(j = 0; j < 8; j++){
 while(!PORTD.F0); //Wait until PORTD.F0 goes HIGH
 delay_us(30);
 if(PORTD.F0 == 0)
       i&= ~(1<<(7 - j));  //Clear bit (7-b)
 else {i|= (1 << (7 - j));  //Set bit (7-b)
 while(PORTD.F0);}  //Wait until PORTD.F0 goes LOW
 }
 return i;
 }
 //////////////////////////////
 void main() {
 OSCCON =  0X70;       // Set internal oscillator at 8MHz
 ANSEL = 0;           // Configure AN pins as digital
 ANSELH = 0;
 Lcd_Init();
 Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
 Lcd_Cmd(_LCD_CLEAR);             // clear LCD
 while(1){
  StartSignal();
  CheckResponse();
  if(Check == 1){
  RH_byte1 = ReadData();
  RH_byte2 = ReadData();
  T_byte1 = ReadData();
  T_byte2 = ReadData();
  Sum = ReadData();
  if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF)){
  Temp = T_byte1;
  Temp = (Temp << 8) | T_byte2;
  RH = RH_byte1;
  RH = (RH << 8) | RH_byte2;
  Lcd_Out(1, 6, "Temp:   . C");
  Lcd_Out(2, 2, "Humidity:   . %");
  if (Temp > 0X8000){
  Lcd_Out(1, 11, "-");
  Temp = Temp & 0X7FFF; }
  LCD_Chr(1, 12, 48 + ((Temp / 100) % 10));
  LCD_Chr(1, 13, 48 + ((Temp / 10) % 10));
  LCD_Chr(1, 15, 48 + (Temp % 10));
  LCD_Chr(2, 12, 48 + ((RH / 100) % 10));
  LCD_Chr(2, 13, 48 + ((RH / 10) % 10));
  LCD_Chr(2, 15, 48 + (RH % 10));
  }
  else{
  Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  Lcd_Out(1, 1, "Check sum error");}
  }
  else {
  Lcd_Out(1, 3, "No response");
  Lcd_Out(2, 1, "from the sensor");
  }
  delay_ms(1000);
  }
  }

Interfacing PIC16F887 with DHT22 Simulation Video:


Interfacing PIC16F877A with DHT22 (AM2302) Proteus simulation:
The following circuit diagram is for interfacing the DHT22 sensor with PIC16F877A:
Interfacing PIC16F877A with DHT22 (AM2302) using DHT22 mikroC library

 Interfacing PIC16F877A with DHT22 MikroC code: 

//Interfacing PIC16F877A with DHT22
//Crystal used @ 12MHz
//Written by: BENCHEROUDA Okba
//http://www.elecnote.blogspot.com
//electronnote@gmail.com
//Use at your own risk

// LCD module connections
 sbit LCD_RS at RB0_bit;
 sbit LCD_EN at RB1_bit;
 sbit LCD_D4 at RB2_bit;
 sbit LCD_D5 at RB3_bit;
 sbit LCD_D6 at RB4_bit;
 sbit LCD_D7 at RB5_bit;
 sbit LCD_RS_Direction at TRISB0_bit;
 sbit LCD_EN_Direction at TRISB1_bit;
 sbit LCD_D4_Direction at TRISB2_bit;
 sbit LCD_D5_Direction at TRISB3_bit;
 sbit LCD_D6_Direction at TRISB4_bit;
 sbit LCD_D7_Direction at TRISB5_bit;
 // End LCD module connections
 unsigned char  Check, T_byte1, T_byte2,
                RH_byte1, RH_byte2, Ch ;
 unsigned Temp, RH, Sum ;
 //////////////////////////////
 void StartSignal(){
 TRISD.F0 = 0;    //Configure RD0 as output
 PORTD.F0 = 0;    //RD0 sends 0 to the sensor
 delay_ms(18);
 PORTD.F0 = 1;    //RD0 sends 1 to the sensor
 delay_us(30);
 TRISD.F0 = 1;    //Configure RD0 as input
  }
 //////////////////////////////
 void CheckResponse(){
 Check = 0;
 delay_us(40);
 if (PORTD.F0 == 0){
 delay_us(80);
 if (PORTD.F0 == 1)   Check = 1;   delay_us(40);}
 }
 //////////////////////////////
 char ReadData(){
 char i, j;
 for(j = 0; j < 8; j++){
 while(!PORTD.F0); //Wait until PORTD.F0 goes HIGH
 delay_us(30);
 if(PORTD.F0 == 0)
       i&= ~(1<<(7 - j));  //Clear bit (7-b)
 else {i|= (1 << (7 - j));  //Set bit (7-b)
 while(PORTD.F0);}  //Wait until PORTD.F0 goes LOW
 }
 return i;
 }
 //////////////////////////////
 void main() {
 Lcd_Init();
 Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
 Lcd_Cmd(_LCD_CLEAR);             // clear LCD
 while(1){
  StartSignal();
  CheckResponse();
  if(Check == 1){
  RH_byte1 = ReadData();
  RH_byte2 = ReadData();
  T_byte1 = ReadData();
  T_byte2 = ReadData();
  Sum = ReadData();
  if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF)){
  Temp = T_byte1;
  Temp = (Temp << 8) | T_byte2;
  RH = RH_byte1;
  RH = (RH << 8) | RH_byte2;
  Lcd_Out(1, 6, "Temp:   . C");
  Lcd_Out(2, 2, "Humidity:   . %");
  if (Temp > 0X8000){
  Lcd_Out(1, 11, "-");
  Temp = Temp & 0X7FFF; }
  LCD_Chr(1, 12, 48 + ((Temp / 100) % 10));
  LCD_Chr(1, 13, 48 + ((Temp / 10) % 10));
  LCD_Chr(1, 15, 48 + (Temp % 10));
  LCD_Chr(2, 12, 48 + ((RH / 100) % 10));
  LCD_Chr(2, 13, 48 + ((RH / 10) % 10));
  LCD_Chr(2, 15, 48 + (RH % 10));
  }
  else{
  Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  Lcd_Out(1, 1, "Check sum error");}
  }
  else {
  Lcd_Out(1, 3, "No response");
  Lcd_Out(2, 1, "from the sensor");
  }
  delay_ms(1000);
  }
  }

Interfacing PIC16F877A with DHT22 Simulation Video:


DHT22 Proteus simulation files download:
DOWNLOAD