Arduino и метеодатчик BME280/BMP280
BME280 – высокоточный метеодатчик, измеряющий такие параметры микроклимата как температура, влажность и атмосферное давление. В зависимости от модуля может подключаться к I2C и SPI шинами микроконтроллера и работать от 3-5V, если на плате есть стабилизатор, или 3V, если его нет.
На обратной стороне платы не просто так написано BME280/BMP280 – BMP является урезанной версией BME, в которой нет влажности. Как их различить, если недобросовестный китаец не поставил галочку? По корпусу датчика:

В наборе GyverKIT первых партий (все наборы 2021 года) шёл BME280 версии I2C 5V, но старт продаж набора совпал с мировым кризисом микросхем, из за которого датчик стал сильно дефицитным и китайцы начали хитрить. В наборах GyverKIT 000, 001 и 002 партий можно встретить:
- Рабочий BME280
- Рабочий BMP280
- Нерабочий BMP280
В партии 003 у нас рабочий BMP280. Для влажности используется другой датчик.
Мы приносим свои извинения за эту ситуацию, вы можете запросить возврат средств за модуль у магазина Giant4.
Подключение
Модуль подключается на шину I2C и питание, как и любой другой модуль такого типа:

Библиотеки
- Adafruit BME280 (для работы также нужна Adafruit Sensor) – самая известная библиотека для работы с BME280. Очень тяжёлая, часть настроек доступна только при ручном редактировании библиотеки.
- GyverBME280 – наша библиотека, более удобная и лёгкая. Также поддерживает датчики BMP280
В примерах на этом сайте мы будем использовать GyverBME280. Библиотека идёт в архиве к набору GyverKIT, а свежую версию всегда можно установить/обновить из встроенного менеджера библиотек Arduino по названию GyverBME280. Краткая документация находится по ссылке выше, базовые примеры есть в самой библиотеке.
Примеры
Первым делом стоит удостовериться в работоспособности датчика и узнать его адрес, он может быть 0x77 и 0x76 . Загружаем следующий код:
#include void setup() < Serial.begin(9600); Serial.println("Start scan"); >void loop() < for (uint8_t i = 1; i < 128; i++) < Wire.beginTransmission(i); if (!Wire.endTransmission()) Serial.println(i, HEX); >Serial.println(". "); delay(5000); >
Открываем монитор порта:
- Если вывелось только Start scan и ничего больше – датчик бракованный и не будет работать
- Если это рабочий BMP/BME – получим вывод такого вида:
Значит датчик ответил по адресу 0x76. Может ответить по 0x77.
- Если вывод имеет вид
Значит Ардуино не находит датчиков на линии. Либо датчик подключен неправильно, либо бракованный.
Далее откроем базовый пример из библиотеки, который опрашивает значения с датчика. В begin() можно передать адрес, который мы узнали из предыдущего скетча-сканера (не забываем префикс 0x). Загружаем и открываем порт:
#include GyverBME280 bme; void setup() < Serial.begin(9600); Serial.println("Start"); // запуск датчика и проверка на работоспособность if (!bme.begin(0x76)) Serial.println("Error!"); >void loop() < // температура Serial.print("Temperature: "); Serial.println(bme.readTemperature()); // влажность Serial.print("Humidity: "); Serial.println(bme.readHumidity()); // давление Serial.print("Pressure: "); Serial.println(bme.readPressure()); Serial.println(); delay(1000); >
- Если выведется только слово Start – датчик бракованный и из-за этого программа зависла
- Если выведется Error! – датчик бракованный или адрес не соответствует, вернись к предыдущему пункту
- Корректно выводятся все три параметра
Start
Temperature: 24.78
Humidity: 41.69
Pressure: 99701.28
Датчик рабочий, и это BME280
- Выводится температура и давление, влажность – 0
Start
Temperature: 24.78
Humidity: 0
Pressure: 99701.28
Датчик рабочий, и это BMP280, т.е. без влажности.
STM Урок 121. Датчик температуры, давления и влажности BME280. Часть 1
На данном занятии мы по многочисленным просьбам рассмотрим датчик от компании Bosch Sensortec — BME280.
Данный датчик измеряет несколько очень важных величин окружающей среды — это температура, влажность воздуха, а также атмосферное давление.
Есть ещё подобный датчик — BMP280, который также измеряет данные величины, но только кроме влажности. Но зато стоит он гораздо дешевле.
Но так как просьбы были именно рассмотреть датчик BME280, то им мы и займёмся.
Помимо того, что датчик измеряет все эти вышеперечисленные величины, он также умеет фильтровать шумы, в него встроена очень тонкая калибровка показаний, в то же время все эти работы он проделывает блестяще и очень быстро. Также в отличие от предыдущих подобных рассмотренных нами датчиков, данный датчик проделывает все эти измерения не только быстро, но и в более широких диапазонах. Например, многие датчики не умеют измерять влажность воздуха менее 20 процентов.
Выглядит датчик следующим образом (нажмите на картинку для увеличения изображения)

И, прежде чем приступить к программированию и подключению данного датчика, мы кратко познакомимся с его основными характеристиками. Если кому-то интересно узнать подробно, то вся информация присутствует на официальном сайте компании Bosch Sensortec.
Пока начнём с того, как данный датчик подключить к контроллеру. Он может подключаться как с помощью шины SPI, так и с помощью шины I2C. Мы же будем подключать его именно по шине I2C, так как мне в руки попал модуль с данным датчиком, который подключается только посредством I2C и интерфейс SPI в нём от датчика на внешние контакты не выведен. Выглядит данный модуль следующим образом


По шине SPI датчик можно тактировать частотой до 10 мегагерц, а по шине I2C — до 3,4 мегагерц
Питать данный модуль можно от 1,71 вольт до 3,6 вольт.
Порт ввода-вывода датчика питается в диапазоне 1,2 — 3,6 В (существует для этого отдельная ножка питания).
Ток потребления датчика:
при измерении влажности и температуры при частоте дискретизации 1 герц — 1,8 мкА,
при измерении давления и температуры при частоте дискретизации 1 герц — 2,8 мкА,
при измерении давления, влажности и температуры при частоте дискретизации 1 герц — 3,6 мкА,
в спящем режиме — 0,1 мкА.
Мы видим, что такие токи у нас будут иметь место только при семплировании 1 герц, без оверсемплинга (передискретизации). А если мы применим какие-нибудь фильтры, то на выходе уже будет совершенно другая частота, в силу вступят коэффициенты фильтрации. Поэтому в таком случае данные токи потребления будут наблюдаться уже при меньшей частоте измерений.
Диапазоны измерения: температуры — -40 … +85 °C, влажности — 0 … 100 %, давления — 300 … 1100 hPa.
Конечно в различных диапазонах точность измерения будет разная.
Например, точность измерения влажности ±3 %RH обеспечивается только в диапазоне 20…80 %RH, а точность измерения давления ±1.0 hPa — в диапазоне 300 … 1100 hPa (то есть во всём диапазоне). Точность измерения температуры ±0.5 °C (при 25 °C),
Шумит датчик следующим образом:
Влажность: 0,07% — без применения оверсемплинга, при максимальном оверсемплинге шумы снижаются до 0,02%.
Давление: 1,3 Pa — без применения оверсемплинга и фильтров, при максимальных оверсемплинге и фильтрации снижаются до 0,2 Pa.
Температура: 0,005 °C — без применения оверсемплинга и фильтров, при максимальных оверсемплинге и фильтрации снижаютя до 0,002 °C.
Теперь посмотрим назначение контактов датчика

Vdd — аналоговое питание;
GND — общий провод;
Vddio — питание цифрового тракта;
SDO — выход цифрового сигнала при использовании 4-проводного режима SPI, при использовании режима I2C — шина адреса (если соединен с общим проводом, то логический ноль в нулевом бите адреса, если с питанием — то логическая 1);
GND — общий провод;
CSB — контакт CS (chip select) при использовании режима SPI;
SDI — вход цифрового сигнала при использовании 4-проводного режима SPI, вход и выход цифрового сигнала при использовании 3-проводного режима SPI и режима I2C;
SCK — шина тактирования цифрового сигнала.
Также у датчика существует масса различных регистров, с которыми подробно мы будем знакомиться при написании кода.
Вот так организована память в датчике (нажмите на картинку для увеличения изображения)

Также следует отметить, что датчик может находиться в трёх режимах: в нормальном (NORMAL MODE), в спящем (SLEEP MODE) и в принудительном (FORCE MODE).
Ну со спящим режимом всё ясно. А чем же отличается нормальный от принудительного?
В нормальном режиме после считывания значений с датчика последний остаётся в этом режиме и дальше, а вот в принудительном, когда мы считаем значения, датчик автоматически переходит в спящий режим. И, чтобы нам опять считывать показатели, нам надо заново инициализировать либо нормальный либо принудительный режимы.
Данная диаграмма как нельзя лучше показывает нам это

Теперь схема подключения.
Модуль с датчиком мы подключим к плате Nucleo STM32F401RE. также к информационным контактам I2C мы подключим логический анализатор, чтобы смотреть, как наш датчик будет откликаться на команды. Затем, как только приём наладится, мы к плате также по I2C подключим символьный дисплей LCD2004.
Вот так выглядит наша схема без дисплея (нажмите на картинку для увеличения изображения)

Создадим новый проект в Cube MX и выберем контроллер

Включим тактирование контроллера

Затем включим отладчик

Включим шину I2C для подключения датчика

Переопределим ножки для удобства подключения датчика

Давайте заодно сразу включим и шину для подключения дисплея

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

Включим также на выход ножку светодиода

Перейдём в System Configuration и настроим следующие частоты (нажмите на картинку для увеличения изображения)

Перейдём в Configuration и настроим I2C для датчика

На всякий случай включим прерывания, вдруг пригодятся

Зайдём в настройки другой шины I2C и убедимся, что там всё правильно

Зайдём в настройки проекта, выберем среду программирования, папку проекта и назовём наш проект

Сохраним настройки проекта, сгенерируем проект для Keil, откроем его в нём, затем настроим программатор на автоперезагрузку, установим уровень оптимизации в 1 и попробуем собрать проект.
Если всё нормально собралось, то продолжим.
Откроем файл main.c и подключим библиотеку для работу со строками
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
Добавим глобальный строковый массив
char str1[ 100 ];
/* USER CODE END PV */
Создадим модуль для нашей новой библиотеке работы с датчиком в виде двух файлов BME280.h и BME280.c следующего содержимого
BME280.h:
#ifndef BME280_H_
#define BME280_H_
#include «stm32f4xx_hal.h»
#endif /* BME280_H_ */
BME280.c:
#include «BME280.h»
extern I2C_HandleTypeDef hi2c1;
extern UART_HandleTypeDef huart2;
extern char str1[ 100 ];
Подключим модуль в файле main.c
#include «BME280.h»
В следующей части урока мы начнём писать инициализацию датчика, в которой считаем идентификатор, калибровочные данные из датчика, также настроим тайминг режима Standby.
Отладочную плату можно приобрести здесь Nucleo STM32F401RE
Логический анализатор 16 каналов можно приобрести здесь
Датчик температуры, давления и влажности BME280 можно приобрести здесь BME280
Дисплей LCD 20×4 можно приобрести тут: LCD 20×4
Переходник I2C to LCD1602 2004 можно приобрести здесь: I2C to LCD1602 2004
Смотреть ВИДЕОУРОК (нажмите на картинку)
Bme280 высота относительно чего
Мини-метеостанция на ESP32 (Arduino) и BME280 с выводом данных на дисплей DWIN.
В этом проекте сделаем мини-метеостанцию используя ESP32 (Arduino) и датчик барометрического давления BME280, который может предоставлять информацию об атмосферном давлении, температуре и влажности в режиме реального времени. С помощью BME280 также можно измерить высоту над уровнем моря. Полученные значения выведем на дисплей DWIN.
Кратко о датчиках давления, температуры и влажности BME280 (BMP280).
BME280 довольно прост в использовании, предварительно откалиброван и не требует дополнительных компонентов. Его достаточно подключить к микроконтроллеру и начать измерение относительной влажности, температуры и атмосферного давления.

Виды датчиков BME280 (BMP280).
Датчик BME280 имеет несколько разновидностей и в зависимости от модуля может подключаться к I2C и SPI шинами микроконтроллера и работать от 3-5В.
Как узнать, какое рабочее напряжение модуля? Если на плате есть стабилизатор, его можно запитать от источника напряжением 5В. Если на плате нет стабилизатора, то подключить можно только к источнику питания 3В.


На обратной стороне платы не просто так написано BME280/BMP280 – BMP является урезанной версией BME, в которой нет влажности. Как их различить, если недобросовестный продавец не поставил галочку? Они отличаются по корпусу датчика:Информация о типах модулей взята с сайта.
Датчики я покупал себе с сопутствующим товаром на будущее и информацию предварительно не почитал. Я повёлся на низкую стоимость и в результате стал счастливым обладателем BMP280. Кстати, покупал 2 модуля, и галочки нет ни на одном. Это, конечно, не критично, но есть некоторые сложности с тем, чтобы заставить датчик работать. Помогла библиотека Гайвера.
Распиновка модуля BME280 без стабилизатора на борту.

Интерфейс BME280 I2C использует следующие контакты:
- VCC: от 1,71 В до 3,6 В
- GND: подключение к GND
- SCL: последовательные часы (SCK)
- SDA: последовательные данные (SDI)
- CSB: должен быть подключен на VDDIO, чтобы выбрать интерфейс I2C.
- SDO: контакт определяет I2C адрес устройства. Если SDO подключается к GND (0), то адрес равен 0x76. Если он подключается к VDDIO(1), то адрес равен 0x77. В этом модуле мы подключили его к VDDIO, поэтому адрес должен быть 0x77.
Интерфейс I2C.
Модуль оснащён простым двухпроводным интерфейсом I2C, который можно легко соединить с любым выводом I2C микроконтроллера. Адрес I2C модуля BME280 по умолчанию 0x76, и его можно легко изменить на 0x77.
На рынке доступен ещё один модуль, который имеет только 4 контакта. Чтобы изменить его адрес I2C, найдите перемычку для пайки рядом с микросхемой.

Благодаря данной перемычке можно изменить адрес I2C.

По умолчанию средний медный контакт площадки подключён к левой контактной площадке. Поэтому вам нужно поцарапать соединение между средней и левой медными контактными площадками, чтобы отсоединить их. Затем вы можете добавить каплю припоя между средней и правой медными площадками, чтобы соединить их. Это позволит вам установить адрес I2C 0x77.
При необходимости мы можем изменить адрес датчика и подключить 2 модуля к одному микроконтроллеру.
Схема подключения дисплея DWIN, модуля BME280 к ESP32.
Датчик барометрического давления BME280 взаимодействует с ESP32 для создания простой мини-метеостанции.

Подключите контакты SDA SCL BME280 к соответствующим контактам ESP32, то есть к контактам GPIO22 и GPIO21 соответственно. Дисплей DWIN подключаем ко второму UART порту ESP32, то есть к контактам GPIO16 и GPIO17.
Библиотека для работы с BME280.
Самая распространённая библиотека для работы с BME280 является Adafruit BME280 (для работы также нужно установить Adafruit Sensor). Но она не работает с BMP280, поэтому пришлось искать альтернативное решение.
GyverBME280 – библиотека более удобная и лёгкая. Также поддерживает датчики BMP280. То, что мне требовалось для данного проекта.

Библиотеку можно установить через менеджер библиотек или скачать с официального сайта разработчика. Также прикреплю библиотеку внизу статьи в разделе «Файлы для скачивания».
Код метеостанции на DWIN, модуле BME280 и ESP32.
В коде менять ничего не нужно. Максимум посмотреть, чтобы был выключен DEBUG. В противном случае вместо влажности воздуха у вас будет выводиться информация со счётчика. Счётчик я добавил для того, чтобы можно было отследить, что всё работает и информация обновляется на дисплее. А также в связи с тем, что у меня датчик BMP280 и значение влажности выводит 0.

Остальные данные меняйте по мере необходимости. Например, адрес устройства по умолчанию 0x76. Возможно, вам нужно будет поменять на 0x77.

Прошивка для дисплея DWIN.
Для данного проекта подайте дисплей без сенсора. Благо, практически для всех моделей дисплеев DWIN доступна версия без сенсора.

Для вывода информации будем использовать всего один инструмент — «Data variables». С данным инструментом мы уже знакомы из проекта «Панель управления подсветкой на дисплее DWIN».

Но его мы использовали только для вывода целочисленных значений. Сегодня в проекте будем выводить дробные значения.

Для этого данные для вывода нужно настроить следующим образом.

Как видим, настройки изменились не сильно. Аналогичным образом выводим все остальные параметры.
Мини-метеостанция на Arduino и BME280 с выводом данных на дисплей DWIN.
И если у вас нет в наличии ESP32, можно сделать проект, используя классическую отладочную плату Arduino UNO или Arduino NANO.

Код для Arduino NANO (UNO).
Внизу статьи в разделе «файлы для скачивания» вы можете скачать код для Arduino NANO (UNO). Обратите внимание, что данный код я не тестировал на железе. Если у вас будут вопросы, пишите в комментариях.

Схема подключения дисплея DWIN и модуля BME280 к Arduino NANO.

Подключаем электронику дисплея DWIN, модуля BME280 к Arduino NANO по схеме.
Вывод.
Получается простая метеостанция. Но я сделал данный проект в первую очередь для демонстрации вывода целочисленных значений больше 255 и дробных значений. В проекте написаны небольшие функции, которые помогут реализовать вывод дробных и целочисленных значений. В дальнейшем планирую сделать более интересные проекты с использованием полученных знаний в данном проекте.
Приобрести дисплей DWIN можно в официальном магазине DWIN Technology на AliExpress.
Понравился проект Мини-метеостанция на ESP32 (Arduino) и BME280 с выводом данных на дисплей DWIN? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте.
Подключение датчика BME280 к Arduino

В этом руководстве мы подробно разберем, как использовать модуль датчика BME280 с Arduino для считывания давления, температуры, влажности и оценки высоты. Вы узнаете как подключить датчик, установить необходимые библиотеки и написать простой скетч для отображения показаний датчика.
Обзор модуля датчика BME280
Датчик BME280 считывает барометрическое давление, температуру и влажность. Также, поскольку давление меняется с высотой, можно также примерно оценить и высоту. Существует несколько версий этого модуля, различающихся используемым протоколом связи I2C или SPI для обмена данными с микроконтроллером.
BME280 c I2C интерфесом

Этот датчик использует протокол связи I2C, поэтому подключение очень простое. Вы подключаете датчик BME280 к контактам Arduino, как показано в таблице ниже:
| BME280 | Arduino UNO | Arduino MINI | Arduino Mega | Arduino Micro | Arduino Nano |
| VIN | 5V | 5V | 5V | 5V | 5V |
| GND | GND | GND | GND | GND | GND |
| SCL | A5 | A7 | 21 | 1 | A5 |
| SDA | A4 | A6 | 20 | 2 | A4 |
BME280 с SPI интерфейсом
Существуют и другие версии этого датчика, которые могут использовать протоколы связи SPI или I2C, например, модуль, показанный на следующем рисунке:

Для подключения датчика по SPI подключите его к следующим контактам Arduino
| BME280 | Arduino Nano | Arduino UNO | Arduino Mega | Arduino Mini |
| SCK (SPI Clock) | Pin 13 | Pin 13 | Pin 52 | Pin 17 |
| SDO (MISO) | Pin 12 | Pin 12 | Pin 50 | Pin 16 |
| SDI (MOSI) | Pin 11 | Pin 11 | Pin 51 | Pin 15 |
| CS (Chip Select) | Pin 10 | Pin 10 | Pin 53 | Pin 14 |
Схема подключения
Подключите датчик BME280 к плате Arduino, как показано на следующей принципиальной схеме.

Установка необходимых библиотек
Для считывания показаний датчика нам нужно установить в Arduino IDE несколько дополнительных библиотек. Это Adafruit_BME280 и Adafruit Unified Sensor. Как это сделать мы сейчас подробно рассмотрим.
Установка библиотеки Adafruit BME280
Чтобы получить показания от модуля датчика BME280, вам необходимо использовать библиотеку Adafruit_BME280. Выполните следующие шаги, чтобы установить её в Arduino IDE:
Перейдите в Скетч> Подключить библиотеку> Управление библиотеками. Должен открыться менеджер библиотек.
Найдите “adafruit bme280” в окне поиска и установите её.

Установка библиотеки Adafruit Unifed Sensor
Чтобы использовать библиотеку BME280, вам также необходимо установить библиотеку Adafruit_Sensor. Выполните следующие шаги, чтобы установить её в Arduino IDE:
Перейдите в Скетч> Подключить библиотеку> Управление библиотеками. Должен открыться менеджер библиотек. Введите “Adafruit Unified Sensor” в поле поиска. Прокрутите до конца, чтобы найти библиотеку и установить её.

После установки библиотек перезапустите Arduino IDE.
Считывание давления, температуры и влажности
Чтобы прочитать давление, температуру и влажность, мы будем использовать пример скетча из библиотеки. Для этого откройте Arduino IDE и перейдите в Файл> Примеры> Adafruit BME280 Library> bme280test.
Как работает код
В данном разделе мы подробно разберем как работает код данной программы
Подключение библиотек и первичная настройка
Код начинается с включения необходимых библиотек: библиотеки wire для использования I2Cибиблиотек Adafruit_Sensor и Adafruit_BME280 для взаимодействия с датчиком BME280.
Поскольку мы собираемся использовать интерфейс I2C, следующие строки, определяющие выводы SPI, можно закомментировать
Далее создаем переменную SEALEVELPRESSURE_HPA
Эта переменная сохраняет давление на уровне моря в гектопаскалях (эквивалентно милибару). Эта переменная используется для оценки высоты для данного давления путем сравнения его с давлением на уровне моря. В этом примере используется значение по умолчанию, но для получения более точных результатов замените это значение текущим давлением на уровне моря в вашем регионе.
В этом примере по умолчанию используется протокол связи I2C. Как вы можете видеть, вам просто нужно создать объект Adafruit_BME280 с именем bme.
Чтобы использовать SPI, вам нужно закомментировать предыдущую строку и раскомментировать одну из следующих строк.
Раздел Setup()
В setup () запускаем последовательный порт со скоростью 9600 бод:
И инициализируем датчик
Вывод значений
В цикле loop() функция printValues() считывает значения с BME280 и выводит результаты в монитор последовательного порта.
Считывание температуры, влажности, давления и оценки высоты выполняем используя следующие методы объекта bme:
- bme.readTemperature() – считывает температуру в градусах Цельсия;
- bme.readHumidity() – считывает абсолютную влажность;
- bme.readPressure() – считывает давление в ГПа (гектопаскаль = миллибар);
- bme.readAltitude(SEALEVELPRESSURE_HPA) – оценивает высоту в метрах на основе давления на уровне моря.
Демонстрация работы

Загрузите скетч в плату Arduino

Откройте монитор последовательного порта со скоростью передачи данных 9600 бод.

Если все предыдущие шаги были выполнены верно вы должны увидеть показания датчиков

Подведение итогов
BME280 обеспечивает простой и недорогой способ получения показаний давления, температуры и влажности. Датчик взаимодействует через протокол связи I2C, что означает, что вам просто нужно подключить датчик к контактам Arduino I2C.
Написание кода для получения показаний датчика также очень просто благодаря библиотеке BME280_Adafruit. Вам просто нужно использовать методы readTemperature(), readHumidity() и readPressure(). Вы также можете оценить высоту, используя метод readAltitude().
STM Урок 121. Датчик температуры, давления и влажности BME280. Часть 4
В предыдущей части урока мы настроили фильтр и оверсемплинги, а также считали с датчика значение температуры воздуха.

Так как давление хранится таким же образом, как и температура, то перейдём в соответствующую функцию BME280_ReadPressure и причитаем там подобным образом сырые показатели давления, только опять же неукоснительно следуя требованиям технической документации, мы сначала прочитаем температуру, так как показания температуры участвуют в расчёте атмосферного давления
float press_float = 0.0 f;
uint32_t press_raw, pres_int;
BME280_ReadTemperature(); // must be done first to get t_fine
BME280_ReadReg_BE_U24(BME280_REGISTER_PRESSUREDATA,&press_raw);
press_raw >>= 4 ;
Думаю, можно в терминальной программе, сырые показатели не смотреть и не тратить на это время, всё будет нормально, я это уже не раз проверил.
Поэтому сначала добавим локальные переменные для промежуточных расчётов
uint32_t press_raw, pres_int;
int64_t val1, val2, p;
И затем рассчитаем давление, следуя примеру из даташита
val1 = (( int64_t ) temper_int) — 128000 ;
val2 = val1 * val1 * ( int64_t )CalibData.dig_P6;
val2 = val2 + ((val1 * ( int64_t )CalibData.dig_P5)
val2 = val2 + (( int64_t )CalibData.dig_P4
val1 = ((val1 * val1 * ( int64_t )CalibData.dig_P3) >> 8 ) + ((val1 * ( int64_t )CalibData.dig_P2)
return 0 ; // avoid exception caused by division by zero
p = 1048576 — press_raw;
val1 = ((( int64_t )CalibData.dig_P9) * (p >> 13 ) * (p >> 13 )) >> 25 ;
val2 = ((( int64_t )CalibData.dig_P8) * p) >> 19 ;
p = ((p + val1 + val2) >> 8 ) + (( int64_t )CalibData.dig_P7
pres_int = ((p >> 8 ) * 1000 ) + (((p & 0xff ) * 390625 ) / 100000 );
press_float = pres_int / 100.0 f;
Перейдём в функцию main() файла main.c и в бесконечном цикле также прочитаем и отобразим давление в различных величинах
pf = BME280_ReadPressure();
sprintf(str1, «Pressure: %.3f Pa; %.3f hPa; %.3f mmHg\r\n» , pf, pf/ 1000.0 f, pf * 0.000750061683 f);
Соберём код, прошьём контроллер и посмотрим результат работы кода функции считывания и расчёта атмосферного давления

Теперь вернёмся в файл BME280.c и напишем тело функции расчёта величины высоты над уровнем моря (данная величина зависит от атмосферного давления, хотя, признаться, зависимость эта, как мной замечено, непостоянная. Вернее непостоянная получается на выходе величина высоты над уровнем моря)
float att = 0.0 f;
float atm = BME280_ReadPressure();
att = 44330.0 * ( 1.0 — pow (atm / seaLevel, 0.1903 ));
Теперь нам нужны будут ещё некоторые коэффициенты.
Перейдём в заголовочный файл BME280.h и добавим для них макросы
#define LED_TGL HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN)
#define SEALEVELPRESSURE_HPA (1013.25)
#define SEALEVELPRESSURE_PA (1013250)
Перейдём в функцию main() файла main.c и в бесконечном цикле также вычислим и отобразим высоту над уровнем моря
af = BME280_ReadAltitude(SEALEVELPRESSURE_PA);
sprintf(str1, «Altitude: %.3f m\r\n» , af);
Соберём код, прошьём контроллер и посмотрим результат в терминальной программе

Осталось нам прочитать только влажность.
Для этого вернёмся в файл BME280.c в функцию BME280_ReadHumidity и попробуем пока прочитать сырое значение из регистра, который у нас двухбайтный

float hum_float = 0.0 f;
int16_t hum_raw;
BME280_ReadTemperature(); // must be done first to get t_fine
BME280_ReadReg_S16(BME280_REGISTER_HUMIDDATA,&hum_raw);
sprintf(str1, «Humidity RAW: 0x%08X\r\n» , hum_raw);
Также и здесь мы видим, что температуру нам надо читать обязательно, так как её значение влияет и на расчёт влажности.
Перейдём в функцию main() файла main.c и в бесконечном цикле вызовем функцию считывания и расчёта влажности воздуха
hf = BME280_ReadHumidity();
sprintf(str1, «Humidity: %.3f %%\r\n» , hf);
Соберём код, прошьём контроллер и посмотрим результат считывания двухбайтовой величины в терминальной программе

Как мы видим, у нас колеблется опять не тот байт.
Поэтому идём в в файл BME280.c и добавим там соответствующую функцию считывания наоборот после функции BME280_ReadReg_S16
void BME280_ReadReg_BE_S16( uint8_t Reg, int16_t *Value)
I2Cx_ReadData16(BME280_ADDRESS,Reg,( uint16_t *)Value);
*( uint16_t *) Value = be16toword(*( uint16_t *) Value);
Теперь вернёмся в функцию BME280_ReadHumidity и изменим вызываемую функцию
BME280_ReadReg_BE_S16(BME280_REGISTER_HUMIDDATA,&hum_raw);
Добавим некоторые локальные переменные для промежуточных расчётов
int32_t hum_raw_sign, v_x1_u32r;
Присвоим считанное значение 32-битной знаковой переменной и смотреть в терминальной программе будем уже его
hum_raw_sign = (( int32_t )hum_raw)& 0x0000FFFF ;
sprintf(str1, «Humidity RAW: 0x%08X\r\n» , hum_raw _sign );
Соберём код, прошьём контроллер и посмотрим значение

Теперь у нас пляшет младший байт — так должно и быть.
Также следуя рекомендациям технической документации, рассчитаем значение влажности воздуха в значении с плавающей точкой
v_x1_u32r = (temper_int — (( int32_t ) 76800 ));
((( int32_t )CalibData.dig_H5) * v_x1_u32r)) + (( int32_t ) 16384 )) >> 15 ) *
(((((((v_x1_u32r * (( int32_t )CalibData.dig_H6)) >> 10 ) *
(((v_x1_u32r * (( int32_t )CalibData.dig_H3)) >> 11 ) + (( int32_t ) 32768 ))) >> 10 ) +
(( int32_t ) 2097152 )) * (( int32_t )CalibData.dig_H2) + 8192 ) >> 14 ));
v_x1_u32r = (v_x1_u32r — (((((v_x1_u32r >> 15 ) * (v_x1_u32r >> 15 )) >> 7 ) *
(( int32_t )CalibData.dig_H1)) >> 4 ));
v_x1_u32r = (v_x1_u32r > 419430400 ) ? 419430400 : v_x1_u32r;
hum_float = (v_x1_u32r>> 12 );
hum_float /= 1024.0 f;
Соберём код, прошьём контроллер и посмотрим результат

Все показания прекрасно читаются и обновляются!
Можно теперь удалить отображение сырого значения
sprintf(str1, «Humidity RAW: 0x%08X\r\n» , hum_raw_sign);
Осталось нам подключить дисплей и отобразить наши показания на нём, так как с дисплеем красивее, чем в терминальной программе, и более автономно, так как не надо будет схему подключать к ПК.
Для этого мы скопируем файлы lcd.h и lcd.c из проекта урока 105 NRF24_RX_LCD в наш проект.
В файле main.c подключим данную библиотеку
#include «lcd.h»
Также подключим файл lcd.c к дереву проекта.
Перейдём в файл и удалим объявление строковой переменной, так как она там не нужна
Вернёмся в файл main.c и в функции main() вызовем инициализацию дисплея
/* USER CODE BEGIN 2 */
LCD_ini();
В бесконечном цикле отобразим различные показатели на нашем дисплее, вставив в нужные места соответствующий код
sprintf(str1, «Temperature: %.3f *C\r\n» , tf);
LCD_SetPos( 0 , 0 );
sprintf(str1, «%11.3f *C» , tf);
LCD_String(str1);
sprintf(str1, «Pressure: %.3f Pa; %.3f hPa; %.3f mmHg\r\n» , pf, pf/ 1000.0 f, pf * 0.000750061683 f);
LCD_SetPos( 0 , 1 );
sprintf(str1, «%11.3f hPa» , pf/ 1000.0 f);
LCD_String(str1);
LCD_SetPos( 0 , 2 );
sprintf(str1, «%11.3f mmHg» , pf * 0.000750061683 f);
LCD_String(str1);
sprintf(str1, «Altitude: %.3f m\r\n» , af);
sprintf(str1, «Humidity: %.3f %%\r\n» , hf);
LCD_SetPos( 0 , 3 );
sprintf(str1, «%7.3f %% %4.1f m» , hf, af);
LCD_String(str1);
Осталось нам собрать код, прошить контроллер, отключить логический анализатор и подключить дисплей.
Полюбуемся результатом работы нашего кода (нажмите на картинку для увеличения изображения)

Таким образом, сегодня мы освоили ещё один отличный погодный датчик, который с высокой точностью и скоростью может измерять сразу и температуру, и давление, и влажность воздуха.
Спасибо всем за внимание!
Отладочную плату можно приобрести здесь Nucleo STM32F401RE
Логический анализатор 16 каналов можно приобрести здесь
Датчик температуры, давления и влажности BME280 можно приобрести здесь BME280
Переходник I2C to LCD1602 2004 можно приобрести здесь: I2C to LCD1602 2004
Смотреть ВИДЕОУРОК (нажмите на картинку)

10 комментариев на “ STM Урок 121. Датчик температуры, давления и влажности BME280. Часть 4 ”
Спасибо большое! Очень помогло разобраться с датчиком.
Большое спасибо за уроки. Не давно перешёл с AVR, с STM все гораздо круче!
Атмосферное давление в Па почему-то на порядок выше, чем обычно. Стандартная атмосфера 101325Па. У вас в листингах получается где-то в 10 раз больше. Т.е. не 100кПа, а 1МПа.
З.Ы. а за уроки, безусловно, большущее спасибо! Очень подробно, внятно и с исходниками!
Ошибки мелкие есть везде. Без них было бы скучно
Удачи и продолжений!
Спасибо за уроки. Сэкономил кучу времени и нервов для себя!
Спасибо большое! Датчик работает. Экран подключу уже завтра.
Единственно, что мой датчик BME280 показывает почему-то давление на 40 Гексапаскалей меньше. Я проверяю по своей другой метеостанции и по данным с официальной метеостанции. Я почистил осторожно его сверху, продул сжатым воздухом, но не помогает.
Как его можно откалибровать? Какую величину изменять? Я это пока не очень хорошо понимаю.
Может будет полезно для начинающих:
— в примерах кода в этой статье есть кое-где rn, которые нужно переправлять в \r\n.
— мне пришлось включать в BME280.h #include , чтобы заработала функция sprintf().
— мне пришлось включать в BME280.h #include , чтобы заработала функция sprintf().
Поправка: на 40 Гектопаскалей, гПа
писал функцию вычисления на СИ (атхмега Атмел студио7)
v_x1_u32r = (((((adc_H 15)*(((((((v_x1_u32r * ((int32_t)dig_H6)) >> 10)*(((v_x1_u32r * ((int32_t)dig_H3)) >> 11) + ((int32_t)32768))) >> 10)+((int32_t)2097152)) * ((int32_t)dig_H2) + 8192) >> 14));
v_x1_u32r = (v_x1_u32r — (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *((int32_t)dig_H1)) >> 4));
v_x1_u32r = (v_x1_u32r 419430400) ? 419430400 : v_x1_u32r;
h = (v_x1_u32r>>12);
занижало влажность на 20 % и работало неправильно. Перепроверил этот же код на ПК — все работает. Видимо какоето переполнение в мк атхмега.
В итоге на атхмега заработал такой код :
var_H = (adc_H — (((double)dig_H4) * 64.0 + ((double)dig_H5) / 16384.0 * var_H)) * (((double)dig_H2) / 65536.0 * (1.0 + ((double)dig_H6) / 67108864.0 * var_H * (1.0 + ((double)dig_H3) / 67108864.0 * var_H)));
var_H = var_H * (1.0 — ((double)dig_H1) * var_H / 524288.0);
h = var_H;
Здравствуйте!
Суть проблемы: Соединил по i2c STM32F4-Discovery и датчик температуры BME-280, написал прошивку по Вашему примеру — температура считывается нормально. Развел плату, запаял туда мк STM32f407vgt6 зашил ту же прошивку, поставил тот же датчик — i2C не включается ни в какую, осциллом смотрел даже посылка не идет от мк, даже в 0 не падает. Перепаял мк, сравнивал те же пины, что и на дискавери, единственное различие на дискавери стоит мк версии z, а в самодельной плате версии 2. Смотрел errata, но с моим английским разницы не нашел. В чём может быть подвох?
Arduino и метеодатчик BME280/BMP280
BME280 – высокоточный метеодатчик, измеряющий такие параметры микроклимата как температура, влажность и атмосферное давление. В зависимости от модуля может подключаться к I2C и SPI шинами микроконтроллера и работать от 3-5V, если на плате есть стабилизатор, или 3V, если его нет.
На обратной стороне платы не просто так написано BME280/BMP280 – BMP является урезанной версией BME, в которой нет влажности. Как их различить, если недобросовестный китаец не поставил галочку? По корпусу датчика:

В наборе GyverKIT первых партий (все наборы 2021 года) шёл BME280 версии I2C 5V, но старт продаж набора совпал с мировым кризисом микросхем, из за которого датчик стал сильно дефицитным и китайцы начали хитрить. В наборах GyverKIT 000, 001 и 002 партий можно встретить:
- Рабочий BME280
- Рабочий BMP280
- Нерабочий BMP280
В партии 003 у нас рабочий BMP280. Для влажности используется другой датчик.
Мы приносим свои извинения за эту ситуацию, вы можете запросить возврат средств за модуль у магазина Giant4.
Подключение
Модуль подключается на шину I2C и питание, как и любой другой модуль такого типа:

Библиотеки
-
(для работы также нужна Adafruit Sensor) – самая известная библиотека для работы с BME280. Очень тяжёлая, часть настроек доступна только при ручном редактировании библиотеки. – наша библиотека, более удобная и лёгкая. Также поддерживает датчики BMP280
В примерах на этом сайте мы будем использовать GyverBME280. Библиотека идёт в архиве к набору GyverKIT, а свежую версию всегда можно установить/обновить из встроенного менеджера библиотек Arduino по названию GyverBME280. Краткая документация находится по ссылке выше, базовые примеры есть в самой библиотеке.
Примеры
Первым делом стоит удостовериться в работоспособности датчика и узнать его адрес, он может быть 0x77 и 0x76 . Загружаем следующий код:
Открываем монитор порта:
- Если вывелось только Start scan и ничего больше – датчик бракованный и не будет работать
- Если это рабочий BMP/BME – получим вывод такого вида:
Значит датчик ответил по адресу 0x76. Может ответить по 0x77.
- Если вывод имеет вид
Значит Ардуино не находит датчиков на линии. Либо датчик подключен неправильно, либо бракованный.
Далее откроем базовый пример из библиотеки, который опрашивает значения с датчика. В begin() можно передать адрес, который мы узнали из предыдущего скетча-сканера (не забываем префикс 0x). Загружаем и открываем порт:
- Если выведется только слово Start – датчик бракованный и из-за этого программа зависла
- Если выведется Error! – датчик бракованный или адрес не соответствует, вернись к предыдущему пункту
- Корректно выводятся все три параметра
Start
Temperature: 24.78
Humidity: 41.69
Pressure: 99701.28
Датчик рабочий, и это BME280
- Выводится температура и давление, влажность – 0
Start
Temperature: 24.78
Humidity: 0
Pressure: 99701.28
Похожие публикации:
- Как слушать диски в машине если нет дисковода
- Как улучшить звук на андроид магнитоле
- 6 вольт сколько работает в электромобилях детских
- Зачем нужен предохранитель в компасе
Подключение датчика BME280 к Arduino
В этом руководстве мы подробно разберем, как использовать модуль датчика BME280 с Arduino для считывания давления, температуры, влажности и оценки высоты. Вы узнаете как подключить датчик, установить необходимые библиотеки и написать простой скетч для отображения показаний датчика.
Обзор модуля датчика BME280
Датчик BME280 считывает барометрическое давление, температуру и влажность. Также, поскольку давление меняется с высотой, можно также примерно оценить и высоту. Существует несколько версий этого модуля, различающихся используемым протоколом связи I2C или SPI для обмена данными с микроконтроллером.
BME280 c I2C интерфесом
Этот датчик использует протокол связи I2C, поэтому подключение очень простое. Вы подключаете датчик BME280 к контактам Arduino, как показано в таблице ниже:
| BME280 | Arduino UNO | Arduino MINI | Arduino Mega | Arduino Micro | Arduino Nano |
| VIN | 5V | 5V | 5V | 5V | 5V |
| GND | GND | GND | GND | GND | GND |
| SCL | A5 | A7 | 21 | 1 | A5 |
| SDA | A4 | A6 | 20 | 2 | A4 |
BME280 с SPI интерфейсом
Существуют и другие версии этого датчика, которые могут использовать протоколы связи SPI или I2C, например, модуль, показанный на следующем рисунке:
Для подключения датчика по SPI подключите его к следующим контактам Arduino
| BME280 | Arduino Nano | Arduino UNO | Arduino Mega | Arduino Mini |
| SCK (SPI Clock) | Pin 13 | Pin 13 | Pin 52 | Pin 17 |
| SDO (MISO) | Pin 12 | Pin 12 | Pin 50 | Pin 16 |
| SDI (MOSI) | Pin 11 | Pin 11 | Pin 51 | Pin 15 |
| CS (Chip Select) | Pin 10 | Pin 10 | Pin 53 | Pin 14 |
Схема подключения
Подключите датчик BME280 к плате Arduino, как показано на следующей принципиальной схеме.
Установка необходимых библиотек
Для считывания показаний датчика нам нужно установить в Arduino IDE несколько дополнительных библиотек. Это Adafruit_BME280 и Adafruit Unified Sensor. Как это сделать мы сейчас подробно рассмотрим.
Установка библиотеки Adafruit BME280
Чтобы получить показания от модуля датчика BME280, вам необходимо использовать библиотеку Adafruit_BME280. Выполните следующие шаги, чтобы установить её в Arduino IDE:
Перейдите в Скетч> Подключить библиотеку> Управление библиотеками. Должен открыться менеджер библиотек.
Найдите “adafruit bme280” в окне поиска и установите её.
Установка библиотеки Adafruit Unifed Sensor
Чтобы использовать библиотеку BME280, вам также необходимо установить библиотеку Adafruit_Sensor. Выполните следующие шаги, чтобы установить её в Arduino IDE:
Перейдите в Скетч> Подключить библиотеку> Управление библиотеками. Должен открыться менеджер библиотек. Введите “Adafruit Unified Sensor” в поле поиска. Прокрутите до конца, чтобы найти библиотеку и установить её.
После установки библиотек перезапустите Arduino IDE.
Считывание давления, температуры и влажности
Чтобы прочитать давление, температуру и влажность, мы будем использовать пример скетча из библиотеки. Для этого откройте Arduino IDE и перейдите в Файл> Примеры> Adafruit BME280 Library> bme280test.
/*************************************************************************** This is a library for the BME280 humidity, temperature & pressure sensor Designed specifically to work with the Adafruit BME280 Breakout ----> http://www.adafruit.com/products/2650 These sensors use I2C or SPI to communicate, 2 or 4 pins are required to interface. The device's I2C address is either 0x76 or 0x77. Adafruit invests time and resources providing this open source code, please support Adafruit andopen-source hardware by purchasing products from Adafruit! Written by Limor Fried & Kevin Townsend for Adafruit Industries. BSD license, all text above must be included in any redistribution See the LICENSE file for details. ***************************************************************************/ #include #include #include #include #define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10 #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); while(!Serial); // time to get serial running Serial.println(F("BME280 test")); unsigned status; // default settings status = bme.begin(); // You can also pass in a Wire library object like &Wire2 // status = bme.begin(0x76, &Wire2) if (!status) < Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); Serial.print(" ID of 0x60 represents a BME 280.\n"); Serial.print(" ID of 0x61 represents a BME 680.\n"); while (1) delay(10); >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"); 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(); >
Как работает код
В данном разделе мы подробно разберем как работает код данной программы
Подключение библиотек и первичная настройка
Код начинается с включения необходимых библиотек: библиотеки wire для использования I2Cибиблиотек Adafruit_Sensor и Adafruit_BME280 для взаимодействия с датчиком BME280.
#include #include #include #include
Поскольку мы собираемся использовать интерфейс I2C, следующие строки, определяющие выводы SPI, можно закомментировать
#define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10
Далее создаем переменную SEALEVELPRESSURE_HPA
#define SEALEVELPRESSURE_HPA (1013.25)
Эта переменная сохраняет давление на уровне моря в гектопаскалях (эквивалентно милибару). Эта переменная используется для оценки высоты для данного давления путем сравнения его с давлением на уровне моря. В этом примере используется значение по умолчанию, но для получения более точных результатов замените это значение текущим давлением на уровне моря в вашем регионе.
В этом примере по умолчанию используется протокол связи 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 () запускаем последовательный порт со скоростью 9600 бод:
Serial.begin(9600);
И инициализируем датчик
status = bme.begin(); if (!status)
Вывод значений
В цикле loop() функция printValues() считывает значения с BME280 и выводит результаты в монитор последовательного порта.
void loop()
Считывание температуры, влажности, давления и оценки высоты выполняем используя следующие методы объекта bme:
- bme.readTemperature() – считывает температуру в градусах Цельсия;
- bme.readHumidity() – считывает абсолютную влажность;
- bme.readPressure() – считывает давление в ГПа (гектопаскаль = миллибар);
- bme.readAltitude(SEALEVELPRESSURE_HPA) – оценивает высоту в метрах на основе давления на уровне моря.
Демонстрация работы
Загрузите скетч в плату Arduino

Откройте монитор последовательного порта со скоростью передачи данных 9600 бод.
Если все предыдущие шаги были выполнены верно вы должны увидеть показания датчиков
Подведение итогов
BME280 обеспечивает простой и недорогой способ получения показаний давления, температуры и влажности. Датчик взаимодействует через протокол связи I2C, что означает, что вам просто нужно подключить датчик к контактам Arduino I2C.
Написание кода для получения показаний датчика также очень просто благодаря библиотеке BME280_Adafruit. Вам просто нужно использовать методы readTemperature(), readHumidity() и readPressure(). Вы также можете оценить высоту, используя метод readAltitude().