Если вы помните, некоторое время назад, я разрабатывал код для взаимодействия с датчиком влажности DHT11. Этот же код с датчиком был внедрен в один проектик, по результатам его работы могу сказать, что я не в восторге от его работы и решил потестить DHT22, ну и сделать задел для будущего проекта под PIC18.
Заглянем в даташит:
Значительно лучше чем в DHT11, как диапазоны так и разрешения по обоим параметрам.
Попытаемся посмотреть, что выдает датчик:
State = 1;
State = 0;
Humpin = 0;
DelayUs(20); //Ждем около 20мс
State = 1;
DelayUs(40); //Ждем 40мкс
И вот, что я получил:
Первые провалы мне совершенно пока непонятны, вроде как должен быть один и поменьше, а тут два лишних. В этот раз пока посчитаем с конца, получается:
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 градус
Вроде похоже на правду. Двигаемся дальше!
Я решил внести несколько изменений в версию прошлого кода:
- Выбор фронта для срабатывания прерываний. В прошлой версии я переключался на возрастающий фронт, а сейчас я внезапно понял, что по ниспадающему фронту работать даже проще.
- В прошлой версии обработка производилась на лету, значение таймера записывалось в переменную и тут же производился анализ и принималось решение бит 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" );
}
А вот результат работы:
Ну и исходники.
Wow, great forum topic.Really looking forward to read more. Shingleton
Thanks,
I’m going to translate blog into english, so I hope it’ll be more convinient for english speaking users.