Interface do DHT11 com o PIC16F877A para medição de temperatura e umidade

Tempo de leitura: 9 minutes

A medição de temperatura e umidade geralmente é útil em muitas aplicações, como Automação residencial, Monitoramento do ambiente Estação meteorológica, etc. O sensor de temperatura mais popularmente usado ao lado LM35 é o DHT11, já construímos muitos Projetos DHT11 interfaciando-o Arduino, com o Raspberry Pi e muitos outros conselhos de desenvolvimento. Neste artigo, aprenderemos como fazer interface com isso DHT11 com PIC16F87A que é um microcontrolador PIC de 8 bits. Usaremos este microcontrolador para leia os valores de temperatura e umidade usando DHT11 e exibi-lo em um visor LCD. Se você é completamente novo com o uso de microcontroladores PIC, pode usar nossa série de tutoriais PIC aprenda a programar e usar o microcontrolador PIC, dito isso, vamos começar.

 

DHT11 – Especificação e Trabalho

O sensor DHT11 está disponível na forma de módulo ou na forma de sensor. Neste tutorial, estamos usando o sensor, a única diferença entre os dois é que, na forma do módulo, o sensor possui um capacitor de filtragem e um resistor de pull-up conectado ao pino de saída do sensor. Portanto, se você estiver usando o módulo, não precisará adicioná-lo externamente. O DHT11 na forma de sensor é mostrado abaixo.

O sensor DHT11 vem com uma caixa de cor azul ou branca. Dentro deste invólucro, temos dois componentes importantes que nos ajudam a sentir a umidade e a temperatura relativas. O primeiro componente é um par de eletrodos; a resistência elétrica entre esses dois eletrodos é decidida por um substrato de retenção de umidade. Portanto, a resistência medida é inversamente proporcional à umidade relativa do ambiente. Mais alto, a umidade relativa mais baixa será o valor da resistência e vice-versa.  Observe também que a umidade relativa é diferente da umidade real. A umidade relativa mede o teor de água no ar em relação à temperatura no ar.

O outro componente é um termistor NTC montado na superfície. O termo NTC significa coeficiente de temperatura negativo, para o aumento da temperatura o valor da resistência diminuirá. A saída do sensor é calibrada de fábrica e, portanto, como programador, não precisamos nos preocupar em calibrar o sensor. A saída do sensor dada por. Comunicação de 1 fio, vamos ver o pino e o diagrama de conexão deste sensor.

O produto está em um pacote de linha única de 4 pinos. O 1o pino é conectado ao VDD e o 4o pino é conectado ao GND. O segundo pino é o pino de dados, usado para fins de comunicação. Este pino de dados precisa de um resistor de pull-up de 5k. No entanto, outros levantam resistores como 4,7k a 10k também podem ser usados. O terceiro pino não está conectado a nada. Então é ignorado.

A folha de dados fornece especificações técnicas e informações de interface que podem ser vistas na tabela abaixo

A tabela acima está sendo exibida Faixa de medição de temperatura e umidade e precisão Ele pode medir a temperatura de 0 a 50 graus Celsius com uma precisão de +/- Celsius de 2 graus e umidade relativa de 20 a 90% RH com uma precisão de +/- 5% RH. A especificação de detalhes pode ser vista na tabela abaixo.

Comunicação com o sensor DHT11

Como mencionado anteriormente, para ler os dados DHT11 com PIC nós temos que usar PIC um fio Protocolo de comunicação. Os detalhes sobre como executar isso podem ser entendidos a partir do diagrama de interface do DHT 11 que pode ser encontrado em sua folha de dados, o mesmo é fornecido abaixo.

DHT11 precisa de um sinal de início do MCU para iniciar a comunicação. Portanto, toda vez que o MCU precisar enviar um sinal de partida ao sensor DHT11 para solicitar que ele envie os valores de temperatura e umidade. Após concluir o sinal de início, o DHT11 envia um sinal de resposta que inclui as informações de temperatura e umidade. A comunicação de dados é feita pelo protocolo de comunicação de dados de barramento único O comprimento total dos dados é de 40 bits e o sensor envia um bit de dados mais alto primeiro.

Devido ao resistor de tração, a linha de dados sempre permanece no nível VCC durante o modo inativo. O MCU precisa reduzir essa tensão de alta a baixa por um período mínimo de 18ms. Durante esse período, o sensor DHT11 detecta o sinal de partida e o microcontrolador aumenta a linha de dados para 20-40us. Esse período de 20 a 40us é chamado de período de espera em que o DHT11 começa com a resposta. Após esse período de espera, o DHT11 envia os dados para a unidade de microcontrolador.

Formato DHT11 Sensor DATA

Os dados consistem em partes decimais e integrais combinadas. O sensor segue o formato de dados abaixo

Dados RH integrais de 8 bits + dados RH decimais de 8 bits + dados T integrais de 8 bits + dados T decimais de 8 bits + soma de verificação de 8 bits.

Pode-se verificar os dados verificando o valor da soma de verificação com os dados recebidos. Isso pode ser feito porque, se tudo estiver adequado e se o sensor tiver transmitido dados adequados, a soma de verificação deve ser a soma de “Dados RH integrais de 8 bits + dados T decimais de RHdata + dados T integrais de 8 bits + dados T decimais de 8 bits”.

 

Componentes necessários

Para este projeto, abaixo as coisas são necessárias –

  1. Configuração de programação do microcontrolador PIC (8 bits).
  2. ProtoBoard
  3. Unidade de fonte de alimentação 5V 500mA.
  4. Resistor de 4,7k 2pcs
  5. Resistor de 1k
  6. PIC16F877A
  7. Cristal de 20mHz
  8. Capacitor 33pF 2 peças
  9. LCD de 16×2 caracteres
  10. Sensor DHT11
  11. Fios de jumper

Esquema

O diagrama de circuito para interface DHT11 com PIC16F877A é mostrado abaixo.

Nós usamos um LCD 16×2 para exibir os valores de temperatura e umidade que medimos no DHT11. O LCD é interface no modo de 4 fios e o sensor e o LCD são alimentados por uma fonte de alimentação externa de 5V. Usei uma placa de ensaio para fazer todas as conexões necessárias e usei um adaptador externo de 5V. Você também pode usar isso fonte de alimentação de placa ProtoBoard para alimentar sua placa com 5V.

Quando o circuito estiver pronto, basta fazer o upload do código fornecido na parte inferior desta página e podemos começar a ler a Temperatura e a Umidade, como mostrado abaixo. Se você quiser saber como o código foi escrito e como ele funciona, leia mais.

DHT11 com explicação do código PIC MPLABX

O código foi escrito usando o MPLABX IDE e compilado usando o compilador XC8, fornecido pelo próprio Microchip e pode ser baixado e usado gratuitamente. Consulte os tutoriais básicos para entender o básico da programação, apenas as três funções importantes necessárias para a comunicação com o sensor DHT11 são discutidas abaixo. As funções são

void dht11_init();
void find_response();
char read_dht11();

A primeira função é usada para o inicie o sinal com dht11 Como discutido anteriormente, toda comunicação com o DHT11 começa com um sinal de início, aqui a direção do pino é alterada primeiro para configurar o pino de dados como saída do microcontrolador. Em seguida, a linha de dados é puxada para baixo e continua aguardando os 18mS. Depois disso, novamente, a linha é elevada pelo microcontrolador e continua esperando por até 30us. Após esse tempo de espera, o pino de dados é definido como entrada para o microcontrolador para receber os dados.

void dht11_init() {
  DHT11_Data_Pin_Direction = 0; // Configurar RD0 como saída
  DHT11_Data_Pin = 0; // RD0 envia 0 para o sensor
  __delay_ms (18);
  DHT11_Data_Pin = 1; // RD0 envia 1 para o sensor
  __delay_us (30);
  DHT11_Data_Pin_Direction = 1; // Configurar RD0 como entrada
 }

A próxima função é usada para configurar um bit de verificação, dependendo do status do pino de dados. Está acostumado detectar a resposta do sensor DHT11.

void find_response() {
  Check_bit = 0;
  __delay_us (40);
  if (DHT11_Data_Pin == 0) {
    __delay_us (80);
    if (DHT11_Data_Pin == 1) {
       Check_bit = 1;
    }          
    __delay_us (50);
  }
}

Finalmente, a função de leitura dht11; aqui os dados são lidos em um formato de 8 bits, onde os dados são retornados usando a operação de troca de bits, dependendo do status do pino de dados.

char read_dht11() {
  char data, for_count;
  for(for_count = 0; for_count < 8; for_count++) {
        while(!DHT11_Data_Pin);
        __delay_us(30);
        if(DHT11_Data_Pin == 0){
          data&= ~(1<<(7 - for_count)); //Clear bit (7-b)
        }else{
          data|= (1 << (7 - for_count)); //Set bit (7-b)
          while(DHT11_Data_Pin);
        }
   }
   return data;
}

Depois disso, tudo é feito na função principal. Primeiro, a inicialização do sistema é feita onde o LCD é inicializado e a direção da porta dos pinos do LCD é definida para a saída. O aplicativo está sendo executado dentro da função principal

void main() {
 system_init();
 while(1){
            __delay_ms(800);
            dht11_init();
            find_response();
            if(Check_bit == 1){
            RH_byte_1 = read_dht11();
            RH_byte_2 = read_dht11();
            Temp_byte_1 = read_dht11();
            Temp_byte_2 = read_dht11();
            Summation = read_dht11();
            if(Summation == ((RH_byte_1+RH_byte_2+Temp_byte_1+Temp_byte_2) & 0XFF)){
            Humidity = Temp_byte_1;
            RH = RH_byte_1;                                
            lcd_com (0x80);                       
            lcd_puts("Temp: ");
            //lcd_puts("                 ");
            lcd_data(48 + ((Humidity / 10) % 10));
            lcd_data(48 + (Humidity % 10));
            lcd_data(0xDF);
            lcd_puts("C   ");
            lcd_com (0xC0);          
            lcd_puts("Humidity: ");
            //lcd_puts("                 ");
            lcd_data(48 + ((RH / 10) % 10));
            lcd_data(48 + (RH % 10));
            lcd_puts("%  ");
            }
            else{
            lcd_puts("Checksum error");
            }
            }
            else {
            clear_screen();
            lcd_com (0x80);
            lcd_puts("Error!!!");
            lcd_com (0xC0);
            lcd_puts("No Response.");
            }
            __delay_ms(1000);
 }
}

A comunicação com o sensor DHT11 é feita dentro do loop while onde o sinal de partida é enviado ao sensor. Depois disso, a função find_response é acionada. Se Check_bit for 1, a comunicação posterior será realizada, caso contrário, o LCD mostrará uma caixa de diálogo de erro.

Dependendo dos dados de 40 bits, o read_dht11 é chamado 5 vezes (5 vezes x 8 bits) e armazenado os dados de acordo com o formato de dados fornecido na ficha técnica. O status da soma de verificação também é verificado e, se forem encontrados erros, ele também notificará no LCD. Finalmente, os dados são convertidos e transmitidos para o LCD de 16×2 caracteres.

Espero que você tenha entendido o projeto e gostado de construir algo útil. Se você tiver alguma dúvida, deixe-a na seção de comentários abaixo ou use nossos fóruns para outras questões técnicas.

O código completo para esta medição de temperatura e umidade PIC pode ser baixado aqui.

 

Código

#include <xc.h>
#include <stdint.h>

#include "supporing_cfile/lcd.h"

#pragma config FOSC = HS        // Bits de seleção do oscilador (oscilador HS)
#pragma config WDTE = OFF       // Bit de habilitação do temporizador de watchdog (WDT desabilitado)
#pragma config PWRTE = ON       // Bit de ativação do temporizador de inicialização (PWRT habilitado)
#pragma config BOREN = ON       // Bit de habilitação de redefinição brown-out (BOR habilitado)
#pragma config LVP = OFF        // Bit de habilitação de programação serial em circuito de baixa tensão (fonte única) (RB3 é E/S digital, HV em MCLR deve ser usado para programação)
#pragma config CPD = OFF        // Bit de proteção de código de memória EEPROM de dados (proteção de código EEPROM de dados desativada)
#pragma config WRT = OFF        // Bits de habilitação de gravação de memória de programa flash (proteção contra gravação desativada; toda a memória de programa pode ser gravada pelo controle EECON)
#pragma config CP = OFF         // Bit de proteção de código de memória de programa flash (proteção de código desativada)

/*
 Definição relacionada ao fluxo do programa
 */
#define DHT11_Data_Pin   PORTDbits.RD5
#define DHT11_Data_Pin_Direction  TRISDbits.TRISD5
#define FIRST_LINE 0x80
#define SECOND_LINE 0xC0

#define _XTAL_FREQ 20000000 //20 Mhz

unsigned char Check_bit, Temp_byte_1, Temp_byte_2, RH_byte_1, RH_byte_2;
unsigned char Himudity, RH, Sumation ;

//Dht11 definição relacionada

void dht11_init();
void find_response();
char read_dht11();

// Definições relacionadas ao sistema

void system_init(void);
void introduction_screen(void);
void clear_screen(void);

void main() { 
 system_init();
 
 while(1){
     __delay_ms(800);
    dht11_init();
    find_response();
    if(Check_bit == 1){
        RH_byte_1 = read_dht11();
        RH_byte_2 = read_dht11();
        Temp_byte_1 = read_dht11();
        Temp_byte_2 = read_dht11();
        Sumation = read_dht11();
        if(Sumation == ((RH_byte_1+RH_byte_2+Temp_byte_1+Temp_byte_2) & 0XFF)){
            Himudity = Temp_byte_1;
            RH = RH_byte_1;                        
            lcd_com (0x80);                   
            lcd_puts("Temp: ");
            //lcd_puts("                ");
            lcd_data(48 + ((Himudity / 10) % 10));
            lcd_data(48 + (Himudity % 10));
            lcd_data(0xDF);
            lcd_puts("C   ");
            lcd_com (0xC0);            
            lcd_puts("Humidity: ");
             //lcd_puts("                ");
            lcd_data(48 + ((RH / 10) % 10));
            lcd_data(48 + (RH % 10));
            lcd_puts("%  ");
            }
        else{
            lcd_puts("Check sum error");
        }
    }
    else {
        clear_screen();
        lcd_com (0x80);
        lcd_puts("Error!!!");
        lcd_com (0xC0);
        lcd_puts("No Response.");
     }
    __delay_ms(1000);
 }
}

/*
 * Isso inicializará o sensor dht22.
 */

void dht11_init(){
 DHT11_Data_Pin_Direction= 0; //Configure RD0 como saída
 DHT11_Data_Pin = 0; //RD0 envia 0 para o sensor
 __delay_ms(18);
 DHT11_Data_Pin = 1; //RD0 envia 1 para o sensor
 __delay_us(30);
 DHT11_Data_Pin_Direction = 1; //Configure RD0 como entrada
 }

/*
 * Isso descobrirá que o sensor dht22 está funcionando ou não.
 */

 void find_response(){
 Check_bit = 0;
 __delay_us(40);
 if (DHT11_Data_Pin == 0){
 __delay_us(80);
 if (DHT11_Data_Pin == 1){
    Check_bit = 1;
 }     
 __delay_us(50);}
 }
 
 /*
 Esta função é para ler dht22.
 */
 
 char read_dht11(){
 char data, for_count;
 for(for_count = 0; for_count < 8; for_count++){
     while(!DHT11_Data_Pin); 
    __delay_us(30);
    if(DHT11_Data_Pin == 0){
        data&= ~(1<<(7 - for_count)); //Limpar bit (7-b)
    }
    else{
        data|= (1 << (7 - for_count)); //Definir bit (7-b)
        while(DHT11_Data_Pin);
    } //Espere até que PORTD.F0 fique BAIXO
    }
 return data;
 }
 
 void system_init(){
     TRISB = 0; // Pinos do LCD definidos para fora.
     lcd_init();
     introduction_screen();
     //dht11_init();
 }
 
 /*
 Esta função é para limpar a tela sem comando.
 */

void clear_screen(void){
    lcd_com(FIRST_LINE);
    lcd_puts("                ");
    lcd_com(SECOND_LINE);
    lcd_puts("                "); 
}

 
 /*
 Esta função é para jogar a introdução.
 */

void introduction_screen(void){
    lcd_com(FIRST_LINE);
    lcd_puts("Bem Vindo");
    lcd_com(SECOND_LINE);
    lcd_puts("CapSistema");
    __delay_ms(1000);
    __delay_ms(1000);
    clear_screen();
    lcd_com(FIRST_LINE);
    lcd_puts("DHT11 Sensor");
    lcd_com(SECOND_LINE);
    lcd_puts("com PIC16F877A");
    __delay_ms(1000);
    __delay_ms(1000);
}