Найти тему
Деревенский ITшник

Метеостанция часть I.

Решил поделиться опытом в создании собственной метеостанции. Часть 1.

Так как прогнозы погоды метеослужб далеко не всегда верны, а иной раз погода в приложении/телевизоре/радио в корне отличается от реальной, в окно что ль выглянуть лень... решил собрать собственную метеостанцию и вести наблюдения с графиками и сравнениями по месяцам\годам. Имеется под рукой целая гора разных датчиков и arduino-подобных плат, которые в свое время на заказывал с алика.

Задача простая:

1.Измерять влажность и температуру

2. Освещенность( в дальнейшем планирую использовать такую же станцию для контроля "умной" теплицы, вкл\выкл досвет и обогрев)

3. Простейший сайт с выводом показаний.( в дальнейшем планирую сделать доступ из интернета)

4. Сохранение данных в exel. Не думал еще как это лучше реализовать, пока из идей только Putty с включенным логированием. Есть еще вариант с СД картой...

5. Интеграция в систему "умный дом" на базе Home Assistant....

Начнем с железок.

Плата: NodeMcu v2 Amica WiFi на ESP8266

Датчики BME280,TEMT6000

Программное обеспечение: Arduino IDE 2.3.2

Скетч который вышел в итоге:

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h> // Подключаем библиотеку ESP8266WiFi
#include <Wire.h> // Подключаем библиотеку Wire
#include <Adafruit_BME280.h> // Подключаем библиотеку Adafruit_BME280
#include <Adafruit_Sensor.h> // Подключаем библиотеку Adafruit_Sensor
#define SEALEVELPRESSURE_HPA (1009.25)      // Задаем высоту
Adafruit_BME280 bme;                         // Установка связи по интерфейсу I2C
const char* ssid = "......";                         // Название Вашей WiFi сети
const char* password = "......";                    // Пароль от Вашей WiFi сети
const long utcOffsetInSeconds = 10800;                  // Смещение на +3 часа
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds); // Время с сервера NTP
WiFiServer server(80);                      // Указываем порт Web-сервера
String header;
int temt6000Pin = A0;          // Переменная аналогового входа для чтения данных с датчика освещенности
float light;
int light_value;
void setup() {
pinMode(temt6000Pin, INPUT);                  // Настраиваем temt6000Pin на вход
Serial.begin(115200);                               // Скорость передачи 115200
bool status;
if (!bme.begin(0x76)) {                             // Проверка инициализации датчика
Serial.println("Could not find a valid BME280 sensor, check wiring!"); // Печать, об ошибки инициализации.
while (1);                                          // Зацикливаем
}
Serial.print("Connect to ");                          // Отправка в Serial port
Serial.println(ssid);                                 // Отправка в Serial port
WiFi.begin(ssid, password);                           // Подключение к WiFi Сети
while (WiFi.status() != WL_CONNECTED) {               // Проверка подключения к WiFi сети
delay(500);                                         // Пауза
Serial.print(".");                                  // Отправка в Serial port
}
Serial.println("");                                   // Отправка в Serial port
Serial.println("WiFi connected.");                    // Отправка в Serial port
Serial.println("IP address: ");                       // Отправка в Serial port
Serial.println(WiFi.localIP());                       // Отправка в Serial port
server.begin();
timeClient.begin();
}
void loop(){
timeClient.update();
WiFiClient client = server.available();               // Получаем данные, посылаемые клиентом
if (client) {
Serial.println("New Client.");                      // Отправка "Новый клиент"
String currentLine = "";                            // Создаем строку для хранения входящих данных от клиента
while (client.connected()) {                        // Пока есть соединение с клиентом
if (client.available()) {                         // Если клиент активен
char c = client.read();                         // Считываем посылаемую информацию в переменную "с"
header += c;
if (c == '\n') {                                // Вывод HTML страницы
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");          // Стандартный заголовок HT
client.println("Content-type:text/html ");
client.println("Connection: close");        // Соединение будет закрыто после завершения ответа
client.println("Refresh: 900");             // Автоматическое обновление каждые 15 мин
client.println();
client.println("<!DOCTYPE html><html>");    // Веб-страница
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<meta charset='UTF-8'>");   // Делаем русскую кодировку
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
client.println("table { border-collapse: collapse; width:50%; margin-left:auto; margin-right:auto; }");
client.println("h1 { padding: 12px; background-color: #0043af; color: white; }");
client.println("tr { border: 1px solid #ddd; padding: 12px; }");
client.println("tr:hover { background-color: #ffffff; }");
client.println("td { border: none; padding: 12px; }");
client.println(".sensor { color:black; font-weight: bold; background-color: #ffffff; padding: 1px; }");
client.println("</style></head><body><h1>");
client.println(daysOfTheWeek[timeClient.getDay()]);
client.println(", ");
client.println(timeClient.getHours());
client.println(":");
client.println(timeClient.getMinutes());
client.println(":");
client.println(timeClient.getSeconds());
client.println ("</h1>");
client.println("<table");
client.println("<tr><td>Температура</td><td><span class=\"sensor\">");
client.println(bme.readTemperature());
client.println(" *C</span></td></tr>");
client.println("<tr><td>Влажность</td><td><span class=\"sensor\">");
client.println(bme.readHumidity());
client.println(" %</span></td></tr>");
client.println("<tr><td>Освещенность</td><td><span class=\"sensor\">");
client.println(light);
client.println(" %</span></td></tr>");
client.println("<tr><td>Давление</td><td><span class=\"sensor\">");
client.println(bme.readPressure() / 100.0F * 0.7500);
client.println(" мм.рт.ст.</span></td></tr>");
client.println("<tr><td>Высота над уровнем моря</td><td><span class=\"sensor\">");
client.println(bme.readAltitude(SEALEVELPRESSURE_HPA));
client.println(" м</span></td></tr>");
client.println("</body></html>");
client.println();
break;
} else {
currentLine = "";
}
} else if (c != '\r') {
currentLine += c;
}
}
}
header = "";
client.stop();
int light_value = analogRead(temt6000Pin);
light = light_value * 0.0976;                         // расчет процента
Serial.print(timeClient.getHours());                  // Вывод часа в порт
Serial.print(":");
Serial.println(timeClient.getMinutes());              // Вывод минут в порт
Serial.print("Sun ");
Serial.print(light);                                  // вывод освещенности в порт
Serial.println(" %");
Serial.print("Temp ");
Serial.print(bme.readTemperature());                  // Вывод температуры в порт
Serial.println(" C");
Serial.print("Vl ");
Serial.print(bme.readHumidity());                     // Вывод влажности в порт
Serial.println(" %");
Serial.println("Client off.");
Serial.println("");
}
}

Подключение датчиков следующее

BME280 подключаем VIN → 3.3, GDN → GDN, SCL → D1, SDA → D2

temt6000 так же к VСС→ 3.3, GDN → GDN, OUT → A0

Получился вот такая вот страничка
Получился вот такая вот страничка

Скетч с комментариями, разберу только подключаемые библиотеки

Не буду описывать подключение библиотек, все уже давно есть в других статьях.

NTPClient.h для считывания времени с NTP сервера в сети

ESP8266WiFi.h из название думаю понятно для чего, подключение к Wi-Fi и создание сервера

Wire.h для связи с модулями через интерфейс I2C в моем случае с BME280

Adafruit_BME280.h для работы с датчиком BME280

Adafruit_Sensor.h для работы с датчиком temt6000

Не уверен что высота над уровнем моря выставлена правильно,

#define SEALEVELPRESSURE_HPA (1009.25)

из-за этого и давление может считаться не правильно, но мне он как то особо и не нужен.

Так же все измерения дублируется в Serial Port и пока что питание идет через USB от компьютера.

Так же появилось необходимость подключить внешнею SD карту и вести запись измерений в нее, питаться то будет в последствии от аккумулятора.

Сейчас тестирую в домашних условиях, в планах запихнуть все это в уличный фонарь с солнечной батареей и аккумулятором, как на фото.

-4

Ссылка на скетч

bme280_time_temt6000sun_web_3.0.ino

Первая моя статья, прошу сильно не ругаться, конструктивная критика приветствуется.

Продолжение следуют...

Использована информация :

Метеостанция NodeMCU на BME280 и SSD1306 с индикацией времени - Мои статьи - Компьютер и интернет - Завод горного оборудования Дарасун
Adafruit_BME280_Library/Adafruit_BME280.h at master · adafruit/Adafruit_BME280_Library