Pic Lab, PIC18, Experiment #2, DHT22

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.

a DHT22 sensor

Starting from the datasheet as usual:

DHT22 datasheet screenshot

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:

  1. The edge by which the uC works is changed to the falling one.
  2. 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.

Leave a Reply

Your email address will not be published.