PIC18 Lab. Experiment #2. DHT22.

Если вы помните, некоторое время назад, я разрабатывал код для взаимодействия с датчиком влажности DHT11. Этот же код с датчиком был внедрен в один проектик, по результатам его работы могу сказать, что я не в восторге от его работы и решил потестить DHT22, ну и сделать задел для будущего проекта под PIC18.

dht22

Заглянем в даташит:

Dht22_Datasheet

Значительно лучше чем в DHT11, как диапазоны так и разрешения по обоим параметрам.

Попытаемся посмотреть, что выдает датчик:

      State = 1;
      State = 0;
      Humpin = 0;
      DelayUs(20);         //Ждем около 20мс
      State = 1;
      DelayUs(40);         //Ждем 40мкс
      

И вот, что я получил:

dht22_output

Первые провалы мне совершенно пока непонятны, вроде как должен быть один и поменьше, а тут два лишних. В этот раз пока посчитаем с конца, получается:

0b00000001 0b10101101 0b00000001 0b00000101 0b10110100

1 173 1 5 180

Контрольная сумма 180 = 173 + 1 + 5 + 1 = ОК

Update: все встало на свои места, я вместо 20мс, сделал задержку на 20мкс, с нормальной задержкой все как и должно быть.

А теперь самое главное – конверсия, как некоторое время назад мне подсказал Сергей Евстратов, нужно просто представить два байта как один int.

Получается RH = 42.9%, T = 26.1 градус

Вроде похоже на правду. Двигаемся дальше!

Я решил внести несколько изменений в версию прошлого кода:

  1. Выбор фронта для срабатывания прерываний. В прошлой версии я переключался на возрастающий фронт, а сейчас я внезапно понял, что по ниспадающему фронту работать даже проще.
  2. В прошлой версии обработка производилась на лету, значение таймера записывалось в переменную и тут же производился анализ и принималось решение бит 0 или 1. Здесь же во время отклика датчика значения временных промежутков сливаются в массив и сохраняются, а непосредственно анализ происходит уже после этого.

Собственно принцип работы полностью такой же как и в прошлой версии, поэтому сразу код:

#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" );    
}

А вот результат работы:

DHT22_result

Ну и исходники.

PIC18 Lab. Experiment #2. DHT22.: 2 комментария

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.