Ардуино: датчик давления BMP180 (BMP085)

Барометр — это устройство, которое измеряет атмосферное давление. То есть давление воздуха, который давит на нас со всех сторон. Еще со школы мы знаем, что первый барометр представлял собой тарелку с ртутью, и перевернутой пробиркой в ней. Автором этого устройства был Эванджели́ста Торриче́лли — итальянский физик и математик. Снять показания ртутного барометра можно так же просто, как и показания спиртового термометра: чем давление снаружи колбы больше, тем выше столбик ртути внутри неё. Пары ртути, как известно, весьма ядовиты.

Позже, появился более безопасный прибор — барометр-анероид. В этом барометре ртуть была заменена на гофрированную коробку из тонкой жести, в которой создано разрежение. Под воздействием атмосферы, коробочка сжимается и через систему рычагов поворачивает стрелку на циферблате. Вот так выглядят эти два барометра. Слева — анероид, справа — барометр Торричелли.

1bar

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

GIA_13_22

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

Электронный барометр

Такие громоздкие барометры мы не сможем использовать в робототехнике. Нам нужен миниатюрный и энергоэффективный прибор, который легко подключается к той же Ардуино Уно. Большинство современных барометров делают по технологии МЭМС, так же как и гиротахометры с акселерометрами. МЭМС барометры основаны на пьезорезистивном, либо на тензометрическом методе, в которых используется эффект изменения сопротивления материала под действием деформирующих сил.

Если открыть корпус МЭМС барометра, можно увидеть чувствительный элемент (справа), который находится прямо под отверстием в защитном корпусе прибора, и плату управления (слева), которая осуществляет первичную фильтрацию и преобразование измерений.

box

Датчики BMP085 и BMP180

К самым доступным датчикам давления, которые часто используются полетных контроллерах и в разного рода самодельных электронных устройствах, можно отнести датчики компании BOSH: BMP085 и BMP180. Второй барометр более новый, но полностью совместимый со старой версией.

pres_bmp180

Немного важных характеристик BMP180:

  • диапазон измеряемых значений: от 300 гПа до 1100 гПа  (от -500м от +9000м над уровнем моря);
  • напряжение питания: от 3.3 до 5 Вольт;
    сила тока: 5 мкА при скорости опроса — 1 Герц;
  • уровень шума: 0.06 гПа (0.5м) в грубом режиме (ultra low power mode) и 0.02 гПа (0.17м) а режиме максимального разрешения (advanced resolution mode).

Теперь подключим этот датчик к контроллеру, и попробуем оценить атмосферное давление.

Список необходимых компонентов

Для выполнения простого примера с датчиком BMP180, кроме самого модуля датчика, потребуется Ардуино-совместимый контроллер и немного проводов вилка-розетка. Необходимые компоненты можно добавить в корзину прямо здесь, и затем оформить заказ в нашем интернет-магазине.

В корзину
В корзину
В корзину

Подключение BMP180

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

BMP 180GNDVCCSDASCL
Ардуино УноGND+5VA4A5

Принципиальная схема

bmp180_схема

Внешний вид макета

bmp180_bb

Программа

Для работы с датчиком нам понадобится библиотека: BMP180_Breakout_Arduino_Library

Скачиваем её из репозитория, и устанавливаем в Arduino IDE. Теперь все готово для написания первой программы. Попробуем получить сырые данные из датчика, и вывести их в монитор COM порта.

#include <SFE_BMP180.h>
#include <Wire.h>

SFE_BMP180 pressure;

void setup(){
    Serial.begin(9600);
    pressure.begin();
}

void loop(){
    double P;
    P = getPressure();
    Serial.println(P, 4); 
    delay(100);
}

double getPressure(){
    char status;
    double T,P,p0,a;

    status = pressure.startTemperature();
    if (status != 0){
        // ожидание замера температуры
        delay(status);
        status = pressure.getTemperature(T);
        if (status != 0){
            status = pressure.startPressure(3);
            if (status != 0){
                // ожидание замера давления
                delay(status);
                status = pressure.getPressure(P,T);
                if (status != 0){
                    return(P);
                }
            }
        }
    }
}

Процедура получения заветного давления из датчика не такая тривиальная, и состоит из нескольких этапов. В упрощенном виде алгоритм выглядит так:

  1. запрашиваем у барометра показания встроенного датчика температуры;
  2. ждем время A, пока датчик оценивает температуру;
  3. получаем температуру;
  4. запрашиваем у барометра давление;
  5. ждем время B, пока датчик оценивает давление;
  6. получаем значение давления;
  7. возвращаем значение давления из функции.

Время B зависит от точности измерений, которая задается в функции startPressure. Единственный аргумент этой функции может принимать значения от 0 до 3, где 0 — самая грубая и самая быстрая оценка, 3 — самая точная оценка давления.

Загружаем программу на Ардуино Уно, и наблюдаем поток измерений атмосферного давления. Попробуем поднять датчик над головой, и опустить до уровня пола. Показания будут немного меняться. Осталось только разобраться, как нам преобразовать эти непонятные числа в высоту над уровнем моря.

Преобразование давления в высоту над уровнем моря

Датчик BMP180 возвращает величину давления в гектопаскалях (гПа). Именно в этих единицах принято измерять атмосферное давление. 1 гПа = 100 Паскалей. Известно, что на уровне моря давление в среднем составляет 1013 гПа, и каждый дополнительный метр над уровнем моря будет уменьшать это давление всего на 0.11 гПа (примерно).

Таким образом, если мы вычтем из результата функции getPressure число 1013, и разделим оставшуюся разность на 0.11, то мы получим значение высоты над уровнем моря в метрах. Вот так изменится наша программа:

void loop(){
    double P, Alt;
    P = getPressure();
    Alt = (P - 1013)/0.11;
    Serial.println(Alt, 2); 
    delay(100);
}

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

for

Здесь p — измеренное в данной точке давление, p0 — давление относительно которого идет отсчет высоты.

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

#include <SFE_BMP180.h>
#include <Wire.h>

SFE_BMP180 pressure;
double P0 = 0;

void setup(){
    Serial.begin(9600);
    pressure.begin();
    P0 = pressure.getPressure();
}

void loop(){
    double P, Alt;
    P = getPressure();
    Alt = pressure.altitude(P,P0)
    Serial.println(Alt, 2); 
    delay(100);
}

double getPressure(){
    ...
}

Я не стал полностью копировать функцию getPressure, чтобы сохранить читабельность текста.

В программе появилась еще одна переменная P0 — это давление, которое мы измерим на старте программы. В случае летательного аппарата, P0 будет давлением на взлетной площадке, относительно которой мы начнем набор высоты.

Визуализация

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

static const byte PACKET_SIZE = 1;
static const byte VALUE_SIZE = 2;
static const boolean SEPARATE_VALUES = true;

#include <SerialFlow.h>
#include <SFE_BMP180.h>
#include <Wire.h>

SFE_BMP180 pressure;
SerialFlow rd(&Serial);
double P0 = 0;

void setup(){
    rd.setPacketFormat(VALUE_SIZE, PACKET_SIZE, SEPARATE_VALUES);
    rd.begin(9600);
    pressure.begin();
    P0 = getPressure();
}

void loop(){
    double P;
    P = getPressure();
    rd.setPacketValue(100+int((P - P0)*100));
    rd.sendPacket();
    delay(100);
}

double getPressure(){
    ...
}

В результате работы программы получим график давления в Паскалях:

main

Заключение

Как мы уяснили из урока, определение высоты над уровнем моря не такая тривиальная задача. Мало того, что давление зависит от высоты нелинейно, так еще картину портят различные внешние факторы. Например, давление  у нас дома постоянно меняется с течением времени. Даже за несколько минут, высота измеренная нашим прибором может варьироваться в диапазоне 0.5 — 1 метра. Температура так же сильно влияет на качество измерений, поэтому нам приходится учитывать её при расчете давления.

Для летательных аппаратов рекомендуется использовать датчики повышенной точности, такие как MS5611. У этого барометра точность измерений может достигать 0,012 гПа, что в 5 раз лучше, чем у BMP180. Также, для уточнения барометрической высоты полета применяют координаты GPS.

Успехов в наблюдении за атмосферой! 🙂


Изменено:

Ардуино: датчик давления BMP180 (BMP085): 18 комментариев

  1. >напряжение питания: от 1.8 до 3.6В (VDD) и от 1.62 до 3.6В (VDDIO);
    Подключаем 5В???))) Логично!)))

    • Андрей, действительно неувязка! На самом деле на модуле есть линейный стабилизатор напряжения, так что он легко питается и от 5 Вольт. А характеристики в статье указаны для самого чипа.

      • Буду знать, спасибо за разъяснение! В других статьях подключают 3.3 В, как я и сделал.

  2. А почему так скачет показатель давления? Как с этим бороться? Ведь давление в реале не мот так хаотично скакать

  3. Объясните, пожалуйста очень подробно ,что означают и делают эти операторы

    pressure.begin()
    status = pressure.startTemperature();
    status = pressure.getTemperature(T);
    status = pressure.getTemperature(P,T);
    return(P);

    В частности что такое «pressure.», «startTemperature()» , что должно стоять в этих скобках?

    «Я не стал полностью копировать функцию getPressure, чтобы сохранить читабельность текста.» Не могли бы вы пояснить, пожалуйста , откуда вы не стали полностью копировать ??

    Я совсем недавно стал этим увлекаться и никак не могу найти информацию в книгах или источниках о данных операторах. Являются ли эти операторы специфическими для определенной библиотеки или датчика ????

      • Антон, в начале статьи приведен полный рабочий код программы для получения давления с датчика. Там же описана функция getPressure.
        Что касается «pressure», то это объект класса SFE_BMP180, который описан в библиотеке SFE_BMP180.h Вы можете называть его и не pressure, а, например, «ubersensor».

        В этой же библиотеке описаны разные полезные методы этого класса (они же функции): startTemperature, getTemperature, startPressure и getPressure.
        Эти методы специфичны для библиотеки SFE_BMP180. Вызываются они с помощью экземпляра класса (pressure) через точку: pressure.getPressure()
        Параметр есть только у функции startPressure и суть этого параметра описана в статье.

        Вообще, нет смысла запоминать все эти функции. Библиотек миллион. И каждый называет функции своими именами. Проще смотреть примеры для конкретной библиотеки и делать всё по аналогии.

        • Олег, не могли бы вы подсказать в чем дело :
          при первой загрузке первого кода выдавало одни нули , а при повторной загрузке кода на ардуино выдает следующее: «nan»

          • Пробовал скетчи из примеров , выдавало следующее :
            Temp(C):0 Alt(cm):0 Pressure(Pa):235

          • Проверьте еще раз подключение к I2C шине, SCL датчика идет на A5, SDA на A4 вход Ардуино. Какой датчик используете?

  4. Не могли бы вы объяснить что это за ошибка , при копировании конечной программы :
    Arduino: 1.6.10 (Windows 7), Плата:»Arduino/Genuino Uno»

    C:\Users\DNS\Desktop\скетчи ардуино\sketch_aug01a\sketch_aug01a.ino: In function ‘void setup()’:

    sketch_aug01a:10: error: no matching function for call to ‘SFE_BMP180::getPressure()’

    C:\Users\DNS\Desktop\скетчи ардуино\sketch_aug01a\sketch_aug01a.ino:10:31: note: candidate is:

    In file included from C:\Users\DNS\Desktop\скетчи ардуино\sketch_aug01a\sketch_aug01a.ino:1:0:

    C:\Program Files\arduino-1.6.10\libraries\SFE_BMP180/SFE_BMP180.h:52:8: note: char SFE_BMP180::getPressure(double&, double&)

    char getPressure(double &P, double &T);

    ^

    C:\Program Files\arduino-1.6.10\libraries\SFE_BMP180/SFE_BMP180.h:52:8: note: candidate expects 2 arguments, 0 provided

    C:\Users\DNS\Desktop\скетчи ардуино\sketch_aug01a\sketch_aug01a.ino: In function ‘void loop()’:

    sketch_aug01a:15: error: ‘getPressure’ was not declared in this scope

    sketch_aug01a:17: error: expected ‘;’ before ‘Serial’

    exit status 1
    no matching function for call to ‘SFE_BMP180::getPressure()’

    Этот отчёт будет иметь больше информации с
    включенной опцией Файл -> Настройки ->
    «Показать подробный вывод во время компиляции»

  5. Антон, Вам это уже наверное не нужно, а другим может пригодится.Предполагаю, что Вы взяли библиотеку с одного места, а программу из другого, поэтому несовместимость используемых процедур. имя sketch_aug01a похоже на урок с другого сайта. Так же хочется обратить внимание, что в статье нет указания на то что это учебник. Автор показал конкретный модуль и один из вариантов работы с ним. Все что происходит у Вас на компьютере зависит от многих параметров, включая настройку среды программирования, а это уже очень индивидуально. начните с точного копирования показанного кода, а когда в нем разберетесь, сможете менять по своему усмотрению.

  6. Здравствуйте, я новичок и у меня возникла проблема. Не могу разобраться, как подключить библиотеку.
    Вот вы сказали :»Для работы с датчиком нам понадобится библиотека: BMP180_Breakout_Arduino_Library
    Скачиваем её из репозитория, и устанавливаем в Arduino IDE.» Не могли бы вы мне дураку конкретнее объяснить, где и как эту библиотеку скачать.
    Вот я перешел по ссылке на github, но где эту библиотеку скачать не понятно. Где этот репозиторий и где сам файл с библиотекой. Помогите пожалуйста разобраться

    • Переходите по этой ссылке. Там сверху будет большая зеленая кнопка Code. Нажмите её и в выпадающем меню жмите Download ZIP.
      Скачается zip архив с библиотекой.

      Затем в Arduino IDE:
      Скетч/Подключить библиотеку/Добавить .ZIP библиотеку
      и выбираете тот самый zip файл

  7. Здравствуйте. Ситуация — метео dht11, bmp-180. При подключении bmp-180 оптопарой 4*2 в экране длиной 10 м на lcd ничего не отображается..Нет данных и с dht-11. ПРи установке бмп-180 в корпус оба датчика выдют инф на лсд. Натолкните на мысль. Спасибо.

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

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

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.