Anda di halaman 1dari 9

Medicin de temperatura y humedad con un

sensor DHT11
12 febrero, 2012

En muchas ocasiones puede sernos til la medida de la temperatura y la humedad relativas. Hay
muchos sensores en el mercado, pero el que usaremos hoy es el DHT11 de Sensirion, con salidas
digitales ya calibradas y a un coste bastante bajo.

Lectura de temperatura y humedad con DHT11

Para probarlo, usaremos un PIC16F628A y un LCD 162.


Acerca del sensor DHT11
El sensor viene en un encapsulado con 4 pines en lnea, y se alimenta en un rango entre 3.5V y
5.5V. Puede medir temperautras entre 0 y 50C con una precisin de 2C, y una humedad
relativa entre el 20% y el 95% con una precisin del 5%.
El sensor se comunica con el microcontrolador a travs del protocolo 1-wire, que implementaremos
en el firmware del PIC ya que no est integrado a nivel hardware.

Sensor DHT11

Protocolo 1-wire
El microcontrolador inicia la comunicacin configurando el pin como salida y enviando la seal de
Start. Esta seal consiste en establecer nivel bajo durante 18ms y nivel alto durante 20us-40us. A
continuacin ponemos el pin como entrada y el sensor responder estableciendo un nivel bajo de
80us y un nivel alto de 80us.
A continuacin el sensor enviar 5 bytes (40 bits) de format continua. El primer bit recibido de cada
byte ser el ms significativo.

Seal Start y respuesta

Los 5 bytes recibidos sern los siguientes:

Byte1: parte entera de humedad relativa


Byte2: parte decimal de humedad relativa

Byte3: parte entera de temperatura


Byte4: parte decimal de temperatura
Byte5: checksum

El sensor DHT11 no utiliza decimales, por lo que podemos ignorar la informacin de los bytes 2 y
4; nos quedaremos slo con los bytes 1 y 3.
El checksum se utiliza para confirmar que la informacin recibida es correcta, y se calcula sumando
los 4 bytes anteriores y quedndonos slo con los 8 bits menos significativos del resultado.
Cada uno de los bits se enva siguiendo esta estructura. Cuando el sensor va a enviar un bit,
siempre tira la lnea abajo durante 50us, y luego la levanta durante 26-28us para sealizar un 0, o
durante 70us si quiere enviar un 1.

Envo de bits 0 y 1

Secuencia completa del protocolo 1-wire

Cuando se han enviado todos los bits, el sensor baja la lnea durante 50us y luego la libera.
El protocolo 1-wire requiere de la existencia de una resistencia de pull-up para que cuando est
libre se mantenga a nivel alto.
Una vez terminada la transmisin, el sensor pasa al estado de bajo consumo de energa.
El circuito

El esquema es muy simple, ya que slo tiene el PIC 16F628A, el LCD y nuestro sensor. El PIC
est conectado a un resonador de 4MHz, lo que le permite trabajar con un ciclo de reloj de 1us, y
esto facilita la lectura de los tiempos de la trama 1-wire.

Esquema circuito

El montaje se ha realizado sobre una protoboard, aprovechando el LCD de una placa de prototipos
genrica.

Instalacin en Protoboard

Detalle del PIC y el sensor DHT11

Firmware
El firmware del micro est escrito en MikroC PRO, y como se puede comprobar a continuacin, la
lectura de las temporizaciones del 1-wire se realiza utilizando el Timer2 del micro. Est configurado
para que este TMR2 se incremente en una unidad cada 1us, por lo que los clculos se simplifican
bastante.

// LCD module connections


sbit
sbit
sbit
sbit
sbit
sbit
sbit
sbit
sbit
sbit
sbit
sbit

LCD_RS at RB2_bit;
LCD_EN at RB3_bit;
LCD_D4 at RB4_bit;
LCD_D5 at RB5_bit;
LCD_D6 at RB6_bit;
LCD_D7 at RB7_bit;
LCD_RS_Direction at
LCD_EN_Direction at
LCD_D4_Direction at
LCD_D5_Direction at
LCD_D6_Direction at
LCD_D7_Direction at

TRISB2_bit;
TRISB3_bit;
TRISB4_bit;
TRISB5_bit;
TRISB6_bit;
TRISB7_bit;

sbit Data at RA0_bit;


sbit DataDir at TRISA0_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
= 0;
Delay_ms(25);
//
Data
= 1;
Delay_us(30);
//
DataDir = 1;
//

Data port is output


Low for at least 18us
High for 20-40 us
Data port is input

}
unsigned short CheckResponse(){
TOUT = 0;
TMR2 = 0;
T2CON.TMR2ON = 1;
// Start TMR2 while waiting for sensor response
while(!Data && !TOUT); // If there's no response within 256us, the Timer2

overflows
if (TOUT) return 0;
// and exit
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; // Start TMR2 from 0 when a low to high data pulse
while(Data);
// is detected, and wait until it falls low again.
T2CON.TMR2ON = 0; // Stop the TMR2 when the data pulse falls low.
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;
TRISA = 0b00100001;
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, "Trying Again ...");
}
}
}while(1);
}

Es posible simplificar la rutina ReadByte si no queremos usar el mdulo Timer2. Esta siguiente
versin de dicha rutina funciona tambin. Cuando se lee el pin a nivel alto, el PIC espera 40s y
chequea la lnea de nuevo. Si est en estado alto, es un 1; en caso contrario es un 0.

unsigned short ReadByte(){


unsigned short num = 0, t;
DataDir = 1;

for (i=0; i<8; i++){


while(!Data);
Delay_us(40);
if(Data) num |= 1<<(7-i);
while(Data);
}
return num;
}

Anda mungkin juga menyukai