ESP8266 с BME280 в Arduino IDE (давление, температура, влажность)
Это руководство показывает, как использовать модуль датчика BME280 с ESP8266 для считывания давления, температуры, влажности и оценки высоты с помощью Arduino IDE. Датчик BME280 использует протокол связи I2C или SPI для обмена данными с микроконтроллером.
Мы покажем вам, как подключить датчик к ESP8266, установить необходимые библиотеки и написать простой скетч, который отображает показания датчика. Мы также создадим пример веб-сервера для отображения последних показаний давления, температуры и влажности.
Прежде чем приступить к этому руководству, у вас должно быть установлено дополнение ESP8266 в вашей Arduino IDE.
Вам также может быть интересно прочитать другие руководства по BME280:
Знакомство с модулем датчика BME280
Модуль датчика BME280 считывает атмосферное давление, температуру и влажность. Поскольку давление изменяется с высотой, вы также можете оценить высоту. Существует несколько версий этого модуля датчика. Мы используем модуль, показанный на рисунке ниже.
Этот датчик обменивается данными по протоколу связи I2C, поэтому подключение очень простое. Вы можете использовать стандартные выводы I2C ESP8266, как показано в следующей таблице:
BME280 |
ESP8266 |
|---|---|
Vin |
3.3V |
GND |
GND |
SCL |
GPIO 5 |
SDA |
GPIO 4 |
Существуют другие версии этого датчика, которые могут использовать протоколы связи 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 |
Необходимые компоненты
Для выполнения этого руководства вам понадобятся следующие компоненты:
ESP8266 (читайте Лучшие платы разработки ESP8266)
Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Схема подключения – ESP8266 с BME280 по I2C
Мы будем использовать протокол связи I2C с модулем датчика BME280. Для этого подключите датчик к выводам SDA и SCL ESP8266, как показано на следующей схеме.
Рекомендуемая литература: Справочное руководство по выводам ESP8266
Установка библиотеки BME280
Для получения показаний с модуля датчика BME280 вам необходимо использовать библиотеку Adafruit_BME280. Выполните следующие шаги для установки библиотеки в вашей Arduino IDE:
Откройте вашу Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться Library Manager.
Найдите «adafruit bme280» в поле поиска и установите библиотеку.
Установка библиотеки Adafruit_Sensor
Для использования библиотеки BME280 вам также необходимо установить библиотеку Adafruit_Sensor. Выполните следующие шаги для установки библиотеки в вашей Arduino IDE:
Перейдите в Sketch > Include Library > Manage Libraries и введите «Adafruit Unified Sensor» в поле поиска. Прокрутите вниз до конца, чтобы найти библиотеку, и установите её.
После установки библиотек перезапустите вашу Arduino IDE.
Считывание давления, температуры и влажности
Для считывания давления, температуры и влажности мы используем пример скетча из библиотеки.
После установки библиотеки 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.
Веб-сервер ESP8266 с датчиком BME280
Датчик BME280 измеряет температуру, влажность и давление. Таким образом, вы можете легко создать компактную метеостанцию и отслеживать показания с помощью веб-сервера, построенного на ESP8266 – именно этим мы и займёмся в этом разделе.
Скопируйте следующий код в вашу 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 с датчиком DHT11 – Асинхронный веб-сервер с автообновлением
Заключение
Эта статья представляла собой подробное руководство по получению показаний давления, температуры и влажности с датчика BME280 с помощью ESP8266 в Arduino IDE и отображению показаний на веб-сервере.
Теперь вы можете развить этот проект дальше и отобразить показания датчика на OLED-дисплее; создать регистратор данных; сохранить показания в собственной базе данных или отправить показания на вашу платформу домашней автоматизации с помощью MQTT. Вот некоторые проекты и руководства, которые могут помочь вам реализовать эти идеи:
Энергоэффективная метеостанция с регистратором данных (MicroPython)
ESP32/ESP8266: вставка данных в базу данных MySQL с помощью PHP и Arduino IDE
Узнайте больше о ESP8266 с нашим курсом: Домашняя автоматизация с использованием ESP8266