ESP8266 с BME280 в Arduino IDE (давление, температура, влажность)

Это руководство показывает, как использовать модуль датчика BME280 с ESP8266 для считывания давления, температуры, влажности и оценки высоты с помощью Arduino IDE. Датчик BME280 использует протокол связи I2C или SPI для обмена данными с микроконтроллером.

ESP8266 с BME280 в Arduino IDE (давление, температура, влажность)

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

Прежде чем приступить к этому руководству, у вас должно быть установлено дополнение ESP8266 в вашей Arduino IDE.

Вам также может быть интересно прочитать другие руководства по BME280:

Знакомство с модулем датчика BME280

Модуль датчика BME280 считывает атмосферное давление, температуру и влажность. Поскольку давление изменяется с высотой, вы также можете оценить высоту. Существует несколько версий этого модуля датчика. Мы используем модуль, показанный на рисунке ниже.

Модуль датчика BME280 I2C для считывания давления, температуры и влажности

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

BME280

ESP8266

Vin

3.3V

GND

GND

SCL

GPIO 5

SDA

GPIO 4

Существуют другие версии этого датчика, которые могут использовать протоколы связи SPI или I2C, как модуль, показанный на следующем рисунке:

Модуль датчика BME280 с протоколами связи SPI или I2C

Если вы используете один из таких датчиков, для использования протокола связи I2C используйте следующие выводы:

BME280

ESP8266

SCK (вывод SCL)

GPIO 5

SDI (вывод SDA)

GPIO 4

Если вы используете протокол связи SPI, вам нужно использовать следующие выводы:

BME280

ESP8266

SCK (SPI Clock)

GPIO 14

SDO (MISO)

GPIO 12

SDI (MOSI)

GPIO 13

CS (Chip Select)

GPIO 15

Необходимые компоненты

Для выполнения этого руководства вам понадобятся следующие компоненты:

Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!

Схема подключения – ESP8266 с BME280 по I2C

Мы будем использовать протокол связи I2C с модулем датчика BME280. Для этого подключите датчик к выводам SDA и SCL ESP8266, как показано на следующей схеме.

Схема подключения ESP8266 с BME280 по I2C

Рекомендуемая литература: Справочное руководство по выводам ESP8266

Установка библиотеки BME280

Для получения показаний с модуля датчика BME280 вам необходимо использовать библиотеку Adafruit_BME280. Выполните следующие шаги для установки библиотеки в вашей Arduino IDE:

Откройте вашу Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться Library Manager.

Найдите «adafruit bme280» в поле поиска и установите библиотеку.

Установка библиотеки BME280 в Arduino IDE

Установка библиотеки Adafruit_Sensor

Для использования библиотеки BME280 вам также необходимо установить библиотеку Adafruit_Sensor. Выполните следующие шаги для установки библиотеки в вашей Arduino IDE:

Перейдите в Sketch > Include Library > Manage Libraries и введите «Adafruit Unified Sensor» в поле поиска. Прокрутите вниз до конца, чтобы найти библиотеку, и установите её.

Установка библиотеки Adafruit Unified Sensor Driver

После установки библиотек перезапустите вашу Arduino IDE.


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

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

ESP8266 с модулем датчика BME280 I2C на макетной плате

После установки библиотеки BME280 и библиотеки Adafruit_Sensor откройте Arduino IDE и перейдите в File > Examples > Adafruit BME280 library > bme280 test.

/*********
  Complete project details at https://randomnerdtutorials.com
*********/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

/*#include <SPI.h>
#define BME_SCK 14
#define BME_MISO 12
#define BME_MOSI 13
#define BME_CS 15*/

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

unsigned long delayTime;

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));

  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  Serial.println("-- Default Test --");
  delayTime = 1000;

  Serial.println();
}

void loop() {
  printValues();
  delay(delayTime);
}

void printValues() {
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");

  // Convert temperature to Fahrenheit
  /*Serial.print("Temperature = ");
  Serial.print(1.8 * bme.readTemperature() + 32);
  Serial.println(" *F");*/

  Serial.print("Pressure = ");
  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
}

Посмотреть исходный код

Мы внесли несколько изменений в скетч, чтобы сделать его полностью совместимым с ESP8266.

Как работает код

Продолжайте чтение этого раздела, чтобы узнать, как работает код, или перейдите к разделу «Демонстрация».

Библиотеки

Код начинается с подключения необходимых библиотек: библиотеки Wire для использования I2C, а также библиотек Adafruit_Sensor и Adafruit_BME280 для взаимодействия с датчиком BME280.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

Связь по SPI

Поскольку мы будем использовать связь I2C, следующие строки, определяющие выводы SPI, закомментированы:

/*#include <SPI.h>
#define BME_SCK 14
#define BME_MISO 12
#define BME_MOSI 13
#define BME_CS 15*/

Примечание: если вы используете связь SPI, используйте стандартные выводы SPI ESP8266:

MOSI

MISO

CLK

CS

GPIO 13

GPIO 12

GPIO 14

GPIO 15

Давление на уровне моря

Создаётся переменная SEALEVELPRESSURE_HPA.

#define SEALEVELPRESSURE_HPA (1013.25)

Эта переменная сохраняет давление на уровне моря в гектопаскалях (что эквивалентно миллибарам). Эта переменная используется для оценки высоты при заданном давлении путём сравнения его с давлением на уровне моря. В этом примере используется значение по умолчанию, но для более точных результатов замените это значение текущим давлением на уровне моря в вашей местности.

I2C

В этом примере по умолчанию используется протокол связи I2C. Как видите, вам нужно просто создать объект Adafruit_BME280 с именем bme.

Adafruit_BME280 bme; // I2C

Для использования SPI вам нужно закомментировать предыдущую строку и раскомментировать одну из следующих строк.

//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

setup()

В setup() запускается последовательная связь:

Serial.begin(9600);

И инициализируется датчик:

status = bme.begin(0x76);
if (!status) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
}

Мы инициализируем датчик с адресом 0x76. Если вы не получаете показания датчика, проверьте I2C-адрес вашего датчика. С датчиком BME280, подключённым к вашему ESP8266, запустите этот скетч I2C сканера, чтобы проверить адрес вашего датчика. Затем при необходимости измените адрес.

Вывод значений

В loop() функция printValues() считывает значения с BME280 и выводит результаты в Serial Monitor.

void loop() {
  printValues();
  delay(delayTime);
}

Считывание температуры, влажности, давления и оценка высоты так же просто, как использование следующих методов объекта bme:

  • bme.readTemperature() – считывает температуру в градусах Цельсия;

  • bme.readHumidity() – считывает абсолютную влажность;

  • bme.readPressure() – считывает давление в гПа (гектоПаскали = миллибары);

  • bme.readAltitude(SEALEVELPRESSURE_HPA) – оценивает высоту в метрах на основе давления на уровне моря.

Демонстрация

Загрузите код в ваш ESP8266 и откройте Serial Monitor на скорости 9600 бод. Нажмите кнопку RST на плате, чтобы запустить код. Вы должны увидеть показания, отображаемые в Serial Monitor.

Вывод показаний давления, температуры и влажности BME280 с ESP32 в Serial Monitor Arduino IDE

Веб-сервер ESP8266 с датчиком BME280

Датчик BME280 измеряет температуру, влажность и давление. Таким образом, вы можете легко создать компактную метеостанцию и отслеживать показания с помощью веб-сервера, построенного на ESP8266 – именно этим мы и займёмся в этом разделе.

Веб-сервер ESP8266 с датчиком BME280 в Arduino IDE

Скопируйте следующий код в вашу Arduino IDE. Пока не загружайте его. Сначала вам нужно указать ваши SSID и пароль.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com
*********/

// Load Wi-Fi library
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

//uncomment the following lines if you're using SPI
/*#include <SPI.h>
#define BME_SCK 14
#define BME_MISO 12
#define BME_MOSI 13
#define BME_CS 15*/

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

void setup() {
  Serial.begin(115200);
  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  //status = bme.begin();
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the table
            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
            client.println("table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }");
            client.println("th { padding: 12px; background-color: #0043af; color: white; }");
            client.println("tr { border: 1px solid #ddd; padding: 12px; }");
            client.println("tr:hover { background-color: #bcbcbc; }");
            client.println("td { border: none; padding: 12px; }");
            client.println(".sensor { color:white; font-weight: bold; background-color: #bcbcbc; padding: 1px; }");

            // Web Page Heading
            client.println("</style></head><body><h1>ESP8266 with BME280</h1>");
            client.println("<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>");
            client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
            client.println(bme.readTemperature());
            client.println(" *C</span></td></tr>");
            client.println("<tr><td>Temp. Fahrenheit</td><td><span class=\"sensor\">");
            client.println(1.8 * bme.readTemperature() + 32);
            client.println(" *F</span></td></tr>");
            client.println("<tr><td>Pressure</td><td><span class=\"sensor\">");
            client.println(bme.readPressure() / 100.0F);
            client.println(" hPa</span></td></tr>");
            client.println("<tr><td>Approx. Altitude</td><td><span class=\"sensor\">");
            client.println(bme.readAltitude(SEALEVELPRESSURE_HPA));
            client.println(" m</span></td></tr>");
            client.println("<tr><td>Humidity</td><td><span class=\"sensor\">");
            client.println(bme.readHumidity());
            client.println(" %</span></td></tr>");
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Посмотреть исходный код

Как работает код

Продолжайте чтение этого раздела, чтобы узнать, как работает код, или перейдите к разделу «Демонстрация».

Этот скетч очень похож на скетч, использованный в руководстве по веб-серверу ESP8266. Сначала вы подключаете библиотеку ESP8266WiFi и необходимые библиотеки для чтения данных с датчика BME280.

// Load Wi-Fi library
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

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

#define SEALEVELPRESSURE_HPA (1013.25)

В следующей строке вы создаёте объект Adafruit_BME280 с именем bme, который по умолчанию устанавливает связь с датчиком по I2C.

Adafruit_BME280 bme; // I2C

Как упоминалось ранее, вам нужно вставить ваши ssid и password в следующие строки внутри двойных кавычек.

const char* ssid     = "";
const char* password = "";

Затем вы устанавливаете порт веб-сервера на 80.

// Set web server port number to 80
WiFiServer server(80);

Следующая строка создаёт переменную для хранения заголовка HTTP-запроса:

String header;

setup()

В setup() мы запускаем последовательную связь на скорости 115200 бод для целей отладки.

Serial.begin(115200);

Вы проверяете, что датчик BME280 был успешно инициализирован.

if (!bme.begin(0x76)) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);

Следующие строки инициируют Wi-Fi соединение с помощью WiFi.begin(ssid, password), ожидают успешного подключения и выводят IP-адрес ESP в Serial Monitor.

// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();

loop()

В loop() мы программируем, что происходит, когда новый клиент устанавливает соединение с веб-сервером. ESP постоянно прослушивает входящих клиентов с помощью этой строки:

WiFiClient client = server.available(); // Listen for incoming clients

Когда запрос получен от клиента, мы сохраняем входящие данные. Цикл while, следующий далее, будет выполняться, пока клиент остаётся подключённым.

if (client) { // If a new client connects,
  Serial.println("New Client."); // print a message out in the serial port
  String currentLine = ""; // make a String to hold incoming data from the client
  while (client.connected()) { // loop while the client's connected
    if (client.available()) { // if there's bytes to read from the client,
      char c = client.read(); // read a byte, then
      Serial.write(c); // print it out the serial monitor
      header += c;
      if (c == '\n') { // if the byte is a newline character
        // if the current line is blank, you got two newline characters in a row.
        // that's the end of the client HTTP request, so send a response:
        if (currentLine.length() == 0) {
          // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
          // and a content-type so the client knows what's coming, then a blank line:
          client.println("HTTP/1.1 200 OK");
          client.println("Content-type:text/html");
          client.println("Connection: close");
          client.println();

Отображение HTML веб-страницы

Следующее, что вам нужно сделать, это отправить ответ клиенту с HTML-текстом для построения веб-страницы.

Веб-страница отправляется клиенту с помощью выражения client.println(). В качестве аргумента вы должны указать то, что хотите отправить клиенту.

Следующий фрагмент кода отправляет веб-страницу для отображения показаний датчика в таблице.

client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
client.println("table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }");
client.println("th { padding: 12px; background-color: #0043af; color: white; }");
client.println("tr { border: 1px solid #ddd; padding: 12px; }");
client.println("tr:hover { background-color: #bcbcbc; }");
client.println("td { border: none; padding: 12px; }");
client.println(".sensor { color:white; font-weight: bold; background-color: #bcbcbc; padding: 1px; }");

// Web Page Heading
client.println("</style></head><body><h1>ESP32 with BME280</h1>");
client.println("<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>");
client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
client.println(bme.readTemperature());
client.println(" *C</span></td></tr>");
client.println("<tr><td>Temp. Fahrenheit</td><td><span class=\"sensor\">");
client.println(1.8 * bme.readTemperature() + 32);
client.println(" *F</span></td></tr>");
client.println("<tr><td>Pressure</td><td><span class=\"sensor\">");
client.println(bme.readPressure() / 100.0F);
client.println(" hPa</span></td></tr>");
client.println("<tr><td>Approx. Altitude</td><td><span class=\"sensor\">");
client.println(bme.readAltitude(SEALEVELPRESSURE_HPA));
client.println(" m</span></td></tr>");
client.println("<tr><td>Humidity</td><td><span class=\"sensor\">");
client.println(bme.readHumidity());
client.println(" %</span></td></tr>");
client.println("</body></html>");

Примечание: вы можете нажать здесь, чтобы просмотреть полную HTML веб-страницу.

Отображение показаний датчика

Для отображения показаний датчика в таблице нам нужно просто отправить их между соответствующими тегами <td> и </td>. Например, для отображения температуры:

client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
client.println(bme.readTemperature());
client.println(" *C</span></td></tr>");

Примечание: тег <span> полезен для стилизации определённой части текста. В данном случае мы используем тег <span>, чтобы включить показания датчика в класс «sensor». Это удобно для стилизации этой конкретной части текста с помощью CSS.

По умолчанию таблица отображает показания температуры как в градусах Цельсия, так и в градусах Фаренгейта. Вы можете закомментировать следующие три строки, если хотите отображать температуру только в градусах Фаренгейта.

/*client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
client.println(bme.readTemperature());
client.println(" *C</span></td></tr>");*/

Закрытие соединения

Наконец, когда ответ заканчивается, мы очищаем переменную header и останавливаем соединение с клиентом с помощью client.stop().

// Clear the header variable
header = "";
// Close the connection
client.stop();

Демонстрация веб-сервера

После ввода ваших сетевых учётных данных вы можете загрузить код на вашу плату.

Убедитесь, что выбрана правильная плата и COM-порт, и загрузите код в ваш ESP8266. После загрузки откройте Serial Monitor на скорости 115200 бод и скопируйте IP-адрес ESP8266.

IP-адрес ESP8266 в Serial Monitor

Откройте ваш браузер, вставьте IP-адрес, и вы должны увидеть последние показания датчика.

Демонстрация веб-сервера BME280 с ESP8266

Для обновления показаний вам просто нужно обновить веб-страницу.

Вам также может понравиться: ESP8266 с датчиком DHT11 – Асинхронный веб-сервер с автообновлением

Заключение

Эта статья представляла собой подробное руководство по получению показаний давления, температуры и влажности с датчика BME280 с помощью ESP8266 в Arduino IDE и отображению показаний на веб-сервере.

Теперь вы можете развить этот проект дальше и отобразить показания датчика на OLED-дисплее; создать регистратор данных; сохранить показания в собственной базе данных или отправить показания на вашу платформу домашней автоматизации с помощью MQTT. Вот некоторые проекты и руководства, которые могут помочь вам реализовать эти идеи:

Узнайте больше о ESP8266 с нашим курсом: Домашняя автоматизация с использованием ESP8266