Sometime ago, I developed the code for interactions with the humidity sensor DHT11. Also, I had used the same code in one of my projects and I was not particularly happy with reliability of this sensor. That’s why I decided to try DHT22 in case if I would use it in some future project.
Starting from the datasheet as usual:
Way better than in DHT11, margins and resolution – everything.
Let’s try to check what the sensor gives us:
State = 1; State = 0; Humpin = 0; DelayUs(20); //Ждем около 20мс State = 1; DelayUs(40); //Ждем 40мкс
I did not get why there are a couple of first low pulses, supposedly should be just a single one and shorter, while here are two. Well, let me count from the end firstly:
0b00000001 0b10101101 0b00000001 0b00000101 0b10110100
1 173 1 5 180
The control sum 180 = 173 + 1 + 5 + 1 = ОК
Update: the problem was in the delay, I accidentally made 20us instead of 20ms, after the fix it as all OK.
Now the conversion by itself – I had got a good insight from one of readers, for a simplicity instead of two char bytes just think about a single int byte.
We are getting RH = 42.9%, T = 26.1 degrees
Looks like a truth, moving further.
I decided to make some changes in the previous code:
- The edge by which the uC works is changed to the falling one.
- An analysis of the data now moved outside of the interruption handler
The principle of work still is the same, so just showing a code right away:
#include <xc.h> #include <plib/usart.h> #include <plib/delays.h> #define _XTAL_FREQ 12000000 //The speed of your internal(or)external oscillator #define State TRISC0 #define HumPin RC0 #pragma config WDTEN = OFF, LVP = OFF, FOSC = HS unsigned char UARTConfig = 0; unsigned char baud = 0; char rxbyte; unsigned int DHTbyte[3]; volatile unsigned char IsrCount = 0; volatile unsigned int TickCount = 0; volatile static bit RHStatus = 0; volatile bit InteFlag = 0; volatile unsigned char tempTmr0[45]; bit CSStatus = 0; bit error = 0; void NumToUart(unsigned int Num); void InitTimer0(); void Delay1us(); //1us delay for 12MHz xtall void DelayUs(unsigned char Us); void DelayMs(unsigned int Ms); void CheckSumm(); void GetRHandTemp(); void DisplayHT(); void main() { ANSEL = 0; //Отключаем аналоговые буфера ANSELH = 0; TRISB7 = 0; //TX pin set as output TRISB5 = 1; //RX pin set as input TRISB6 = 1; //RX pin set as input State = 1; UARTConfig = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ; //прерывания выключены, асинхронный режим, 8 бит, высокоскоростной режим baud = 77; //Focs/(9600*16) - 1 OpenUSART(UARTConfig,baud); putsUSART( (char *) "Welcome to Diymicro.ru\r\n" ); putsUSART( (char *) " \r\nNow, press 1 button for start measurement \r\n" ); INTEDG0 = 0; GIE = 1; PEIE = 1; while(1) { while(!DataRdyUSART()); rxbyte=ReadUSART(); while(BusyUSART()); if (rxbyte == 49) { putsUSART( (char *) "Measuring has been started!\r\n" ); GetRHandTemp(); DisplayHT(); rxbyte = 0; } }//while(1) }//main() void interrupt isr() //Interrupt routine { if (INT0IF) { tempTmr0[IsrCount] = TMR0; IsrCount++; //InteFlag = 1; TMR0 = 0; INT0IF = 0; } //if (INTF) } //isr() void NumToUart(unsigned int Num) //Number to uart { unsigned int bignum = 10000; unsigned char numtemp = 5; if (!Num) { WriteUSART('0'); //Выталкиеваем все разряды - от старшего к младшему while(BusyUSART()); //Ждем пока освободится модуль иначе будут прострелы } else { while(numtemp>0) //Определяем сколько разрядов имеет наше число { if (Num/bignum) break; numtemp--; bignum = bignum / 10; } for (unsigned char i = numtemp; i>0; i--) { WriteUSART( (Num - (Num/(bignum*10))*bignum*10 )/bignum + '0'); //Выталкиеваем все разряды - от старшего к младшему while(BusyUSART()); //Ждем пока освободится модуль иначе будут прострелы bignum = bignum/10; } } } void InitTimer0() //Timer0 initialization, 8bit mode, prescaler = 4 { TMR0 = 0; T0CON = 0b11010001; } void Delay1us() //delay approx 1 us { Delay1TCY(); Delay1TCY(); Delay1TCY(); } void DelayUs(unsigned char Us) //delay for a given number of microseconds { for (unsigned char i = 0; i<Us; i++) Delay1us(); } void DelayMs(unsigned int Ms) //approx delay for a given number of miliseconds { for (unsigned int i=0; i<Ms; i++) Delay1KTCYx(3); } void CheckSumm() //Checksumm checking { unsigned char b1, b2, b3, b4; b1 = DHTbyte[0]>>8; b2 = DHTbyte[0]; b3 = DHTbyte[1]>>8; b4 = DHTbyte[1]; /*NumToUart(b1); putsUSART( (char *) "\r\n"); NumToUart(b2); putsUSART( (char *) "\r\n"); NumToUart(b3); putsUSART( (char *) "\r\n"); NumToUart(b4); putsUSART( (char *) "\r\n"); NumToUart(DHTbyte[2]);*/ if (DHTbyte[2] == (b1+b2+b3+b4)) CSStatus = 1; //CSStatus = 1 in case right checksumm and = 0 in case wrong else CSStatus = 0; } void GetRHandTemp() //Humidity and temperature getting procedure { INT0IE = 0; //RC0 interrupt on change disable DHTbyte[0] = 0; //clearing of working bytes DHTbyte[1] = 0; DHTbyte[2] = 0; State = 1; //measurement initialization State = 0; HumPin = 0; DelayMs(20); State = 1; HumPin = 1; DelayUs(40); State = 1; INTEDG0 = 0; INT0IE = 1; //RC0 interrupt on change enable IsrCount = 0; error = 0; InitTimer0(); while (IsrCount<41) { if (TMR0 > 254) //sesnor doesn't respond break; } INT0IE = 0; if (TMR0 > 254) error = 1; //error has been detected if (!error) { for (unsigned char i=1;i<17;i++) //Humidity byte { DHTbyte[0]<<=1; if (tempTmr0[i]>80) DHTbyte[0] |= 1; } for (unsigned char i=17;i<33;i++) //Temperature byte { DHTbyte[1]<<=1; if (tempTmr0[i]>80) DHTbyte[1] |= 1; } for (unsigned char i=33;i<41;i++) //CheckSumm byte { DHTbyte[2]<<=1; if (tempTmr0[i]>80) DHTbyte[2] |= 1; } CheckSumm(); //Checksumm checking } }//GetRHandTemp void DisplayHT() { if (!error) { putsUSART( (char *) "\r\nMeasuring procedure done!\r\n" ); putsUSART( (char *) "Humidity - " ); NumToUart(DHTbyte[0]/10); WriteUSART('.'); while(BusyUSART()); NumToUart(DHTbyte[0]-(DHTbyte[0]/10)*10); putsUSART( (char *) "\r\nTemperature - " ); NumToUart(DHTbyte[1]/10); WriteUSART('.'); while(BusyUSART()); NumToUart(DHTbyte[1]-(DHTbyte[1]/10)*10); putsUSART( (char *) "\r\nCheksumm is " ); if (CSStatus) putsUSART( (char *) "OK\r\n" ); else putsUSART( (char *) "wrong\r\n" ); } else putsUSART( (char *) "ERROR! Sensor is not responding\r\n" ); }
And the result:
The source code is here.