PIC16F877 temperature and humidity example

In this example we will read the temperature and humidity using a DHT11 sensor and display the readings on our LCD. We have linked to the datasheet at the bottom of the page, download it and then you can read a bit more technical information on this sensor.

These sensors whether standalone or in the form of breakouts are relatively inexpensive and for most projects they have an acceptable level of accuracy

I tried a couple of examples on the internet and none of them worked for me. Fortunately these all seemed to use Port A.0, changing this to PORTD.0 fixed the problems for me.

Schematic

I’ve omitted the external crystal and power connections to the PIC micro, concentrated mainly on the connections between the DHT11, LCD and the PIC micro.

PIC16F877 and DHT11 schematic
PIC16F877 and DHT11 schematic

Code

mikroC for PIC code again


sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;


sbit Data at RD0_bit;
sbit DataDir at TRISD0_bit;
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;

void StartSignal(){
DataDir = 0;     // Data port is output
Data    = 0;
delay_ms(18);
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);
TMR2 = 0;
T2CON.TMR2ON = 1;
while(Data);
T2CON.TMR2ON = 0;
if(TMR2 > 40) num |= 1<<(7-i);  // If time > 40us, Data is 1
}
return num;
}

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

void main() {
unsigned short check;
TRISB = 0b00000000;
PORTB = 0;
TRISD = 0b00000001;
CMCON = 7;
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);

do {
Delay_ms(1000);
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))
{
message1[7]  = T_Byte1/10 + 48;
message1[8]  = T_Byte1%10 + 48;
message1[10] = T_Byte2/10 + 48;
message2[7]  = RH_Byte1/10 + 48;
message2[8]  = RH_Byte1%10 + 48;
message2[10] = RH_Byte2/10 + 48;
message1[11] = 223;     // Degree symbol
Lcd_Cmd(_Lcd_Clear);
Lcd_Out(1, 1, message1);
Lcd_Out(2, 1, message2);
}

else{
Lcd_Cmd(_Lcd_Clear);
Lcd_Out(1, 1, "Checksum Error!");
Lcd_Out(2, 1, "Try Again.");
}
}

}while(1);
}


Links

DHT11 datasheet

1x DHT11 DHT-11 Digital Temperature and Humidity Temperature sensor