Este projeto é direcionado para a Internet das Coisas (IoT) , desta vez com o microcontrolador NodeMCU! Neste artigo, 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 humidade relativa do ar.
O diagrama em blocos abaixo, nos dá uma visão geral sobre o projeto:
No vídeo abaixo, pode ver como ficará o projeto final:
1: Lista de materiais
- NodeMCU ESP8266-12E
- 0.96″ I2C IIC SPI Serial 128X64 White OLED LCD LED Display Module
- DHT22 AM2302 Temperature And Humidity Sensor
- Mini BreadBoard
- Male-Female Dupont Cables
- Fonte externa de 5V ou bateria
2: Instalando o OLED no NodeMCU
Agora é hora de instalar nosso velho conhecido, o display OLED SSD1306, cujas principais caraterísticas são:
- Tamanho do display: 0.96 “
- Comunicação Serial I2C IIC SPI
- 128X64
- Display de carateres cor branca
Interligue 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) como com 3.3V fornecidos diretamente do módulo NodeMCU.
Depois de ligar o OLED, devemos fazer download e instalar a 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. No link abaixo e faça o download da 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 superior.
Depois de reiniciado o IDE, a biblioteca já deverá estar instalada.
A biblioteca suporta o protocolo I2C para aceder ao modulo OLED, usando a biblioteca Wire.h:
#include #include "SSD1306.h" SSD1306 display(ADDRESS, SDA, SDC);
Listaremos apenas algumas API mais importantes, as quais serão utilizadas com o OLED.
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 position 0 to position 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 ligação dos pinos OLED 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 teste:
3: Obtendo os dados internos (“Indoor”)
Neste momento, nosso NodeMCU já pode comunicar com o mundo pelo display. Instalemos agora um sensor digital de Temperature e Humidade, o nosso habitual 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 humidade de baixo custo da família DHT, são muito básicos e lentos, mas ótimos para hobbies ou pequenos projetos domésticos. Os sensores DHT são construídos em duas partes, um sensor de humidade 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 como o Arduino, Raspberry Pi ou outros.
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 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 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 o DHT22):
/* 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:
Poderá fazer o download do código completo para operação “indoor” a partir do GitHub:
Home Weather Station Indoor code
4: Obtendo os dados externos (“Outdoor”):
Nossos dados meteorológicos serão fornecidos por um serviço gratuito, o “Weather Underground“. Você precisará criar uma conta em seu site e obter uma chave para poder se utilizar da API. Faça-o, seguindo as instruções no link abaixo:
https://www.wunderground.com/weather/api
Nossa estação meteorológica doméstica é baseada no extraordinário trabalho desenvolvido por Daniel Eichhorn (@ squix78). Siga as instruções constantes de seu GitHub para obter as bibliotecas apropriadas. Você precisará ao menos, instalar as bibliotecas abaixo:
- 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.
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. Agora cada um 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
Via MJRobot