Continuemos nossa exploração pelo mundo do IoT, nas asas do NodeMCU! Neste tutorial, desenvolveremos uma estação meteorológica doméstica, onde se exibirá informações tais como temperatura e condições climáticas, tanto para o dia corrente quanto para os próximos 3 dias. Nossa estação também exibirá informações internas da casa, como temperatura e umidade relativa do ar.
O diagrama em blocos abaixo, nos dá uma visão geral sobre o projeto:
No vídeo abaixo, você pode ver como ficará o projeto final:
1: Lista de materiais (BoM)
Valores referenciais em USD
- NodeMCU ESP8266-12E ($8.79)
- Mini BreadBoard ($1.00)
- Male-Female Dupont Cables ($1.00)
- Fonte externa de 5V ou bateria
2: Instalando o OLED no NodeMCU
Suponho que você já tenha o IDE do Arduino preparado com todas as bibliotecas necessárias para executar o código NodeMCU. Caso não, leia as instruções em meu tutorial premiado: Do “blink” ao BLYNK, uma viagem pela “Internet das coisas” nas asas do NodeMCU ESP-12E
Agora é hora de instalar nosso velho conhecido, o display OLED SSD1306, cujas principais características são:
- Tamanho da tela: 0.96 “
- Comunicação Serial I2C IIC SPI
- 128X64
- Display de caracteres na cor branca
Conecte os pinos do OLED ao NodeMCU, conforme descritos abaixo e no diagrama elétrico acima:
- SDA ==> D1 (5)
- SCL * ==> D2 (4) * Você também poderá encontrar “SDC” ao invés de SCL
- VCC ==> 3.3V ou 5V
GND ==> GND
O SSD1306 pode ser alimentado tanto com 5V (externo) quanto com 3.3V fornecidos diretamente do módulo NodeMCU.
Depois de conectar o OLED,devemos baixar e instalar sua biblioteca no IDE do Arduino. Usamos em projetos anteriores a biblioteca desenvolvida pela ACROBOT, que apesar de fácil de usar, é mais limitada. Desta vez exploraremos a poderosa biblioteca gráfica desenvolvida por Daniel Eichhorn. Entre no link abaixo e faça o descarregue a biblioteca, instalando-a no IDE do Arduino:
https://github.com/squix78/esp8266-oled-ssd1306
Certifique-se de usar a versão 3.0.0 ou maior!
Depois de reiniciado o IDE, a biblioteca já deverá estar instalada.
A biblioteca suporta o protocolo I2C para acessar a modulo OLED, usando a biblioteca Wire.h:
#include <Wire.h> #include "SSD1306.h" SSD1306 display(ADDRESS, SDA, SDC);
Listaremos apenas algumas API mais importantes, as quais serão utilizadas com o OLED.
A lista completa poderá ser encontrada no GITHub fornecido anteriormente neste tópico.
A. Controle de exibição do display:
void init(); // Initialise the display void resetDisplay(void); // Cycle through the initialisation void displayOn(void); // Turn the display on void displayOff(void); // Turn the display offs void clear(void); // Clear the local pixel buffer void invertDisplay(void); // Inverted display mode void normalDisplay(void); // Normal display mode void setContrast(char contrast); // Set display contrast void flipScreenVertically(); // Turn the display upside down
B. Desenho gráfico
void setColor(OLEDDISPLAY_COLOR color); // Sets the color of all pixel operations void setPixel(int16_t x, int16_t y); // Draw a pixel at given position void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); // Draw a line from pos 0 to pos 1 void drawHorizontalLine(int16_t x, int16_t y, int16_t length); // Draw a line horizontally void drawVerticalLine(int16_t x, int16_t y, int16_t length); // Draw a lin vertically void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const char *image); // Draw a bitmap in the internal image format
C. Operações com texto:
void drawString(int16_t x, int16_t y, String text); // Write the text at given position uint16_t getStringWidth(const char* text, uint16_t length); // Returns the width of the const char* with the current font settings uint16_t getStringWidth(String text); // Convenience method for the const char version void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); // TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH void setFont(const char* fontData); // Sets the current font. // Available default fonts: ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
D. Frames (“Ui Library”)
A Ui Library é utilizada para fornecer um conjunto básico de elementos Ui chamados, Frames e Overlays. Um Frame é usado para fornecer informações onde o comportamento padrão é exibir um Frame por um tempo definido e passar para o próximo (como “Paginas”). A biblioteca também fornece um Indicador de qual frame (ou página) está sendo mostrada. Um overlay, por outro lado, é uma informação (por exemplo, um relógio) que é exibido sempre na mesma posição.
void init(); // Initialise the display void setTargetFPS(uint8_t fps); //Configure the internal used target FPS void enableAutoTransition(); //Enable automatic transition to next frame void disableAutoTransition(); // Disable automatic transition to next frame. void setAutoTransitionForwards(); // Set the direction if the automatic transitioning void setAutoTransitionBackwards(); // Set the direction if the automatic transitioning void setTimePerFrame(uint16_t time); //Set the approx. time a frame is displayed void setTimePerTransition(uint16_t time); //Set the approx. time a transition will take void setFrameAnimation(AnimationDirection dir); //Configure what animation is used to transition void setFrames(FrameCallback* frameFunctions, uint8_t frameCount); //Add frame drawing functions int8_t update(); // This needs to be called in the main loop
Uma vez que o OLED e sua biblioteca estejam instalados, escreveremos um simples programa, o “Hello World” para testá-los. Entre com o código abaixo em seu IDE, o resultado deverá ser algo como mostrado na foto:
/* Hello World OLED Test */ #include // Only needed for Arduino 1.6.5 and earlier #include "SSD1306.h" // alias for `#include "SSD1306Wire.h"` SSD1306 display(0x3c, 5, 4); // Initialise the OLED display using Wire library void setup() { Serial.begin(115200); display.init(); // Initialising the UI will init the display too. display.flipScreenVertically(); display.clear(); drawHelloWorld(); display.display(); } void loop() { } void drawHelloWorld() { display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_10); display.drawString(0, 0, "Hello world"); display.setFont(ArialMT_Plain_16); display.drawString(0, 10, "Hello world"); display.setFont(ArialMT_Plain_24); display.drawString(0, 26, "Hello world"); }
Agora, carregue a sketch: SSD1306SimpleDemo.ino, a qual faz parte dos EXEMPLOS incluídos com biblioteca.
Antes de executar o código, altere a conexão OLED pinos em conformidade:
// Initialise the OLED display using Wire library SSD1306 display(0x3c, 5, 4);
O vídeo abaixo mostra o OLED executando o código de teste:
3: Obtendo os dados internos (“Indoor”)
Neste momento, nosso NodeMCU já pode se comunicar com o mundo pelo display! Instalemos agora um sensor digital de Temperature e umidade, nosso bom e velho DHTxx (DHT11 ou DHT22). O site da ADAFRUIT fornece ótimas informações sobre esses sensores. Abaixo, algumas informações retiradas do site:
Visão geral
Os sensores de temperatura e umidade de baixo custo da família DHT, são muito básicos e lentos, mas ótimos para hobbyists que querem fazer algum registro de dados básico. Os sensores DHT são construídos em duas partes, um sensor de umidade capacitiva e um termistor. Há também um chip muito básico no interior que faz a conversão analógica para digital. O sinal digital gerado é bastante simples de ser lido usando-se qualquer micro controlador.
DHT11 vs DHT22
Temos duas versões do sensor DHT, eles se parecem e têm a mesma pinagem, mas possuem algumas características diferentes. Aqui estão as especificações:
DHT11
- Bom para leituras de 20-80% de humidade com 5% de precisão
- Bom para leituras de temperatura de 0-50 ° C ± 2 ° C de precisão
- Não mais de 1 Hz taxa de amostragem (uma vez por segundo)
- Ultra baixo custo
- Alimentação: 3 a 5V
- Consumo: 2.5mA max (durante a conversão de dados)
- Tamanho do corpo 15.5mm x 12mm x 5.5mm
- 4 pinos com espaçamento de 0,1 “
DHT22
- Bom para leituras de 0-100% de humidade com precisão de 2 a 5%
- Bom para leituras de temperatura de -40 a 125 ° C Precisão de ± 0,5 ° C
- Não mais de 0,5 Hz taxa de amostragem (uma vez a cada 2 segundos)
- Baixo custo
- Alimentação: 3 a 5V
- Consumo: 2.5mA max (durante a conversão de dados)
- Tamanho do corpo 15.1mm x 25mm x 7.7mm
- 4 pinos com espaçamento de 0,1 “
Como você pode ver, o DHT22 é um pouco mais preciso e melhor sobre um intervalo ligeiramente maior. Ambos usam um único pino digital e são “lentos”, pois você não pode consultá-los mais de uma vez a cada segundo (DHT11) ou dois (DHT22).
Ambos os sensores funcionam bem para obter informações sobre o interior da casa a serem exibidas em nossa Estação Meteorológica Doméstica.
O DHTxx tem 4 pinos (olhando para o sensor, como mostra a foto, o pino 1 é o mais à esquerda):
- VCC (conectado a 5V externo ou a 3.3V de NodeMCU)
- Dados
- Não conectado
- Terra.
Uma vez que normalmente você usará o sensor em distâncias inferiores a 20m, um resistor de 10K ohms deve ser conectado entre os pinos Data e VCC. O pino de saída será conectado ao pino D3 do NodeMCU (veja o diagrama acima).
Uma vez instalado o sensor em nosso módulo, faça o download da biblioteca DHT do repositório GitHub da Adafruit e instale-o no arquivo de bibliotecas do Arduino.
Uma vez recarregado o IDE do Arduino, a “biblioteca de sensores DHT” deverá estar instalada.
Definamos os parâmetros e variáveis associadas para o sensor (usaremos em primeiro lugar oDHT22):
/* DHT22 */ #include "DHT.h" #define DHTPIN D3 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); int localHum = 0; int localTemp = 0;
Agora criaremos uma função para leitura dos dados:
/*************************************************** * Get indoor Temp/Hum data ****************************************************/ void getDHT() { float tempIni = localTemp; float humIni = localHum; localTemp = dht.readTemperature(); localHum = dht.readHumidity(); if (isnan(localHum) || isnan(localTemp)) // Check if any reads failed and exit early (to try again). { Serial.println("Failed to read from DHT sensor!"); localTemp = tempIni; localHum = humIni; return; } }
Uma vez de posse dos dados, usemos o OLED para mostrá-los :
/*************************************************** * Draw Indoor Page ****************************************************/ void drawDHT() { int x=0; int y=0; display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0 + x, 5 + y, "Hum"); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(43 + x, y, "INDOOR"); display.setFont(ArialMT_Plain_24); String hum = String(localHum) + "%"; display.drawString(0 + x, 15 + y, hum); int humWidth = display.getStringWidth(hum); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(95 + x, 5 + y, "Temp"); display.setFont(ArialMT_Plain_24); String temp = String(localTemp) + "°C"; display.drawString(70 + x, 15 + y, temp); int tempWidth = display.getStringWidth(temp); }
A foto abaixo mostra como os dados serão apresentados no display:
Você poderá fazer o download do código completo para operação “indoor” á partir de meu GitHub:
Home Weather Station Indoor code
4: Obtendo os dados externos (“Outdoor”):
- Weather Station by Daniel Eichhorn: https://github.com/squix78/esp8266-weather-station
- Json Streaming Parser by Daniel Eichhorn: https://github.com/squix78/json-streaming-parser
Depois de ter as bibliotecas instaladas e o IDE reiniciado, baixe o programa completo a partir de meu GitHub:
MJRoBot Home Weather Station code
Depois de ter o código carregado no IDE do Arduino, abra o arquivo stationCredentials.h e entre com seus dados pessoais:
/* WIFI */ const char* WIFI_SSID = "YOUR SSID"; const char* WIFI_PWD = "YOUR PASSWORD"; /* Wunderground Settings */ const boolean IS_METRIC = true; const String WUNDERGRROUND_API_KEY = "YOUR KEY"; const String WUNDERGRROUND_LANGUAGE = "EN"; const String WUNDERGROUND_COUNTRY = "CL"; const String WUNDERGROUND_CITY = "Santiago";
Observe que as informações meteorológicas que iremos recuperar do serviço W.Underground serão sobre Santiago (“city”) e CL (“country”: Chile). Você também deve alterá-las com os dados de sua cidade.
E é isso aí, pessoal!
Sua estação meteorológica doméstica deverá estar funcionando agora! Nas fotos abaixo, você pode ver meu protótipo funcionando:
5: Colocando a estação “na caixa”
A última etapa é montar nossa estação em uma caixa. Fiz duas montagens diferentes em caixas plásticas. Você decide a melhor maneira de “empacotar” seu projeto!
Em outra montagem, aproveitei e também testei a estação com o DHT11.
Não se esqueça de alterar os dados do DHT no arquivo “stationDefines.h”.
6: Conclusão
Como sempre, espero que este projecto possa ajudar outros a encontrarem o seu caminho no emocionante mundo da electrónica e do IoT!
Visite o meu depositário no GitHub para obter os arquivos atualizados:
MJRoBot Home Weather Station depository
Não deixem de visitar e seguir minha página: MJRoBot.org no Facebook
Saludos desde el sur del mundo!
Até o próximo tutorial!
Obrigado
Marcelo
Prezado Sr.,
Gostaria de saber o custo de uma estação meteorológica com os seguintes sensores: Temperatura ambiente do ar, direção do vento, pressão barométrica, umidade relativa do ar e índice pluviométrico (todas as unidades no sistema métrico decimal ou SI). Estação com funcionamento sem fio (wifi) e que possa transmitira dados de Teresópolis para o Rio de Janeiro, RJ e no local display de acompanhamento.
Também, necessito que o sistema tenha capacidade de fechar/abrir um contato NA dependendo de uma velocidade pre programada de vento. Se destina a um sistema de painéis fotovoltaicos instalados em Teresópolis e que eu possa ter os dados aqui no Rio. Padrão de qualidade de estação meteorológica caseira. Grato
CurtirCurtir
Hola, saludos. He realizado tu proyecto y me falla la lectura del sensor DHT22, me da números erróneos. He comprobado otro sensor, alimentacion e incluso utilizar otro pin de salida. Mi conclusion es que debe de ser algo del codigo ya que en funcionamiento le desconecto los 3v del DHT y sigue dando los mismos valores erróneos. Me puedes dar alguna idea ? Gracias y un saludo.
CurtirCurtir
Consigo usar um display touch de 3.5 TFT?
CurtirCurtir
Purtroppo API Weather Underground:
To improve our services and enhance our relationship with our users, we will no longer provide free weather API keys as part of our program. If you have been directed to download our Weather Underground free API key by a third party provider, please contact your vendor for resolution.
:-((((
CurtirCurtir
Não consigo obter as informações meteorológicas do serviço W.Underground para cidade do Rio de Janeiro. Como você fez para conseguir da sua cidade ?
CurtirCurtir
Você tentou rio_de_janeiro?
CurtirCurtir
Funcionou perfeitamente com WUNDERGROUND_COUNTRY = “BR”; WUNDERGROUND_CITY = “rio_de_janeiro”;
Parabéns pelo excelente trabalho que você desenvolve!
CurtirCurtir
Outra opção: id: IRIODEJA79
CurtirCurtir
Parabéns pelo blog está ajudando muito estou estudando sobre esse fantástico Arduino. Portanto posso utilizar o display LCD 16 x 2?
CurtirCurtir
Oi Roniedson, para este projeto o LCD 16 x 2 não funcionaria. Teriamos que escrever todo o SW novamante, pois o OLED é grafico e o LCD 16 x 2 é só para caracteres. Em minha opinião não faria muito sentido. Mas voce poderia fazer outro projeto do zero onde somente escrevesse a temperatura, etc.
CurtirCurtir
muito obrigado pela atenção e como usaria somente o dht 22 com o nodemcu e visualizar no blink
CurtirCurtir
Seria mais ou menos com no fiz neste projeto:
https://mjrobot.org/2017/01/06/o-iot-feito-simples-monitorando-a-temperatura-desde-qualquer-lugar/
Somente você deverá trocar as rotinas relacionadas com sensor DS18B20 pelas do DH22 que está neste post aqui. Se você quiser só escrever os valores locais em um display simples, também da sem problema.
CurtirCurtir
Olá Marcelo. Eu já tinha colocado uma dúvida relativa a este projeto no https://www.instructables.com/id/IoT-Made-Simple-Home-Weather-Station-With-NodeMCU-/ mas acho que não consegui transmitir essa dúvida. É assim: o meu OLED é o modelo da waveshare (http://www.waveshare.com/0.96inch-oled-b.htm). Após configurar o OLED no NodeMCU eu consigo obter e visualizar os dados da Temperatura e humidade nele. Quando tento o resto é que dá erros… Será que a Ui Library funciona com este OLED? O seu projeto é muito bom e gostaria de tentar. Sou principiante nestas áreas mas estou a gostar muito. Este será já o meu 4º projeto…
Melhores cumprimentos,
Luís
CurtirCurtir
Hi Luis. OK. Eu pensava que era outro tipo de display. Eu nunca trabalhei com este modelo que voce está utilizando, mas entendo que o “core” é o mesmo OLED SSD1336 e a biblioteca deveria funcionar.
Fui dar uma verificada no GitHub do Daniel Eichhorn (squix78)
https://github.com/squix78/esp8266-oled-ssd1306 , que foi quem desenvolveu estas bibliotecas, onde ele declara:
“This is a driver for the SSD1306 based 128×64 pixel OLED display running on the Arduino/ESP8266 platform. Can be used with either the I2C or SPI version of the display”.
No caso do I2C (meu display de 4 pinos), deve-se incluir no inicio do código:
#include <Wire.h>
#include “SSD1306.h”
SSD1306 display(ADDRESS, SDA, SDC);
No caso do SPI (seu display de 7 pinos), deve-se incluir no inicio do código:
#include <SPI.h>
#include “SSD1306Spi.h”
SSD1306Spi display(RES, DC, CS);
Novamente, eu nunca utilizei este display, mas acredito que com isto deva funcionar.
Boa sorte e um abraço.
Marcelo
CurtirCurtir
Obrigado pela rápida resposta. Entretanto eu tentei novamente através de uma análise ao seu código e reparei que eu cometi um erro. Agora está tudo operacional a 100%
Muito obrigado pelo disponibilizar este projeto! 🙂
Luís Ferreira
CurtirCurtido por 1 pessoa
Que bom que encontrou a solução! 😉
E me desculpe, estava viajando e vi sua pergunta no Instructables no iphone e pensei que estava com um Display não gráfico. Agora voltei lá e vi que o que te comentei acima voce já tinha verificado. 😉 Mas o legal é ir descobrindo as coisas e aprendendo com os erros! Manda bala com seus projetos! Abração!
CurtirCurtir
Nice project!! Works better than Forecast Weather Report from TV!
CurtirCurtido por 1 pessoa
Thanks! 😉
CurtirCurtir