Решил поделиться опытом в создании собственной метеостанции. Часть 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 карту и вести запись измерений в нее, питаться то будет в последствии от аккумулятора.
Сейчас тестирую в домашних условиях, в планах запихнуть все это в уличный фонарь с солнечной батареей и аккумулятором, как на фото.
Ссылка на скетч
Первая моя статья, прошу сильно не ругаться, конструктивная критика приветствуется.
Продолжение следуют...
Использована информация :