Estação Meteorológica Arduino Nano: Kit de Sensores e Display OLED
Componentes e Materiais
| Componente | Quantidade |
|---|---|
| Arduino Nano R3 | 1 |
| Sensor Barométrico Seeed Grove BMP280 | 1 |
| Sensor Temperatura e Umidade DHT11 (4 pinos) | 1 |
| Display OLED 0.96" 128x64 (ElectroPeak) | 1 |
| Sensor UV GUVA-S12SD | 1 |
| RTC DS3231 | 1 |
Ferramentas Necessárias
- Ferro de solda
- Fio de solda (sem chumbo)
- Impressora 3D (genérica)
Aplicativos e Serviços Online
- Arduino IDE
- Autodesk Fusion 360 (para modelagem do gabinete)
Sobre o Projeto
Há muito tempo queria fazer uma estação meteorológica sem usar internet. É ótimo medir os dados climáticos do seu entorno e consultá-los quando quiser. Então criei uma estação meteorológica local com visual legal que mede pressão atmosférica, temperatura, umidade e índice UV do dia (se colocada perto da janela). E tem mais! 😉 Também tem tela de relógio mostrando hora, data e dia da semana.








Neste tutorial, mostro como fazer esta estação meteorológica nos seguintes passos.
Passo 1: Construir o Gabinete
Usei Autodesk Fusion 360 para criar o gabinete e imprimi com PLA verde. Necessita suportes; imprimi com 20% de preenchimento e 70 mm/s na minha Ender 3. O arquivo STL do gabinete está disponível com o projeto.


Passo 2: BMP280
O BMP280 mede pressão atmosférica e temperatura, usando I2C ou SPI. Aqui usei SPI. Conexões:
- CS → D10
- SDA → D11
- SDO → D12
- SCK → D13
No código, incluo a biblioteca #include <Adafruit_BMP280.h> (baixe aqui). Defino os pinos SPI, inicializo o sensor no setup() e leio pressão e temperatura no loop() com bmp.readPressure() e bmp.readTemperature(). Divido pressão por 100 para obter hPa. Para altitude, uso bmp.readAltitude(1005.47) — altere 1005.47 para a pressão média da sua região.
Passo 3: RTC DS3231
A estação também tem tela de relógio (hora, data, dia da semana). Uso o módulo RTC DS3231 (protocolo I2C). Conexões:
- SCL → A5
- SDA → A4
Primeiro, ajuste a hora/data no RTC usando o programa DS3231_set.ino dos exemplos da biblioteca.
No programa principal, incluo #include <DS3231.h> e leio os dados de tempo conforme a biblioteca. Criei um switch-case para cada dia da semana.
Passo 4: DHT11
Uso este sensor para umidade. Conecte seu pino de dados ao D2 do Arduino. No programa, incluo #include <DHT.h>, inicializo no setup() e leio umidade no loop() com dht.readHumidity().
Passo 5: Sensor UV GUVA-S12SD
O GUVA-S12SD é um fotodiodo Schottky à base de Nitreto de Gálio. Detecção UV típica de 240-370 nm (cobre UVB e a maior parte do UVA). Emite tensão analógica calibrada que varia com intensidade da luz UV. Podemos ler o valor analógico via ADC do Arduino.
No loop(), leio o sensor e calculo o índice UV:
float sensorValue = analogRead(A0);
float sensorVoltage = sensorValue / 1024 * 5.0;
int UV_index = sensorVoltage / 0.1;
Passo 6: Display OLED
Uso display OLED 0.96" 128x64 (protocolo I2C). Conexões:
- SCK → A5
- SDA → A4
No programa, incluo as bibliotecas:
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Crio a variável display e adiciono bitmaps para exibir ícones. No setup(), inicializo o display. No loop(), exibo todos os dados usando display.print(). Os dados aparecem em 4 páginas: Hora, Pressão, Temperatura & Umidade, Índice UV. Há delay de 5 segundos entre cada página.
Vídeo Demonstrativo
Vídeo do projeto em funcionamento disponível na página original.
Código Completo
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>
#include <DS3231.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeMonoBoldOblique12pt7b.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10
DS3231 clock;
bool century = false;
bool h12Flag;
bool pmFlag;
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Bitmaps para ícones (frame0, frame1, frame2) - omitidos por brevidade
// const unsigned char PROGMEM frame0 [] = { ... };
// const unsigned char PROGMEM frame1 [] = { ... };
// const unsigned char PROGMEM frame2 [] = { ... };
void setup() {
Serial.begin(57600);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Falha SSD1306"));
}
Wire.begin();
dht.begin();
if (!bmp.begin()) {
Serial.println(F("Problema BMP"));
while (1) delay(10);
}
// Tela inicial
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 9);
display.setFont(&FreeSans9pt7b);
display.println("**** LOCAL ****");
display.setCursor(0, 38);
display.setFont(&FreeMonoBoldOblique12pt7b);
display.println("wather");
display.setCursor(27, 58);
display.println("Station");
display.display();
delay(2000);
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,
Adafruit_BMP280::SAMPLING_X2,
Adafruit_BMP280::SAMPLING_X16,
Adafruit_BMP280::FILTER_X16,
Adafruit_BMP280::STANDBY_MS_500);
}
void loop() {
// Página 1: Hora
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(13, 15);
display.setFont(&FreeMonoBoldOblique12pt7b);
display.print(clock.getHour(h12Flag, pmFlag));
display.setCursor(38, 15);
println(":");
display.setCursor(50, 15);
display.println(clock.getMinute());
display.setCursor(70, 15);
if (pmFlag) display.println(" PM"); else display.println(" AM ");
display.setFont(&FreeSans9pt7b);
display.setCursor(20, 60);
display.println(clock.getDate());
display.setCursor(40, 60);
display.println("/");
display.setCursor(46, 60);
display.println(clock.getMonth(century));
display.setCursor(65, 60);
display.println("/");
display.setCursor(70, 60);
display.println("20");
display.setCursor(90, 60);
display.println(clock.getYear());
display.setCursor(30, 30);
display.setFont(&FreeSans9pt7b);
switch (clock.getDoW()) {
case 1: display.println("Sabado"); break;
case 2: display.println("Domingo"); break;
case 3: display.println("Segunda"); break;
case 4: display.println("Terca"); break;
case 5: display.println("Quarta"); break;
case 6: display.println("Quinta"); break;
case 7: display.println("Sexta"); break;
}
display.display();
delay(5000);
// Página 2: Pressão
display.clearDisplay();
display.drawBitmap(0, 0, frame0, 40, 40, 1);
display.setFont(&FreeSans9pt7b);
display.setCursor(41, 28);
display.println(bmp.readPressure() / 100);
display.setCursor(110, 28);
display.setFont();
display.println("hPa");
display.setCursor(0, 55);
display.setFont(&FreeSans9pt7b);
display.println("Altitude:");
display.setCursor(65, 62);
display.println(bmp.readAltitude(1005.47));
display.setCursor(113, 62);
display.println("m");
display.display();
delay(5000);
// Página 3: Temperatura e Umidade
display.clearDisplay();
display.setFont(&FreeMonoBoldOblique12pt7b);
display.drawBitmap(0, 5, frame1, 40, 51, 1);
display.setCursor(35, 30);
display.print(bmp.readTemperature());
display.setFont(&FreeSans9pt7b);
display.setCursor(102, 28);
display.println(" *");
display.setCursor(110, 31);
display.println(" C");
display.setFont();
display.setCursor(66, 45);
display.println("RH :");
byte RH = dht.readHumidity();
display.setCursor(95, 45);
display.println(RH);
display.setCursor(110, 45);
display.println("%");
display.drawBitmap(0, 56, frame2, 135, 15, 1);
display.display();
delay(5000);
// Página 4: Índice UV
display.clearDisplay();
float sensorValue = analogRead(A0);
float sensorVoltage = sensorValue / 1024 * 5.0;
int UV_index = sensorVoltage / 0.1;
display.setFont(&FreeSans9pt7b);
display.setCursor(0, 15);
display.print(" UV INDEX ");
display.setCursor(58, 45);
display.println(UV_index);
display.display();
delay(5000);
}
Peças Personalizadas e Gabinetes
Arquivo STL do gabinete disponível para download.
Esquemático

Processo de manufatura
- Estação Meteorológica Solar DIY com Raspberry Pi
- Construindo Estação Meteorológica Externa com Raspberry Pi 2 e ADS‑WS1
- Construa Estação Meteorológica Raspberry Pi que Envia Dados Diários por Email
- Estação Meteorológica Avançada v2.0: Monitoramento em Tempo Real de Temperatura, Pressão, Umidade e Altitude
- Estação de Mistura de Bebidas 6-Shooter Controlada por Arduino – Construa seu Próprio Automatizador de Coquetéis
- Sistema Multi-Posição de Sensores de Temperatura para Integração em Casa Inteligente
- Registrador de Dados de Balão Meteorológico Arduino de Alto Desempenho
- Estação Meteorológica Portátil Arduino por $10 – DIY com Nano, DHT22, BMP180 e LCD
- Monitoramento Meteorológico em Tempo Real com Arduino e ThingSpeak IoT
- Estação Meteorológica WiFi com ESP8266 e Sensor DHT22