Módulo Cartão micro SD com NodeMCU - Construindo um datalogger
Módulo Cartão micro SD com NodeMCU - Construindo um datalogger
Neste tutorial, iremos desenvolver um datalogger bem simples, voltado ao armazenamento de informações de temperatura e umidade de um ambiente, coletados através de um sensor DHT11, usando um módulo leitor de cartão micro SD ou módulo cartão SD em conjunto com um NodeMCU.
Apesar de usarmos um NodeMCU, esse projeto pode ser facilmente adaptado para outras plataformas como ESP32 ou Arduino.
Você pode conhecer mais sobre o NodeMCU no tutorial: Conhecendo a Família ESP8266
[toc]
Armazenando informações
Ao desenvolver projetos voltados a coleta de informações, iremos precisar armazenar estas informações geradas para uma análise posterior. Se o volume de informações não for muito grande, podemos armazenar estes dados utilizando a própria memória não volátil que grande parte das plataformas já disponibilizam. Porém, dependendo do tempo que o nosso projeto esteja coletando dados, o volume de informação gerada, será tão grande, que não seremos capazes de armazenar todos estes dados apenas utilizando a memória nativa. Com isso, uma solução barata e eficiente, é o uso de cartões SD ou micro SD, que devido ao baixo custo e alta capacidade de armazenamento, permitem que o sistema armazene informações de forma estruturada e fácil.
Módulo micro SD
Para construir o nosso sistema de datalogger, iremos utilizar o módulo leitor cartão micro SD, que irá funcionar como ponte entre o microcontrolador e o cartão SD. A comunicação entre microcontrolador e módulo é feita através do protocolo SPI utilizando um total de 6 pinos, sendo dois para alimentação do circuito e os outros para comunicação.
Sensor de temperatura e umidade DHT11
O DHT11 é um sensor básico e de baixo custo que utiliza um termistor e um sensor capacitivo para medir a temperatura e a umidade do ar ambiente. Ele é bem simples de usar mas reque atenção com o tempo entre duas leituras consecutivas, uma vez que é necessário um intervalo de, no mínimo, 1 segundo entre uma leitura e outra.
Mãos à obra - Construindo a estrutura do nosso datalogger
Componentes utilizados
- 1x NodeMCU
- 1x Módulo micro sd
- 1x Cartão micro sd (Formatado em FAT 32)
- 1x Sensor temperatura e umidade DHT11
- Fios Jumper
Montando o projeto
Neste projeto, teremos dois módulos conectados ao nosso NodeMCU, com base nisso iremos utilizar a seguinte ordem de conexão dos fios:
A montagem final do sistema, deve estar semelhante a figura abaixo:
Veja só como ficou a montagem de todo o circuito:
Antes de ligar o seu circuito, verifique se todas as conexões foram feitas corretamente. Um curto circuito causado por uma ligação errada pode danificar todo o seu projeto.
Programando
- Bibliotecas
Neste tutorial iremos utilizar duas bibliotecas para construir o sistema. Uma dessas bibliotecas SD, já é nativa do arduino logo não precisamos realizar a sua instalação. Já a biblioteca utilizada pelo sensor DHT 11 será necessária a instalação, que pode ser feita da seguinte forma:
- Na ide do arduino, navegamos até a opção Sketch, selecionamos a opção Incluir biblioteca e navegamos até a opção Gerenciar Bibliotecas como mostra a figura abaixo:
- Ao selecionar a opção Gerenciar bibliotecas, será aberto um painel como mostra a figura a seguir:
- Nesta janela, iremos buscar pela biblioteca DHT sensor library by Adafruit, e realizar seu download/instalação
- Código utilizado
Agora que temos o nosso sistema montado, e as bibliotecas já instaladas, podemos partir para o código. Observem o código a seguir que utilizaremos como base para o nosso datalogger.
#include "DHT.h" // Biblioteca Adafruit para sensor de temperatura DHT11 #include <SPI.h> // Biblioteca de comunicação SPI Nativa #include <SD.h> // Biblioteca de comunicação com cartão SD Nativa #define DHTPIN 0 // Define para o pino D3 do nodeMCU -> D3 #define DHTTYPE DHT11 // DHT 11 que será utilizado para comunicação const int chipSelect = 4; // Constante que indica em qual pino está conectado o Chip Select do módulo de comunicação DHT dht(DHTPIN, DHTTYPE); // Objeto responsável pela comunicação microcontrolador/sensor File dataFile; // Objeto responsável por escrever/Ler do cartão SD bool cartaoOk = true; void setup() { Serial.begin(9600); // Inicialização da porta de comunicação Serial dht.begin(); // Inicialização do objeto de comunicação com sensor // Se não for possível se comunicar com o cartão SD o código não deve prosseguir if (!SD.begin(chipSelect)) { Serial.println("Erro na leitura do arquivo não existe um cartão SD ou o módulo está conectado corretamente ?"); cartaoOk = false; return; } } void loop() { // Caso o cartão esteja ok é criado um arquivo no cartão SD com o nome datalog.csv em modo de escrita if (cartaoOk){ dataFile = SD.open("datalog.csv", FILE_WRITE); Serial.println("Cartão SD Inicializado para escrita :D "); } //Limpando Variáveis String leitura = ""; // Limpo campo contendo string que será armazenada em arquivo CSV float temperatura = 0 ; // Limpo variável de temperatura a cada nova leitura float umidade = 0; // Limpo variável de umidade a cada nova leitura //Leitura do sensor temperatura = dht.readTemperature(); // Função que realiza a leitura da temperatura do sensor dht11 umidade = dht.readHumidity(); // Função que realiza a leitura da umidade do sensor dht11 // Caso os valores lidos do sensor não sejam válidos executamos as seguintes linhas if (isnan(temperatura) || isnan(umidade)){ Serial.println ("Falha na leitura do sensor"); // Informar ao usuário que houve uma falha na leitura do sensor delay(1500); // Aguardamos 1,5 segundos return ; // Retornamos a função para o seu ponto inicial } // Se tudo estiver ok, escrevemos os dados a serem armazenados em uma String leitura = String(millis()) + ";" + String(temperatura) + ";" + String(umidade) + ";"; // Se o arquivo estiver realmente aberto para leitura executamos as seguintes linhas de código if (dataFile) { Serial.println(leitura); // Mostramos no monitor a linha que será escrita dataFile.println(leitura); // Escrevemos no arquivos e pulamos uma linha dataFile.close(); // Fechamos o arquivo } delay(1500); // Aguardamos 1,5 segundos para executar o loop novamente }
Colocando pra funcionar
Se tudo estiver montado corretamente, o nosso sistema já deve estar funcionando e coletando informações sobre a temperatura e umidade do ambiente. Uma coisa interessante, é que o arquivo construído está no formato CSV, então podemos abrir ele utilizando o excel, ou o software editor de planilhas de sua preferência.
Entendendo a Fundo
Software
- Incluindo bibliotecas necessárias
Inicialmente, adicionamos as bibliotecas que iremos utilizar para comunicação com o módulo DHT11 e o módulo micro SD. Todas elas são essenciais para que a comunicação com os dispositivos possa ser feita de forma transparente. Como a biblioteca SD e SPI já são nativas do arduino não é necessária a sua instalação. Porém a biblioteca do sensor dht deveremos instalar como mostrado anteriormente.
#include "DHT.h" // Biblioteca do sensor DHT 11 da Adafruit #include <SPI.h> // Biblioteca de comunicação SPI Nativa #include <SD.h> // Biblioteca de comunicação com cartão SD Nativa
Existem diversas implementações da biblioteca DHT, utilizei esta em especial por achar mais simples o seu funcionamento. Porém fica a critério do usuário :)
- Criando parâmetros de configuração e objetos de comunicação
Inicialmente iremos criar dois parâmetros para configurar os pinos onde estão conectados o sensor DHT11 e o módulo micro sd. Neste caso o sensor dht11 está conectado ao pino 0 e o pino Chip Select está conectado ao pino 4.
#define DHTPIN 0 // Define para o pino D3 do nodeMCU -> D3 #define DHTTYPE DHT11 // DHT 11 que será utilizado para comunicação const int chipSelect = 4; // Constante que indica em qual pino está conectado o Chip Select do módulo de comunicação
Logo em seguida, iremos criar dois objetos pelos quais iremos nos comunicar com o módulo dht11 e o módulo micro SD. Também criamos uma variável do tipo bool, responsável por informar se a comunicação com o cartão SD está funcionando ou não.
DHT dht(DHTPIN, DHTTYPE); // Objeto utilizado para comunicação entre sensor e microcontrolador File dataFile; // Objeto responsável por escrever/Ler do cartão SD bool cartaoOk = true;
O objeto dht, tem como objetivo realizar a comunicação entre o microcontrolador e o sensor de temperatura/umidade. Ele recebe como parâmetros em seu método construtor, o pino com o qual está conectado ao microcontrolador e o tipo de sensor DHT que está sendo utilizado (neste caso o dht11).
- Função setup
A função setup, será utilizara para inicializarmos a comunicação com o cartão micro SD e a comunicação serial (caso você queira debugar o que está acontecendo no microcontrolador no momento). Com base nisso, este código executa o seguinte fluxograma
- Inicializamos a comunicação serial na taxa de comunicação padrão
- Inicializamos o objeto dht para comunicação microcontrolador/sensor
- Tentamos inicializar a comunicação com o cartão sd
- Se estiver tudo ok, a comunicação é inicializada e a escrita pode começar
- Caso o cartão não esteja presente ou exista alguma conexão errada, o sistema irá escrever na serial que houve um erro na comunicação com o cartão SD e a variável cartaoOk é marcada como falso
void setup() { Serial.begin(9600); // Inicialização da porta de comunicação Serial dht.begin(); // Inicialização do objeto de comunicação com sensor // Se não for possível se comunicar com o cartão SD o código não deve prosseguir if (!SD.begin(chipSelect)) { Serial.println("Erro na leitura do arquivo não existe um cartão SD ou o módulo está conectado corretamente ?"); cartaoOk = false; return; } }
- Condição inicial ( É possível escrever no arquivo ? )
Este trecho de código, será utilizado para identificar se é possível escrever no arquivo ou não. Caso seja possível iremos abrir o arquivo para escrita na linha 2 com o comando SD.open("datalog.csv", FILE_WRITE). Caso não seja possível realizar a escrita no arquivo o código irá pular esta condição
// Caso o cartão esteja ok é criado um arquivo no cartão SD com o nome datalog.csv em modo de escrita if (cartaoOk){ dataFile = SD.open("datalog.csv", FILE_WRITE); Serial.println("Cartão SD Inicializado para escrita :D "); }
- Variáveis de armazenamento
A leitura dos dados é feita a cada intervalo de 1,5 segundos, e a cada leitura realizada precisamos limpar a leitura feita anteriormente, para isso dentro da função loop do código adicionamos o trecho de código que será responsável por limpar as variáveis a cada leitura realizada.
//Limpando Variáveis String leitura = ""; float temperature = 0; float humidity = 0;
- Leitura da temperatura
Neste bloco de código, iremos realizar a leitura da temperatura utilizando o sensor, o processo é bem simples, realizamos a leitura utilizando a função, readTemperature(). Que irá nos retornar um valor válido, ou inválido caso ocorra algum problema na comunicação com o sensor
temperatura = dht.readTemperature(); // Função que realiza a leitura da temperatura do sensor dht11
- Leitura da umidade
O processo de leitura da umidade será feito de forma semelhante ao que foi feito na leitura da temperatura. a única mudança será no método utilizado, que no caso será readHumidity();
umidade = dht.readHumidity(); // Função que realiza a leitura da umidade do sensor dht11
- Validando a leitura dos dados
Já com os dados de temperatura e umidade lidos, iremos agora validar se estes dados são válidos ou não. Para isso, iremos utilizar o método isnan(), ou is not a number. Esta função, tem como objetivo verificar se o valor contido dentro de uma variável é realmente um número ou não. Como a função readTemperature() e readHumidity(), apenas retornam números válidos se a leitura for feita com sucesso, podemos considerar que a leitura será válida apenas quando as variáveis temperatura e umidade forem valores reais. Com base nisso, este trecho de código verifica se as variáveis lidas são realmente números válidos, caso não sejam todo o código dentro do if será executado.
// Caso os valores lidos do sensor não sejam válidos executamos as seguintes linhas if (isnan(temperatura) || isnan(umidade)){ Serial.println ("Falha na leitura do sensor"); // Informar ao usuário que houve uma falha na leitura do sensor delay(1500); // Aguardamos 1,5 segundos return ; // Retornamos a função para o seu ponto inicial }
- String para gravação
Após uma leitura ser feita com sucesso, iremos prosseguir para o processo de estruturação dos dados a serem armazenados no arquivo .csv, para isso iremos utilizar o seguinte comando:
// Se tudo estiver ok, escrevemos os dados a serem armazenados em uma String leitura = String(millis()) + ";" + String(temperatura) + ";" + String(umidade) + ";";
Com este comando, estamos basicamente criando uma String que irá armazenar todas as informações que queremos armazenar em nosso arquivo csv. O ";" que está sendo utilizado como separador será compreendido pela aplicação de tabelas utilizada como uma nova posição na tabela, ou seja estamos separando o tempo, a temperatura e a umidade em células diferentes.
- Gravando dados em arquivo
Por fim, mas não menos importante, devemos gravar os dados gerados em nosso cartão micro sd. Para isso iremos antes verificar se está tudo ok com o arquivo ( utilizando aquele flag que criamos anteriormente)
// Se o arquivo estiver realmente aberto para leitura executamos as seguintes linhas de código if (dataFile) { Serial.println(leitura); // Mostramos no monitor a linha que será escrita dataFile.println(leitura); // Escrevemos no arquivos e pulamos uma linha dataFile.close(); // Fechamos o arquivo }
Se estiver tudo ok, iremos gravar a nossa String criada utilizando o comando
dataFile.println(leitura); // Escrevemos no arquivos e pulamos uma linha
e em seguida fechamos o arquivo com:
dataFile.close(); // Fechamos o arquivo
Por fim, aguardamos o nosso intervalo de 1,5 segundos para recomeçar todo o processo novamente, e para isso utilizando o comando
delay(1500);
Desafio
Neste tutorial, utilizamos o tempo de funcionamento do microcontrolador para contabilizar o tempo onde foi feita a leitura das variáveis de temperatura e umidade. Uma proposta que seria bem interessante e usual, seria utilizar um relógio de tempo real, ou até mesmo o protocolo NTP para obter o horário real da leitura. Como desafio, proponho a modificação deste código para que ao invés do tempo do microcontrolador ele grave com a data e hora real em que foi feita a leitura. Como base para este desafio, vocês podem utilizar os tutoriais já apresentados aqui no blog como:
Considerações finais
Este tutorial, teve como objetivo mostrar a estrutura de um datalogger bem simplificado, onde utilizamos sensores para obter dados do ambiente e um módulo para armazenar estes dados de forma transparente para o desenvolvedor. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
DHT11 e DHT22 | Sensor de umidade e Temperatura com Arduino
DHT11 e DHT22, Sensor de umidade e Temperatura com Arduino
Umidade e temperatura são duas grandezas que estão muito relacionadas quando o assunto é climatização. Nesse tutorial você aprenderá a medir essas duas grandezas através do sensor de umidade e temperatura DHT11 ou o DHT22 em conjunto com um Arduino.
[toc]
Sensores de umidade e temperatura DHT11 e DHT22
O sensor DHT11 e o sensor DHT22 são sensores básicos e de baixo custo que utilizam um termistor e um sensor capacitivo para medir a temperatura e a umidade do ar ambiente.
Esses sensores são bastante simples de usar, mas requer cuidado com o tempo entre duas leituras consecutivas, uma vez que é necessário um intervalo de, no mínimo, 1 segundo entre uma leitura e outra.
Existem diferentes versões do DHT, similares na aparência e na pinagem, porém com características diferentes. As características do DHT11 e DHT22, dois modelos populares desse sensor, são:
Sensor DHT11
- Muito baixo custo
- Tensão de alimentação de 3V a 5V
- 2.5mA de corrente máxima durante a conversão
- Bom para medir umidade entre 20% e 80%, com 5% de precisão
- Bom para medir temperaturas entre 0 e 50°C, com ±2°C de precisão
- Taxa de amostragem de até 1Hz (1 leitura por segundo)
- Dimensões: 15.5mm x 12mm x 5.5mm
- 4 pinos com 0.1" de espaçamento entre eles
Sensor DHT22
- Baixo custo
- Tensão de alimentação de 3V a 5V
- 2.5mA de corrente máxima durante a conversão
- Bom para medir umidade entre 0% e 100%, com 2% a 5% de precisão
- Bom para medir temperaturas entre -40 e 125°C, com ±0,5°C de precisão
- Taxa de amostragem de até 0,5Hz (2 leituras por segundo)
- Dimensões: 15.1mm x 25mm x 7.7mm
- 4 pinos com 0.1" de espaçamento entre eles
Como pode ser observado, o DHT22 é um pouco mais preciso e trabalha em uma faixa um pouco maior de temperatura e umidade. Porém, ambos utilizam apenas um pino digital e são relativamente lentos, visto que é necessário um intervalo de tempo relativamente grande entre cada leitura.
Incluindo Bibliotecas
Uma grande vantagem das placas Arduino é a grande diversidade de bibliotecas disponíveis que podem ser usadas em seu programa. Isso faz com o trabalho pesado em programação seja abstraído e resumido em simples comandos.
Com isso, o desenvolvedor não precisa de conhecimento muito aprofundado em programação, podendo gastar menos tempo nisso, resultando em mais tempo para trabalhar com empenho na estratégia de controle.
A seguir, iremos aprender como adicionar uma biblioteca em sua IDE. Esse mesmo procedimento será usado para outros sensores ou módulos.
Incluindo a biblioteca DHT
Para trabalhar de forma fácil com o DHT, podemos baixar uma biblioteca para ele no GitHub do Rob Tillaart (https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib).
Há mais de uma forma de incluir bibliotecas no seu programa, a principal é:
Instalar a biblioteca pelo IDE do Arduino
Esse é o método mais fácil. Primeiramente, faça o download dos arquivos da biblioteca compactados no formato zip. Geralmente as bibliotecas já são distribuídas compactadas, porém às vezes é necessário fazer o download dos arquivos separadamente e compactá-los à parte. Em seguida, basta abrir o IDE e ir em "Sketch -> Incluir Biblioteca -> Adicionar biblioteca .ZIP":
Na janela que abrir, selecione a biblioteca a ser adicionada:
Com isso, a nova biblioteca foi instalada. Para utilizá-la, basta ir em "Sketch -> Incluir Biblioteca" e selecionar a biblioteca desejada:
Observe que o IDE adicionou no início do seu código a linha incluindo a biblioteca no seu programa.:
#include <dht.h>
Outras opções:
Instalar manualmente a biblioteca
Para instalar manualmente uma biblioteca, feche o IDE do Arduino e em seguida descompacte os arquivos da biblioteca. Se os arquivos .cpp e .h não estiverem dentro de uma pasta, crie uma e mova os arquivos para lá. Em seguida, basta mover a pasta para o local:
Windows: "Meus documentos\Arduino\libraries"
Mac: "Documents/Arduino/libraries"
Depois desse processo, a biblioteca estará disponível em "Sketch -> Incluir Biblioteca" na próxima vez que o IDE for aberto.
Incluir a biblioteca sem instalá-la
É possível também utilizar a biblioteca sem instalá-la no IDE do Arduino. Para isso, basta descompactar a biblioteca e colocar os arquivos .h e .cpp no mesmo diretório do programa, incluindo no início do mesmo a linha:
#include "nome_da_biblioteca.h"
Mãos à obra – Usando o Sensor de umidade e temperatura DHT11 com Arduino
Componentes necessários
- DHT11 ou DHT22
- Fios Jumper’s
- Protoboard
- Arduino Uno ou similar
Montando o projeto
Agora vamos conectar os componentes do projeto. Para isso, desligue o cabo USB de seu Arduino e monte seu circuito conforme a figura a seguir.
Conectando o Arduino ao computador
Conecte seu Arduino ao computador e abra a IDE Arduino.
Antes de carregar um programa, você precisa selecionar qual porta você deseja usar para fazer carregar o programa no Arduino (upload). Dentro do Arduino IDE, clique no menu Ferramentas (tools) e abra o submenu Porta(Port). Clique na porta que seu Arduino está conectado, tal como COM3 ou COM4. Geralmente aparece o nome da placa Arduino : “COM3 (Arduino/Genuino Uno)”.
Você também precisa garantir que o tipo de placa apropriado está selecionado em Ferramentas(Tools) no submenu Placa (Board).
Programando
Crie um programa (sketch) e salve com o nome de “programa_dht11”.
Com o seu programa salvo, escreva nele o código conforme escrito abaixo.
#include <dht.h> // Inclui a biblioteca no seu código dht DHT; // Cria um objeto da classe dht uint32_t timer = 0; void setup() { Serial.begin(9600); // Inicializa serial com taxa de transmissão de 9600 bauds } void loop() { // Executa 1 vez a cada 2 segundos if(millis() - timer>= 2000) { DHT.read11(A1); // chama método de leitura da classe dht, // com o pino de transmissão de dados ligado no pino A1 // Exibe na serial o valor de umidade Serial.print(DHT.humidity); Serial.println(" %"); // Exibe na serial o valor da temperatura Serial.print(DHT.temperature); Serial.println(" Celsius"); timer = millis(); // Atualiza a referência } }
Após escrever o código, clique em Carregar (Upload) para que o programa seja transferido para seu Arduino.
Colocando para funcionar
Caso tenha ocorrido tudo conforme esperado, poderemos fazer a leitura da temperatura através do monitor serial. Abra o monitor serial para verificar o que está sendo lido na entrada A0.
Entendendo a fundo
Entendendo o Software
millis()
Retorna o número de milissegundos desde a placa Arduino começou a funcionar com programa atual. Este número irá saturar (voltar para zero), após, aproximadamente, 50 dias.
timer = millis(); //Atualiza a referência
Veja que usamos o millis como nossa referência de tempo. Toda vez que a diferença entre o millis e o timer for de 2000 milissegundos, entraremos no if e o timer irá assumir o valor atual de millis.
Desta forma, o programa irá executar o que está dentro do if de 2000 em 2000 milissegundos, ou seja, 2 em 2 segundos.
Esse tipo de estrutura é muito comum e será usada em outras experiências.
Biblioteca dht.h
Na elaboração do software utilizamos a biblioteca dht.h. Esta biblioteca implementa as funcionalidades do sensor DHT11 e DHT22 tornando sua utilização extremamente simples.
Declarando um DHT
Ao usar essa biblioteca trataremos cada sensor DHT como um objeto, dessa forma precisamos declará-lo no início do código.
dht DHT; // Cria um objeto da classe dht
Depois de declarado, sempre que quisermos mexer em alguma função desse DHT, devemos usar o nome da função precedida do nome do DHT e ponto.
DHT.exemplo(); // chama função exemplo() para o objeto DHT
Lendo o sensor
Para ler o sensor basta chamar o método de leitura (read11 se estiver utilizando o DHT11, ou read22 se estiver utilizando o DHT22) e em seguida ler os valores nos atributos temperature e humidity.
Importante: O sensor demora no mínimo 1 segundo de intervalo entre uma leitura e outra.
DHT.read11(A1); // chama método de leitura da classe dht, // com o pino de transmissão de dados ligado no pino A1
Temos o valor de umidade em porcentagem armazenado em:
float umidade = DHT.humidity
Temos o valor de temperatura em graus Celsius armazenado em:
float temperatura = DHT.temperature
Exemplo de aplicação:
// Exibe na serial o valor de umidade Serial.print(DHT.humidity); Serial.println(" %"); // Exibe na serial o valor da temperatura Serial.print(DHT.temperature); Serial.println(" Celsius");
Fechamento
Esperamos que tenham gostado, deixe seu comentário com duvidas, sugestões ou com a foto ou vídeo de seu projeto!! Compartilhe à vontade.
Tutorial feito em parceria com Ronan Largura