Домашняя метеостанция на ESP8266 и датчике BME280

Домашняя метеостанция на ESP8266 и датчике BME280

Дата Автор 11 комментариев 38 865 просмотров

Оживляя цикл публикаций про Raspberry Pi и Arduino, хочу написать статью о сборке домашней метеостанции на основе ESP8266 и цифрового датчика BME280.

BME280 разработан в группе компаний Bosch и включает в себя термометр, барометр и гигрометр. По результатам сравнительного исследования он является наиболее точным из недорогих датчиков подобного типа, часто используемых в DIY электронике.

Себестоимость используемых компонентов составляет меньше $10, а процесс сборки устройства займет не более 1 — 1.5 часов.

Что нам понадобится

Для реализации описываемого в статье проекта понадобится:

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

Датчик BME280 (как и многие другие подключаемые модули для Arduino / ESP8266) поставляется с нераспаянными ножками. Они идут в комплекте, но подпаивать их придется самостоятельно. Для пайки могу порекомендовать вот эту паяльную пасту.

Подключение ESP8266 к ПК

Изначально я хотел написать отдельную статью о подключении плат на основе ESP8266 к компьютеру и видах прошивок для них чтобы ссылаться на эту статью в дальнейшем. Но статья «не пошла», поэтому напишу здесь вкратце, а более подробную информацию по любому из непонятных моментов можно найти в интернете.

Для того, чтобы компьютер увидел плату, нужно установить драйвер для USB-UART (USB -> COM TTL) моста. Используемые для этого моста контроллеры могут различаться в зависимости от версии платы, соответственно, будут различаться и устанавливаемые драйвера. Например, в моем случае используется модуль CH340G, но также могут использоваться модули CP2102. Хорошие, ответственные производители обычно пишут название используемого контроллера на самой плате, но их можно отличить и на глаз: CH340G — маленькая прямоугольная микросхема, а CP2102 имеет квадратную форму.

Если драйвер подобран и установлен правильно, то после подключения ESP8266 к компьютеру USB-кабелем в разделе «Порты (COM и LPT)» диспетчера устройств Windows появится новый виртуальный COM-порт, через который будет проходить обмен данными с платой.

Затем нужно загрузить на ESP8266 Arduino-совместимую прошивку от Ai-Thinker (легко находится и скачивается в интернете) через программу ESP8266Flasher.

Финальный шаг — запустить Arduino IDE и добавить поддержку ESP-модулей. После этого ESP8266 можно программировать как обычную плату Arduino.

Важный момент: не рекомендуется прикасаться к ESP8266 во включенном состоянии, особенно — если плата подключена к USB-порту компьютера. Очень легко случайно замкнуть пальцами контакты на плате, от чего в самом неудачном раскладе может сгореть как сам модуль, так и USB-порт.

Сборка схемы

Домашняя метеостанция на ESP8266 и датчике BME280

Для удобства сборки следует использовать макетные платы и DuPont-провода. И то и другое можно найти как на AliExpress, так и в оффлайновых магазинах с радиодеталями.

Подключение BME280 к ESP8266:
3V — VIN
G — GND
D5 — SCL
D6 — SDA

Подключение OLED-дисплея:
G — GND
3V — VDD
D5 — SCK
D6 — SDA

И дисплей, и датчик BME280 используют I2C-шину и потому подключаются к одним и тем же пинам.

Скетч 1: метеостанция с OLED-дисплеем

Для компиляции и загрузки скетча нужно установить в Arduino дополнительные библиотеки:

После установки в файле библиотеки BME280 нужно вручную поправить адрес с 0x77 на 0x76:

Домашняя метеостанция на ESP8266 и датчике BME280

(Установленные библиотеки Arduino IDE хранит в папке \Documents\Arduino\libraries текущего пользователя Windows)

После чего остается только скомпилировать и загрузить в память ESP8266 следующий скетч:

#include "Wire.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"
#include "SSD1306.h"

const float SEA_LEVEL_PRESSURE_HPA = 1013.25;
const int DELAY = 3000;
const int STARTUP_DELAY = 500;


Adafruit_BME280 bme;

SSD1306 display(0x3c, D6, D5);

void setup() 
{
 Serial.begin(115200);
 Wire.begin(D6, D5);
 Wire.setClock(100000); 
 if(!bme.begin())
 {
 Serial.println("Could not find a valid BME280 sensor, check wiring!");
 while (1)
 {
 yield();
 delay(DELAY);
 }
 }
 delay(STARTUP_DELAY);

display.init();
 display.flipScreenVertically();

}

void loop() 
{
 float tempC = bme.readTemperature();
 float humidity = bme.readHumidity();
 float pressurePascals = bme.readPressure();

// Print to serial monitor
 printToSerial(tempC, humidity, pressurePascals);

// Display data on screen in metric units
 drawWithMetricUnits(tempC, humidity, pressurePascals);
 yield();
 delay(DELAY);
}

void drawWithMetricUnits(float tempC, float humidity, float pressurePascals)
{
 float pressureHectoPascals = pressurePascals / 100.0;
 
 display.clear();
 
 display.drawRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
 
 display.setFont(ArialMT_Plain_16);
 display.drawString(35, 3, "BME280");
 
 display.setFont(ArialMT_Plain_10);
 display.drawString(5, 22, "Temperature = " + String(tempC) + " *C");
 display.drawString(5, 35, "Humidity = " + String(humidity) + "%");
 display.drawString(5, 48, "Pressure = " + String(pressureHectoPascals) + " h,Pa");
 
 display.display();
}

void printToSerial(float tempC, float humidity, float pressurePascals)
{
 // Temperature
 float tempF = 9.0/5.0 * tempC + 32.0;

Serial.println("Temperature:");
 printValueAndUnits(tempC, "*C");
 printValueAndUnits(tempF, "*F");
 //printValueAndUnits(tempC, "°C");
 //printValueAndUnits(tempF, "°F");
 Serial.println("");

// Barometric pressure
 float pressureHectoPascals = pressurePascals / 100.0;
 float pressureInchesOfMercury = 0.000295299830714 * pressurePascals;

Serial.println("Pressure:");
 printValueAndUnits(pressurePascals, "Pa");
 printValueAndUnits(pressureHectoPascals, "hPa");
 printValueAndUnits(pressureInchesOfMercury, "inHg");
 Serial.println("");

// Humidity
 Serial.println("Humidity:");
 printValueAndUnits(humidity, "%");
 Serial.println("");

// Approximate altitude
 float altitudeMeters = bme.readAltitude(SEA_LEVEL_PRESSURE_HPA);
 float altitudeFeet = 3.28 * altitudeMeters;
 
 Serial.println("Approx. Altitude:");
 printValueAndUnits(altitudeMeters, "m");
 printValueAndUnits(altitudeFeet, "ft");
 Serial.println();
}

void printValueAndUnits(float value, String units)
{
 Serial.print(" ");
 Serial.print(value);
 Serial.print(" ");
 Serial.println(units);
}

Вот так будет выглядеть собранное устройство в работе:

Домашняя метеостанция на ESP8266 и датчике BME280

Датчик меряет все доступные ему показатели (температура, влажность, давление) и они выводятся на экран. Показатели обновляются — обновляется информация на экране. Все.

К слову, на фотографии выше можно увидеть какой низкий уровень влажности стоит в помещении зимой в период работы центрального отопления. Низкая влажность негативно влияет на самочувствие людей и комнатных растений, а также ускоряет деградацию деревянной мебели и картин.

Регулярное отслеживание показателей микроклимата в помещении может стать первым шагом к его оздоровлению путем установки увлажнителей воздуха, термостатов и автоматических проветривателей.

Скетч 2: метеостанция с веб-сервером

Домашняя метеостанция на ESP8266 и датчике BME280

Еще один хороший вариант использование датчика BME280 — метеостанция с возможностью удаленного мониторинга через браузер.

В данном случае дисплейный модуль не задействован. ESP8266 подключается к Wi-Fi сети и поднимает веб-сервер, содержащий обновляемую показателями датчика страницу, которую можно открыть в браузере.

Хорошая статья на эту тему находится на англоязычном блоге Embedded Lab и там же можно скачать архив с готовым скетчем. Хочу только обратить внимание, что:

  • У автора той статьи задействованы пины D3 и D4, тогда как у меня D5 и D6. Можно переподключить провода как предлагает он, а можно собрать устройство по моей схеме и переправить пины в скетче.
  • Перед компиляцией скетча нужно ввести в него SSID и пароль своей Wi-Fi сети

Заключение

Вот так на основе ESP8266 и нескольких недорогих модулей можно собрать метеостанцию для домашнего использования.

Можно модернизировать схему, добавив в нее газоанализатор и датчик CO2, превратив тем самым устройство в полноценный монитор качества воздуха, точности которого будет более чем достаточно для домашнего применения.

Еще один вариант развития идеи — настроить отсылку данных с датчиков по MQTT-протоколу, благодаря чему устройство можно интегрировать в любую платформу умного дома и использовать получаемые данные для управления другими умными девайсами.

Автор статьи:
Дмитрий
Руководитель отдела в IT-компании. Веду этот блог с 2013 года, пишу о гаджетах и домашней автоматизации, обозреваю одноплатные компьютеры, неспешно собираю «умный дом».

11 комментария на «Домашняя метеостанция на ESP8266 и датчике BME280»

  1. Дмитрий, а может быть, сделаете отдельную подробную статью по созданию метеостанции на веб-сервере?

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

  2. Очень интересны такие станции, особенно, если они умеют писать в БД показания. У нас на работе была похожая, и на сайте можно было посмотреть, как меняется температура в течении времени, т.е. можно сравнить, было ли теплее например год назад

    • Видел такие в продаже, но не пробовал.
      Я читал, что OLED-дисплеи выгорают при активном использовании и сильно теряют в яркости. Если это так, то подключать дисплей отдельным модулем выходит практичнее.

  3. Спасибо за статью. Тоже хочу поднять такой проект.Есть вопрос.В своем проекте я не хочу поднимать Web-сервер на NodeMCU, а использовать для мониторинга показателей уже развернутый сервер на Raspberry.Насколько я понимаю — возможно с нода информацию отправлять сразу на малинку. Или я ошибаюсь?

    • Можно, например по MQTT-протоколу. На Raspberry Pi ставится Mosquitto и связывается с каким-нибудь сервером умного дома (они все поддерживают mqtt-устройства), а в скетч для ESP8266 добавляется функция MQTT-клиента.

      ESP8266 отправляет данные, MQTT-брокер на Raspberry Pi их получает, а сервер умного дома обрабатывает и выводит в наглядном виде (в виде графика, например, или еще как-то).

    • Эта строка рисует рамку на экране, ее можно просто закомментировать или исправьте строку на
      display.drawRect(0, 0, display.getWidth(), display.getHeight());

  4. При компиляции в Arduino IDE выдает ошибку:
    error: ‘D6’ was not declared in this scope
    13 | SSD1306 display(0x3c, D6, D5);
    | ^~
    error: ‘D5’ was not declared in this scope
    13 | SSD1306 display(0x3c, D6, D5);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

[Хамство, оскорбления и попытки крауд-маркетинга будут удалены]