Подключение датчика атмосферного давления BMP388 (альтиметр) к Arduino
Многие люди сегодня летают на дронах, и знать высоту, которой достиг ваш дрон — полезная информация. Молниеносно быстрый, температурно-стабильный, высокоточный датчик атмосферного давления, такой как BMP388 от Bosch, может стать идеальным выбором для отслеживания высоты в вашем следующем проекте дрона.
Обзор оборудования
В основе модуля лежит цифровой датчик давления и температуры нового поколения от Bosch — `BMP388 `_.
Датчик давления BMP388
BMP388 — это очень маленький, молниеносно быстрый, точный, маломощный датчик абсолютного атмосферного давления с низким уровнем шума. Он обеспечивает точное отслеживание высоты и идеально подходит для применения в дронах или любых проектах, где необходимо отслеживать высоту над уровнем моря.
BMP388 может измерять атмосферное давление от 300 гПа до 1250 гПа и имеет относительную точность 8 Паскалей, что соответствует примерно ±0,5 метра высоты.
BMP388 имеет встроенный датчик температуры, который можно использовать для компенсации изменений окружающей среды и калибровки измерений. Это достаточно точный датчик температуры, который измеряет температуру кристалла в диапазоне от -40˚C до +85˚C с точностью ±1˚C.
Требования к питанию
Модуль поставляется с прецизионным стабилизатором напряжения MIC5219 на 3,3 В и преобразователем уровня напряжения, поэтому вы можете использовать его с вашим любимым микроконтроллером на 3,3 В или 5 В без каких-либо опасений.
BMP388 потребляет менее 0,7 мА во время измерений и всего 2 мкА в спящем режиме. Такое низкое энергопотребление позволяет использовать его в устройствах с батарейным питанием, таких как телефоны, носимые устройства или умные часы.
Цифровые интерфейсы
Датчик взаимодействует через I2C или SPI.
Датчик использует интерфейс I2C для связи с Arduino. Он поддерживает два отдельных I2C-адреса: 0x77 и 0x76. Это позволяет использовать два модуля BMP388 на одной шине или избежать конфликтов адресов с другим устройством на шине.
Вывод SDO определяет I2C-адрес модуля. Этот вывод имеет встроенный подтягивающий резистор. Поэтому, когда вы оставляете вывод SDO неподключённым, I2C-адрес по умолчанию равен 0x77, а когда вы подключаете его к GND, линия подтягивается к LOW, и I2C-адрес становится 0x76.
Датчик также может взаимодействовать через интерфейс SPI.
К сведению:
Если вам нужно выбрать между ними, SPI, как правило, является лучшим вариантом, если вам нужна более высокая скорость передачи данных (до 10 МГц). I2C, с другой стороны, лучше подходит, если у вашего микроконтроллера ограничено количество свободных выводов.
Режимы работы
BMP388 имеет 3 режима работы:
SLEEP_MODE: переводит устройство в неактивное состояние ожидания (измерения не выполняются).
NORMAL_MODE: выполняет непрерывные преобразования, разделённые временем ожидания.
FORCED_MODE: выполняет одно преобразование, возвращаясь в SLEEP_MODE после завершения.
Буфер FIFO
BMP388 содержит встроенный 512-байтный буфер FIFO (первый вошёл — первый вышел) для хранения до 72 результатов измерений давления и/или температуры. Буфер FIFO позволяет разгрузить микроконтроллер от чтения каждого нового значения с датчика, тем самым экономя энергию системы.
Прерывания
BMP388 имеет выходной вывод прерывания (INT), который позволяет выполнять измерения по прерываниям вместо опроса, что позволяет хост-микроконтроллеру выполнять другие задачи, пока данные собираются датчиком. Прерывание может быть включено для 3 различных источников:
Data Ready: срабатывает после завершения измерения давления и температуры, когда результаты преобразования сохранены в регистры данных и в FIFO.
FIFO Watermark: срабатывает, когда уровень заполнения FIFO достиг заранее установленного предела.
FIFO Full: срабатывает, когда FIFO заполняется и данные могут быть потеряны.
Выходной каскад вывода INT может быть: PUSH_PULL или OPEN_COLLECTOR, уровень вывода INT может быть: ACTIVE_LOW или ACTIVE_HIGH, а само прерывание может быть: UNLATCHED или LATCHED. В режиме UNLATCHED сигнал прерывания автоматически сбрасывается через 2,5 мс, а в режиме LATCHED сигнал прерывания остаётся активным до тех пор, пока данные не будут прочитаны.
Технические характеристики
Вот полные технические характеристики:
Для получения более подробной информации обратитесь к техническому описанию ниже.
Распиновка модуля BMP388
Давайте рассмотрим распиновку.
Выводы питания:
VCC — это вывод питания. Вы можете подключить его к выходу 5V вашего Arduino.
3Vo — это выход 3,3 В от стабилизатора напряжения. При необходимости с него можно получить до 100 мА.
GND — общая земля для питания и логики.
Логические выводы SPI:
SCK — вывод тактирования SPI, это вход микросхемы.
SDO — вывод последовательных данных на выход (MISO), для данных, отправляемых от BMP388 к вашему микроконтроллеру.
SDI — вывод последовательных данных на вход (MOSI), для данных, отправляемых от вашего микроконтроллера к BMP388.
CS — вывод выбора микросхемы; подтяните его к LOW, чтобы включить связь по SPI. Если вы хотите подключить несколько BMP388 к одному микроконтроллеру, используйте общие выводы SDI, SDO и SCK и назначьте каждому уникальный вывод CS.
Логические выводы I2C:
SCK — это также вывод тактирования I2C; подключите его к линии тактирования I2C вашего микроконтроллера.
SDI — это также вывод данных I2C; подключите его к линии данных I2C вашего микроконтроллера.
Вывод SDO определяет I2C-адрес модуля. Когда вы оставляете вывод SDO неподключённым, I2C-адрес по умолчанию равен 0x77, а когда вы подключаете его к GND, линия подтягивается к LOW, и I2C-адрес становится 0x76.
Вывод прерывания:
INT — это вывод прерывания. BMP388 можно запрограммировать на генерацию прерываний по определённым событиям. Обратитесь к разделу «Прерывания».
Схема подключения модуля BMP388 к Arduino
Теперь, когда мы знаем всё о модуле, можно приступить к его подключению к Arduino!
Схема подключения I2C
Используйте эту схему подключения, если хотите подключиться через интерфейс I2C.
Начните с подключения вывода VCC к источнику питания — подойдёт 3 В–5 В. Используйте то же напряжение, на котором основана логика вашего микроконтроллера. Для большинства Arduino это 5 В. Для устройств с логикой 3,3 В используйте 3,3 В. Теперь подключите GND к общей земле.
Подключите вывод SCK к выводу тактирования I2C, а вывод SDI к выводу данных I2C на вашем Arduino. Обратите внимание, что каждая плата Arduino имеет разные выводы I2C, которые необходимо подключать соответствующим образом. На платах Arduino с компоновкой R3 линия SDA (данные) и SCL (тактирование) расположены на штыревых разъёмах рядом с выводом AREF. Они также известны как A5 (SCL) и A4 (SDA).
На следующей иллюстрации показана схема подключения.
Схема подключения SPI
Поскольку это датчик с поддержкой SPI, вы можете использовать аппаратный или программный SPI. Однако рекомендуется использовать аппаратные выводы SPI, так как они значительно быстрее, чем программная реализация интерфейса на других выводах.
Опять же, каждая плата Arduino имеет разные выводы SPI, которые необходимо подключать соответствующим образом. Для плат Arduino, таких как UNO/Nano V3.0, эти выводы — цифровые 13 (SCK), 12 (MISO), 11 (MOSI) и 10 (SS).
Если вы используете другую плату Arduino, рекомендуется проверить официальную документацию о `расположении выводов SPI `_ перед началом работы.
На следующей иллюстрации показана схема подключения.
Как только ваш модуль подключён к Arduino, пора писать код!
Установка библиотеки
Чтобы начать считывать данные с датчика, вам нужно установить `библиотеку Adafruit BMP3XX `_. Она доступна в менеджере библиотек Arduino.
Для установки библиотеки перейдите в Sketch > Include Library > Manage Libraries… Подождите, пока менеджер библиотек загрузит индекс библиотек и обновит список установленных библиотек.
Отфильтруйте поиск, введя „adafruit bmp3xx“, и установите библиотеку.
Библиотека датчика BMP3XX использует `бэкенд поддержки Adafruit Sensor `_. Поэтому найдите в менеджере библиотек Adafruit Unified Sensor и установите её тоже (возможно, придётся немного прокрутить).
Код Arduino — считывание давления, высоты и температуры
Ниже приведён базовый скетч для Arduino. Загрузите его на ваш Arduino. Вы должны увидеть давление, температуру и приблизительную высоту в мониторе последовательного порта.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
//Uncomment if you want to use SPI
//#define BMP_SCK 13
//#define BMP_MISO 12
//#define BMP_MOSI 11
//#define BMP_CS 10
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BMP3XX bmp;
void setup() {
Serial.begin(115200);
while (!Serial);
if (!bmp.begin_I2C()) { // hardware I2C mode, can pass in address & alt Wire
//if (! bmp.begin_SPI(BMP_CS)) { // hardware SPI mode
//if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) { // software SPI mode
Serial.println("Could not find a valid BMP3 sensor, check wiring!");
while (1);
}
// Set up oversampling and filter initialization
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
}
void loop() {
if (! bmp.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
Serial.print("Temperature = ");
Serial.print(bmp.temperature);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Approx. Altitude = ");
Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Serial.println();
delay(2000);
}
Обратите внимание, что вы должны установить скорость монитора последовательного порта на 115200 бод для работы с этим скетчем.
Вы увидите множество данных, отображающих значения давления, температуры и приблизительной высоты. Попробуйте перемещать датчик и обратите внимание, как меняются данные.
Объяснение кода:
Скетч начинается с подключения четырёх необходимых библиотек: Wire.h (для I2C), SPI.h (для SPI), Adafruit_Sensor.h и Adafruit_BMP3XX.h.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
Этот скетч использует протокол I2C для связи с датчиком. Однако скетч подготовлен на случай, если вы захотите использовать SPI. Вам просто нужно раскомментировать следующие строки кода, определяющие выводы SPI.
//#define BMP_SCK 13
//#define BMP_MISO 12
//#define BMP_MOSI 11
//#define BMP_CS 10
Далее определяется переменная SEALEVELPRESSURE_HPA. Эта переменная сохраняет давление на уровне моря в миллибарах и используется для оценки высоты для заданного давления путём сравнения с давлением на уровне моря. Этот скетч использует значение по умолчанию, но для точных результатов замените его текущим давлением на уровне моря в вашем местоположении.
#define SEALEVELPRESSURE_HPA (1013.25)
Следующая строка создаёт объект Adafruit_BMP3XX с именем bmp.
Adafruit_BMP3XX bmp;
В функции setup() мы инициализируем последовательную связь с компьютером и вызываем функцию begin().
Функция bmp.begin_I2C() инициализирует интерфейс I2C и проверяет правильность идентификатора чипа. Затем она сбрасывает чип с помощью программного сброса и ожидает калибровки датчика после пробуждения. Аналогично, функция bmp.begin_SPI() инициализирует интерфейс SPI. Если вы хотите использовать SPI, вам нужно раскомментировать соответствующий if.
Serial.begin(115200);
while (!Serial);
Serial.println("Adafruit BMP388 / BMP390 test");
if (!bmp.begin_I2C()) { // hardware I2C mode, can pass in address & alt Wire
//if (! bmp.begin_SPI(BMP_CS)) { // hardware SPI mode
//if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) { // software SPI mode
Serial.println("Could not find a valid BMP3 sensor, check wiring!");
while (1);
}
Далее мы задаём некоторые параметры для датчика.
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
Рассмотрим каждую функцию по отдельности.
Для увеличения эффективного разрешения измерений и снижения шума BMP388 поддерживает передискретизацию (взятие нескольких выборок и их усреднение). Есть две функции — setTemperatureOversampling() и setPressureOversampling() — для установки передискретизации измерений температуры и давления соответственно. Эти функции принимают один из следующих параметров:
BMP3_NO_OVERSAMPLING (отключает считывание)
BMP3_OVERSAMPLING_2X
BMP3_OVERSAMPLING_4X
BMP3_OVERSAMPLING_8X
BMP3_OVERSAMPLING_16X
BMP3_OVERSAMPLING_32X
BMP388 также имеет встроенный фильтр IIR для уменьшения кратковременных изменений давления в выходных значениях датчика, вызванных внешними воздействиями (такими как хлопок двери или окна, или поток воздуха на датчик). Функция setIIRFilterSize() устанавливает фильтр IIR. Фильтр IIR может быть настроен на различные коэффициенты фильтрации путём выбора одного из следующих параметров:
BMP3_IIR_FILTER_DISABLE (без фильтрации)
BMP3_IIR_FILTER_COEFF_1
BMP3_IIR_FILTER_COEFF_3
BMP3_IIR_FILTER_COEFF_7
BMP3_IIR_FILTER_COEFF_15
BMP3_IIR_FILTER_COEFF_31
BMP3_IIR_FILTER_COEFF_63
BMP3_IIR_FILTER_COEFF_127
Обратите внимание, что более высокие коэффициенты фильтра IIR обеспечивают стабильные измерения за счёт более медленного времени отклика.
Функция setOutputDataRate() устанавливает частоту выходных данных, то есть максимальную частоту, с которой вы можете считывать данные с устройства при заданных настройках. Эта функция принимает один из следующих параметров:
BMP3_ODR_200_HZ
BMP3_ODR_100_HZ
BMP3_ODR_50_HZ
BMP3_ODR_25_HZ
BMP3_ODR_12_5_HZ
BMP3_ODR_6_25_HZ
BMP3_ODR_3_1_HZ
BMP3_ODR_1_5_HZ
BMP3_ODR_0_78_HZ
BMP3_ODR_0_39_HZ
BMP3_ODR_0_2_HZ
BMP3_ODR_0_1_HZ
BMP3_ODR_0_05_HZ
BMP3_ODR_0_02_HZ
BMP3_ODR_0_01_HZ
BMP3_ODR_0_006_HZ
BMP3_ODR_0_003_HZ
BMP3_ODR_0_001_HZ
В функции loop() мы вызываем функцию bmp.performReading() для выполнения измерения. После этого мы можем получить доступ к переменным экземпляра объекта (bmp), используя оператор точки.
bmp.temperature возвращает показания температуры.
bmp.pressure возвращает показания атмосферного давления.
bmp.readAltitude(SEALEVELPRESSURE_HPA) — функция вычисляет высоту (в метрах) на основе указанного атмосферного давления (в гПа) и давления на уровне моря (в гПа).
void loop() {
if (! bmp.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
Serial.print("Temperature = ");
Serial.print(bmp.temperature);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Approx. Altitude = ");
Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Serial.println();
delay(2000);
}