Погодная станция на Arduino Nano: BMP280, DHT11, UV, DS3231, OLED 0.96″
Компоненты и материалы
- Arduino Nano R3 — 1 шт.
- BMP280 (давление + температура) — 1 шт. (Grove / Breakout, SPI)
- DHT11 (температура + влажность) — 1 шт.
- OLED 0.96″ 128×64 (SSD1306, I2C) — 1 шт.
- GUVA-S12SD (UV-индекс, аналоговый) — 1 шт.
- DS3231 RTC (часы реального времени) — 1 шт.
- Корпус (3D-печать, STL в проекте) — 1 шт. (PLA, 20% наполнение, поддержки нужны)
Инструменты
- Паяльник, припой (бессвинцовый)
- 3D-принтер (Ender 3 / любой FDM)
ПО и библиотеки
- Arduino IDE 1.6.7+
- Autodesk Fusion 360 (для корпуса)
- Библиотеки (через менеджер):
Adafruit_BMP280DS3231(by Rinky-Dink Electronics / jarzebski)DHT sensor library(Adafruit)Adafruit_GFX+Adafruit_SSD1306Fonts/FreeSans9pt7b.h,Fonts/FreeMonoBoldOblique12pt7b.h(встроены в Adafruit_GFX)
Подключение (проводка)
| Модуль | Пины Arduino Nano | Протокол |
|---|---|---|
| BMP280 | CS→D10, SDA→D11, SDO→D12, SCK→D13 | SPI |
| DS3231 | SDA→A4, SCL→A5 | I2C |
| OLED SSD1306 | SDA→A4, SCL→A5 | I2C (общая шина с RTC) |
| DHT11 | DATA→D2 | 1-Wire |
| GUVA-S12SD | OUT→A0 | Аналог |
Логика работы и код
Дисплей циклически показывает 4 экрана по 5 секунд:
- Время/Дата/День недели — от DS3231.
- Давление (hPa) + Высота (м) — от BMP280. Высота считается относительно среднего давления вашего региона (в коде
1005.47— замените на своё). - Температура (°C) + Влажность (%) — T от BMP280 (точнее), RH от DHT11.
- UV Index — от GUVA-S12SD:
UV_index = (analogRead(A0) / 1024.0 * 5.0) / 0.1.
Настройка RTC
Перед первым запуском прошейте пример DS3231_set.ino из библиотеки для установки текущего времени/даты. Батарея CR2032 на модуле держит время при отключении питания.
Формула UV Index
float sensorValue = analogRead(A0);
float sensorVoltage = sensorValue / 1024.0 * 5.0;
int UV_index = sensorVoltage / 0.1; // 0.1 В на единицу UV Index (по даташиту)
Полный скетч (основные моменты)
#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
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
DS3231 clock;
bool century=false, h12Flag, pmFlag;
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// ... bitmap-массивы frame0, frame1, frame2 для иконок (druck, temp/rh, uv) ...
void setup() {
Serial.begin(57600);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { /* error */ }
Wire.begin(); dht.begin();
if(!bmp.begin()) { /* error */ }
// Приветствие
display.clearDisplay();
display.setFont(&FreeSans9pt7b);
display.setCursor(0,9); display.println("**** LOCAL ****");
display.setFont(&FreeMonoBoldOblique12pt7b);
display.setCursor(0,38); 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() {
// 1. TIME
display.clearDisplay();
display.setFont(&FreeMonoBoldOblique12pt7b);
display.setCursor(13,15); display.print(clock.getHour(h12Flag,pmFlag));
display.setCursor(38,15); display.print(":");
display.setCursor(50,15); display.print(clock.getMinute());
display.setCursor(70,15); display.print(pmFlag?" PM":" AM");
display.setFont(&FreeSans9pt7b);
display.setCursor(20,60); display.print(clock.getDate());
display.setCursor(40,60); display.print("/");
display.setCursor(46,60); display.print(clock.getMonth(century));
display.setCursor(65,60); display.print("/20");
display.setCursor(90,60); display.print(clock.getYear());
display.setCursor(30,30);
switch(clock.getDoW()){
case 1: display.print("Saturday"); break;
case 2: display.print("Sunday"); break;
case 3: display.print("Monday"); break;
case 4: display.print("Tuesday"); break;
case 5: display.print("Wednesday"); break;
case 6: display.print("Thursday"); break;
case 7: display.print("Friday"); break;
}
display.display(); delay(5000);
// 2. PRESSURE + ALTITUDE
display.clearDisplay();
display.drawBitmap(0,0,frame0,40,40,1);
display.setFont(&FreeSans9pt7b);
display.setCursor(41,28); display.print(bmp.readPressure()/100.0);
display.setCursor(110,28); display.setFont(); display.print("hPa");
display.setCursor(0,55); display.setFont(&FreeSans9pt7b); display.print("Altitude:");
display.setCursor(65,62); display.print(bmp.readAltitude(1005.47)); // <-- СВОЁ ДАВЛЕНИЕ!
display.setCursor(113,62); display.print("m");
display.display(); delay(5000);
// 3. TEMP + HUMIDITY
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.print(" *"); display.setCursor(110,31); display.print("C");
display.setFont(); display.setCursor(66,45); display.print("RH :");
byte RH = dht.readHumidity();
display.setCursor(95,45); display.print(RH); display.setCursor(110,45); display.print("%");
display.drawBitmap(0,56,frame2,135,15,1);
display.display(); delay(5000);
// 4. UV INDEX
display.clearDisplay();
float sv = analogRead(A0); float volt = sv/1024.0*5.0;
int uv = volt/0.1;
display.setFont(&FreeSans9pt7b);
display.setCursor(0,15); display.print(" UV INDEX ");
display.setCursor(58,45); display.print(uv);
display.display(); delay(5000);
}
Корпус (3D-печать)
STL-файлы прикреплены к проекту. Напечатаны зелёным PLA на Ender 3 (20% infill, 70 мм/с, с поддержками). Корпус закрытый, датчики вынесены наружу / в вентиляционные щели.
Видео-демонстрация
См. видео в оригинале проекта (раздел Video Clip).
Производственный процесс
- DIY солнечная метеостанция на Raspberry Pi
- Сборка уличной метеостанции на Raspberry Pi 2 и ADS‑WS1
- Создание метеостанции на Raspberry Pi с ежедневными email-отчётами о погоде
- Продвинутая метеостанция v2.0: мониторинг температуры, давления, влажности и высоты в реальном времени
- Автоматизированная барная станция «6-Сhooter» на Arduino — Собираем коктейльный робот своими руками
- Многопозиционная система датчиков температуры для интеграции в умный дом
- Высокопроизводительный регистратор данных для метеозонда на Arduino
- Портативная метеостанция на Arduino Nano за $10: DHT22, BMP180 и LCD
- Метеостанция на Arduino и ThingSpeak: температура и влажность в облаке
- Wi-Fi метеостанция на ESP8266 (ESP-01) и DHT22: отправка данных в ThingSpeak