Franzininho C0: Monitoramento de Temperatura e Umidade com Sensor DHT11

Este post faz parte da série Franzininho C0 com Arduino

Introdução

Neste tutorial, vamos utilizar a Franzininho C0 em conjunto com o sensor DHT11, que mede a temperatura e a umidade do ambiente, e um LED para sinalização, criando um sistema de monitoramento de temperatura e umidade. Este projeto será desenvolvido utilizando a IDE do Arduino.

Sensor DHT11

O sensor DHT11 é um dispositivo projetado para medir com precisão a temperatura e a umidade do ambiente, por meio de uma saída digital. Embutido em seu encapsulamento, há um microcontrolador de 8 bits, que contribui para a alta performance do módulo.

A principal característica do DHT11 é o elemento resistivo NTC, que é responsável pela medição precisa da temperatura. Com isso, o sensor demonstra uma resposta rápida às variações ambientais, além de possuir uma ótima capacidade de resistir a interferências externas.

O dispositivo opera em uma faixa de medição de temperatura de 0 a 50ºC e em uma faixa de umidade de 20 a 80%.

Figura 1 – Sensor DHT11

Materiais necessários 

  • Franzininho C0
  • Protoboard
  • Sensor DHT11
  • Jumpers

Pinout da Franzininho C0

Para definir os pinos utilizados, precisamos consultar o pinout da placa:

Acesse a documentação completa em:

https://docs.franzininho.com.br/docs/franzininho-c0/franzininho-c0-board

Circuito

Conecte a Franzininho C0 à protoboard. Em seguida, conecte os pinos GND e 3,3 V na protoboard para fornecer energia aos demais dispositivos.

Vamos começar com o sensor, que possui 4 pinos: VCC, Data, NC e GND. A identificação de cada pino é mostrada na Figura 2. 

Figura 2 – Pinos do DHT11

Siga os passos abaixo para conectá-lo à placa:

  1. Conecte o terminal VCC do sensor ao trilho de 3,3 V da protoboard.
  2. Conecte o terminal data do sensor a um dos pinos digitais da Franzininho C0 (por exemplo, PA5).
  3. O terminal NC não será utilizado
  4. Conecte o terminal GND do sensor ao trilho de GND da protoboard.
Figura 3 – Montagem do circuito.

Código

Para criar um sistema de monitoramento de temperatura e umidade usando a Franzininho C0, utilizaremos o código a seguir. Esse código é baseado no exemplo desenvolvido por Daniel Quadros em seu blog.

/* Baseado no teste do sensor DHT11 
 * Por: Daniel Quadros - 31/07/18 
 * https://dqsoft.blogspot.com/2018/08/sensor-de-umidade-e-temperatura-dht11.html
*/
static const int DHTPIN = PA5;  
static const int timeout = 200; 
static const int LED = PB6;

// Resposta do sensor  
typedef struct  
{  
  byte umidInt;  
  byte umidDec;  
  byte tempInt;  
  byte tempDec;  
  byte checksum;  
} RESPOSTA;  
  
// Iniciação  
void setup() {  
  pinMode (DHTPIN, INPUT);
  pinMode (LED, OUTPUT);

  // Conecta a UART aos pinos ligados à USB
  Serial.setRx(PA_10_R);
  Serial.setTx(PA_9_R);  
  Serial.begin (115200); 

}  
  
// Laço Principal  
void loop() {  
  RESPOSTA resp;  
  delay (5000);   // lê a cada 5 segundos  
  if (leDHT11(&resp)) { 
    Serial.print ("Temperatura ");  
    Serial.print (resp.tempInt);  
    Serial.print (",");  
    Serial.print (resp.tempDec);  
    Serial.print ("C Umidade ");  
    Serial.print (resp.umidInt);  
    Serial.print (",");  
    Serial.print (resp.umidDec);  
    Serial.println ("%");

    if (resp.tempInt>= 30 || resp.umidInt<= 60){
      digitalWrite(LED, HIGH);
    }
    else{
      digitalWrite(LED, LOW);
    }
  }  
  else {  
    Serial.println ("Falha na leitura");  
  }  
}  
  
// Efetua a leitura  
bool leDHT11 (RESPOSTA *pResp) {  
  byte *pDados = (byte *) pResp;  
  byte iByte, iBit;  
  unsigned long to;  
  
  // Solicita leitura  
  pinMode (DHTPIN, OUTPUT);  
  digitalWrite (DHTPIN, LOW);  
  delay (20);    
  digitalWrite (DHTPIN, LOW);  
  
  // Aguarda confirmar  
  pinMode (DHTPIN, INPUT);  
  to = micros() + timeout;  
  while (digitalRead(DHTPIN) == HIGH) {  
    if (micros() > to) {  
      return false;  
    }  
  }  
  while (digitalRead(DHTPIN) == LOW) {  
    if (micros() > to) {  
      return false;  
    }  
  }  
  while (digitalRead(DHTPIN) == HIGH) {  
    if (micros() > to) {  
      return false;  
    }  
  }  
  
  // Le os dados  
  iByte = iBit = 0;  
  while (iByte < 5) {  
    // pulso inicial  
    to = micros() + timeout;  
    while (digitalRead(DHTPIN) == LOW) {  
      if (micros() > to) {  
        return false;  
      }  
    }  
    // valor do bit  
    to = micros() + timeout;  
    while (digitalRead(DHTPIN) == HIGH) {  
      if (micros() > to) {  
        return false;  
      }  
    }  
    pDados[iByte] = pDados[iByte] << 1;  
    if (((micros() + timeout) - to) > 40) {  
      pDados[iByte] |= 1;  
    }  
    // passa para o próximo bit  
    if (++iBit > 7) {  
      iBit = 0;  
      iByte++;  
    }  
  }  
    
  // Confere o checksum  
  return (pDados[0]+pDados[1]+pDados[2]+pDados[3]) == pDados[4];  
}  

Obs.1: Antes da IDE iniciar o carregamento do programa, a Franzininho C0 deve executar o bootloader, caso contrário ocorrerá um erro.

Explicação do Código

Por conta das limitações de memória do microcontrolador STM32C0, da Franzininho C0, a leitura dos dados do sensor DHT11, que normalmente é feita com o auxílio de uma biblioteca, precisou ser implementada de forma mais enxuta. Por isso, utilizamos o código desenvolvido por Daniel Quadros.

Antes da função setup(), definimos as variáveis globais do programa. As variáveis DHTPIN e LED correspondem aos pinos da placa conectados ao sensor DHT11 e ao LED, respectivamente. A variável timeout define o período para a leitura dos dados.

static const int DHTPIN = PA5; 
static const int timeout = 200;
static const int LED = PB6;

Em seguida, temos a estrutura RESPOSTA, que contém os atributos para armazenar os valores de umidade (umidInt e umidDec) e temperatura (tempInt e tempDec) lidos pelo sensor, divididos em parte inteira e parte decimal. Há também o campo checksum, que será utilizado para verificar a integridade dos dados.

// Resposta do sensor 
typedef struct 
{ 
  byte umidInt; 
  byte umidDec; 
  byte tempInt; 
  byte tempDec; 
  byte checksum; 
} RESPOSTA;  

No setup(), inicializamos o pino do DHT11 (DHTPIN) como entrada e o pino do LED (LED) como saída. Também configuramos a comunicação serial definindo os pinos UART da Franzininho C0 e 115200 de baud rate, isso é feito para visualizar os dados no monitor serial do Arduino.

// Iniciação 
void setup() { 
  pinMode (DHTPIN, INPUT);
  pinMode (LED, OUTPUT);

  // Conecta a UART aos pinos ligados à USB
  Serial.setRx(PA_10_R);
  Serial.setTx(PA_9_R); 
  Serial.begin (115200);
} 

Na função leDHT11() é feita a leitura e armazenamento dos dados do sensor. A função tem como argumento pResp, um ponteiro para uma estrutura RESPOSTA, onde os dados lidos serão armazenados. O retorno da função é booleano, então ela irá retornar true se a leitura for bem-sucedida, ou false se houver um erro.

No início da função o ponteiro pDados, do tipo byte, aponta para a mesma área de memória de pResp. As variáveis do tipo byte iByte e iBit são definidas para uso posterior. Como também a variável to.

bool leDHT11 (RESPOSTA *pResp) {  
  byte *pDados = (byte *) pResp;  
  byte iByte, iBit;  
  unsigned long to;
...} 

O pino DHTPIN é alterado para funcionar como saída, isso é feito para que um sinal de início de comunicação ao sensor seja enviado. Assim, com digitalWrite(DHTPIN, LOW) definimos o DHTPIN como nível baixo, sinalizando ao sensor que o microcontrolador está pronto para receber dados. Um delay de 20 milissegundos é necessário para garantir que o sensor reconhecerá a solicitação de leitura.

{ ...
// Solicita leitura  
  pinMode (DHTPIN, OUTPUT);  
  digitalWrite (DHTPIN, LOW);  
  delay(20);
  digitalWrite (DHTPIN, LOW);
... }

Depois, o DHTPIN volta a ser configurado como entrada para começar a receber a resposta do sensor. A variável to é definida como o tempo atual em microssegundos (micros()) somado ao valor do timeout, definido no início do código como 200. 

O to é usado como limite de tempo para evitar que o código fique preso dentro do loop caso o sensor não responda.

O código então verifica três estados sequenciais:

  1. Espera pela mudança de nível alto para baixo: O primeiro while(digitalRead(DHTPIN) == HIGH) aguarda que o pino mude de estado alto (HIGH) para baixo (LOW). O sensor DHT11 deve responder com um pulso de nível baixo logo após a solicitação de leitura. Se o pino não mudar antes de atingir o tempo de timeout, a função retorna false, indicando uma falha na leitura.
  2. Espera pela mudança de nível baixo para alto: O segundo while(digitalRead(DHTPIN) == LOW) aguarda que o pino mude de estado baixo (LOW) para alto (HIGH). Isso indica que o sensor DHT11 está pronto para enviar os dados. Novamente, se o pino não mudar antes do timeout, a função retorna false.
  3. Espera pela mudança de nível alto para baixo: É o último bit de sincronização inicial. Se o pino não mudar antes do timeout, a função retorna false.
{ ... // Aguarda confirmar  
  pinMode (DHTPIN, INPUT);  
  to = micros() + timeout;  
  while (digitalRead(DHTPIN) == HIGH) {  
    if (micros() > to) {  
      return false;  
    }  
  }  
  while (digitalRead(DHTPIN) == LOW) {  
    if (micros() > to) {  
      return false;  
    }  
  }  
  while (digitalRead(DHTPIN) == HIGH) {  
    if (micros() > to) {  
      return false;  
    }  
  } 
... }

Finalmente, é feita a leitura dos dados. Primeiramente, iByte e iBit são iniciados com zero. O iByte é responsável por controlar qual byte da resposta está sendo lido, enquanto iBit controla qual bit do byte está sendo manipulado.

// Le os dados  
  iByte = iBit = 0;  

O laço while (iByte < 5) é feito para executar até que todos os 5 bytes (ou 40 bits) de dados do sensor tenham sido lidos. Novamente to é utilizado como limite de tempo.

Dentro desse loop temos while (digitalRead(DHTPIN) == LOW) que aguarda até que DHTPIN mude de nível lógico baixo para alto, sinalizando o início de cada bit.

while (iByte < 5) {  
    // pulso inicial  
    to = micros() + timeout;  
    while (digitalRead(DHTPIN) == LOW) {  
      if (micros() > to) {  
        return false;  
      }  
    }  

Em seguida, o laço while (digitalRead(DHTPIN) == HIGH) é usado para aguardar a transição do DHTPIN de nível lógico alto para baixo. Antes desse laço, o valor de to é atualizado com o objetivo de medir o tempo em que o pino permanece em HIGH, o que ajudará a determinar se o bit lido é 0 ou 1.

// valor do bit  
    to = micros() + timeout;  
    while (digitalRead(DHTPIN) == HIGH) {  
      if (micros() > to) {  
        return false;  
      }  
    } 

Na linha seguinte deslocamos todos os bits do byte atual (pDados[iByte]) uma posição à esquerda. Logo, se por exemplo, o byte atual fosse 00000001, após o deslocamento se tornaria 00000010. 

pDados[iByte] = pDados[iByte] << 1;  

Feito isso, com a estrutura condicional fica definido que:

  • Se o tempo que o pino permaneceu em HIGH foi  maior que 40 microssegundos, o bit é 1.
  • Caso contrário, o bit é 0. 

É preciso prestar atenção que aqui é feita uma operação OR bit a bit, com pDados[iByte] |= 1. Logo, se o tempo foi maior que 40 microssegundos, o código adiciona 1 na posição menos significativa do byte que está sendo construído.

if (((micros() + timeout) - to) > 40) {  
      pDados[iByte] |= 1;  
    }

Após ler cada bit, iBit é incrementado. Quando iBit chegar a 8 (indicando que todos os 8 bits do byte foram lidos), iByte é incrementado para passar ao próximo byte, e iBit é zerado.

// passa para o próximo bit  
    if (++iBit > 7) {  
      iBit = 0;  
      iByte++;  
    }  
  }  

Por último é feito uma verificação da integridade dos dados recebidos do sensor DHT11. Lembrando que pDados é do tipo de RESPOSTA, logo é formado pelos 5 bytes de dados:

  1. pDados[0]: Parte inteira da umidade.
  2. pDados[1]: Parte decimal da umidade.
  3. pDados[2]: Parte inteira da temperatura.
  4. pDados[3]: Parte decimal da temperatura.
  5. pDados[4]: Checksum (soma de verificação).
// Confere o checksum  
  return (pDados[0]+pDados[1]+pDados[2]+pDados[3]) == pDados[4];  
}

Por fim, na função loop(), declaramos uma variável resp do tipo RESPOSTA, que será utilizada para armazenar os dados do sensor. Esses dados serão lidos a cada 5 segundos.

void loop() {  
  RESPOSTA resp;  
  delay (5000);   // lê a cada 5 segundos  
...}

Em uma estrutura condicional, leDHT11(&resp) é chamada para ler os dados do sensor e armazená-los na variável resp. Se a leitura for bem-sucedida, a função retorna true, e o código dentro do if é executado. Se a leitura falhar, a função retorna false, e o bloco else é executado.

No bloco if, exibimos no monitor serial do Arduino os valores de temperatura e umidade, seguidos das unidades Celsius e porcentagem (%), respectivamente. Se o valor de temperatura ou umidade exceder o intervalo estabelecido, o LED do Franzininho C0 é acionado para alertar o usuário sobre um comportamento que necessita de atenção.

No bloco else, uma mensagem “Falha na leitura” é exibida no monitor serial para indicar o erro.

if (leDHT11(&resp)) { 
    Serial.print ("Temperatura ");  
    Serial.print (resp.tempInt);  
    Serial.print (",");  
    Serial.print (resp.tempDec);  
    Serial.print ("C Umidade ");  
    Serial.print (resp.umidInt);  
    Serial.print (",");  
    Serial.print (resp.umidDec);  
    Serial.println ("%");

    if (resp.tempInt>= 30 || resp.umidInt<= 60){
      digitalWrite(LED, HIGH);
    }
    else{
      digitalWrite(LED, LOW);
    }
  }  
  else {  
    Serial.println ("Falha na leitura");  
  } 

Ao executar o código, o monitor serial exibe a temperatura e a umidade detectadas pelo DHT11. Para alterar esses valores, você pode assoprar o sensor com ar quente, o que fará com que a temperatura aumente. No entanto, tome cuidado para não danificar o sensor.

Figura 4 – Resultado do teste do projeto.

Conclusão

Neste projeto, implementamos um sistema de monitoramento de temperatura e umidade utilizando a Franzininho C0, o LED integrado da placa, e um sensor DHT11. O sensor DHT11 é responsável por detectar as condições ambientais, enquanto o LED sinaliza quando determinados limites de temperatura e umidade são atingidos, proporcionando uma solução eficiente para monitoramento em tempo real.

Desafio

Neste desafio, você irá atualizar o projeto de monitoramento de temperatura e umidade, adicionando recursos visuais e sonoros para o operador. Esse aprimoramento incluirá a integração de um buzzer e um LED RGB, que mudará de cor conforme as condições ambientais. 

O funcionamento será o seguinte:

  • LED verde: indica que a temperatura e a umidade estão dentro dos parâmetros normais
  • LED laranja: sinaliza que os valores estão em um intervalo que requer atenção
  • LED vermelho: alerta para um valor crítico, acionando o buzzer como alerta sonoro.

Franzininho C0 com Arduino

Franzininho C0: Detecção de chuva usando Arduino
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Notícias » Franzininho C0: Monitoramento de Temperatura e Umidade com Sensor DHT11

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: