Подключение BMP180 датчик давления и температуры к Arduino.

Датчик абсолютного давления и температуры (последним сегодня уже никого не удивишь) Bosch BMP180. Датчик  не нов и хорошо известен, datasheet изучен  вдоль и поперек, а библиотек целая куча.

Характеристики :
  • Диапазон измерения давления: 300 – 1100 hPa.
  • Напряжение питания: от 1.8 — 3.3 и 5V(если на плате стоит стабилизатор напряжения).
  • Низкое энергопотребление: 3 мкА (режим ультра-низкого энергопотребления)
  • Точность: режим пониженного энергопотребления, разрешение 0.06hPa (0,5 м).
  • Высокий линейный режим с разрешением 0.02hPa (0,17 м).
  • Подключение: интерфейс I2C.
  • Возможность измерения температуры в диапазоне  -40 … +85 ° C.
  • Время отклика: 5ms — 7.5ms (standart mode).
  • Ток в режиме ожидания: 0,1 мкA

Более подробно можно прочитать в Datasheet.

Принцип действия датчика BMP180:

В датчике имеется герметичная камера, одна из стенок которой является гибкой мембраной с установленными на ней тензодатчиками. Мембрана прогибается пропорционально разности давлений внутри камеры и снаружи, что влияет на изменение сопротивления тензодатчиков электрическому току. Так же имеется термодатчик, сопротивление которого меняется пропорционально температуре. АЦП (аналого-цифровой преобразователь) переводит результаты изменений датчиков в цифровые данные «некомпенсированные результаты», которые доступны для чтения из регистров датчика: «Out MSB», «Out LSB» и «Out xLSB». Для компенсации указанных результатов (компенсации смещения, температурной зависимости, погрешностей при изготовлении, неоднородностей материалов и т.д.) каждый датчик калибруется на заводе, и в EEPROM записываются индивидуальные для каждого датчика 11 калибровочных коэффициентов
(176 бит), которые доступны для чтения из регистров датчика: «AC1», «AC2», «AC3», «AC4», «AC5», «AC6», «B1», «B2», «MB», «MC», «MD».

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

Алгоритм получения данных:
  • Чтение калибровочных коэффициентов:

Чтение значений из одноименных регистров:
short                      AC1, AC2, AC3, B1, B2, MB, MC, MD;
unsigned short    AC4, AC5, AC6;

  • Чтение температуры: (некомпенсированное значение)

Записываем в регистр «Measurement Control» значение: 0x2E;
Ожидаем спад флага состояния «CSO» в «0»;
Читаем результат из регистров «Out MSB» и «Out LSB»;

  • Чтение давления: (некомпенсированное значение)

Записываем в регистр «Measurement Control» значение: 0x34 + (OSS<<6);
Ожидаем спад флага состояния «CSO» в «0»;
Читаем результат из регистров «Out MSB», «Out LSB» и «Out xLSB»;
long UP = («Out MSB»<<16 + «Out LSB»<<8 + «Out xLSB») >> (8-OSS);

  • Вычисление действительных значений

Код и подключение.

Датчик достаточно популярный. Чаще всего он идет уже с обвязкой в виде готового модуля. Вы без труда найдете много разных, готовых библиотек. Я остановился на BMP180_Breakout_Arduino_Library. Скачать можно с GitHub  или с  нашего сайта

Подключение описано в библиотеке, но я его продублирую на всякий случай:

SCL(clock) 

  • Uno,Nano,Pro  к     А5
  • Mega,Due         к     21
  • Leonardo          к     3

SDA(Data)

  • Uno,Nano,Pro  к     А4
  • Mega,Due         к     20
  • Leonardo          к     2

VIN  — к +5 вольта.

IO  — Этот вывод есть на некоторых платах, питание в обход стабилизатора. НЕ больше 3.3 вольта.

GND — подключаем к минус.

Ну вот примерочный код с пояснениями :

#include <SFE_BMP180.h>
#include <Wire.h>
 
// Объявим переменную для доступа к SFE_BMP180:
SFE_BMP180 pressure;
 
#define ALTITUDE 203.0 // высота над уровнем моря в метрах. 
 
void setup()
{
 Serial.begin(9600);
 Serial.println("REBOOT"); 
 // инициализация
 if (pressure.begin())
 Serial.println("BMP180 init ok");
 else
 {
 // Если мы тут то что-то не срослось. Как правило косяки с подключением
 Serial.println("BMP180 init fail\n\n");
 while(1); // зависаем
 }
} 
void loop()
{
 char status;
 double T,P,p0,a; 
 // Если вы хотите знать давление воздуха, откорректированное по уровню моря, которое обычно используется в прогнозах погоды
 // Вам надо знать уровень моря в вашей местности где проводится замер
 // Ее и надо указать в константе ALTITUDE в начале кода
 Serial.println();
 Serial.print("Уровень моря: ");
 Serial.print(ALTITUDE,0);
 Serial.print(" метров, ");
 Serial.print(ALTITUDE*3.28084,0);
 Serial.println(" футов");
 
 // Если вы хотите наоборот узнать высоту над уровнем моря, а давление вам известно
 // надо указать текущее атмосферное давление. Как это сделать написано в конце кода.
 // Если все ровно, pressure.startTemperature вернет в status количество милисекунд,
 // которое нужно подождать для замера температуры
 // Если какой-то ошибка, вернет 0
 
 status = pressure.startTemperature();
 if (status != 0)
 {
 // ждем:
 delay(status);
 
 // Получаем температуру
 // Функция вернет 1 если все ОК, 0 если не ОК
 status = pressure.getTemperature(T);
 if (status != 0)
 { 
 Serial.print("Температура: ");
 Serial.print(T,2);
 Serial.print(" градусов C, "); // в цельсиях
 Serial.print((9.0/5.0)*T+32.0,2);
 Serial.println(" градусов F"); // в фаренгейтах
 
 // Определяем атм. давление:
 // Параметр указывает разрешение, от 0 до 3 (чем больше разрешение, тем выше точность, тем дольше ждать). 
 status = pressure.startPressure(3);
 if (status != 0)
 {
 delay(status);
 // Теперь можно получить давление в переменную P.
 //Функция вернет 1 если все ОК, 0 если не ОК.
 status = pressure.getPressure(P,T);
 if (status != 0)
 {
 Serial.print("Абсолютное давление: ");
 Serial.print(P,2);
 Serial.print(" миллибар, "); //millibar (mb)
 Serial.print(P*0.750064,2);
 Serial.println(" мм ртутного столба");
 
 // Параметры: P = давленик с датчика в миллибарах, ALTITUDE = высота над уровнем моря в метрах.
 // Результат: p0 = давление, откорректированное по уровню моря
 
 p0 = pressure.sealevel(P,ALTITUDE);
 Serial.print("Давление по уровню моря: ");
 Serial.print(p0,2);
 Serial.print(" миллибар, ");
 Serial.print(p0*0.750064,2);
 Serial.println("мм ртутного столба");
 
 // Или если вы хотите сделать наоборот и определить высоту над уровнем моря по известному давлению,
 // Parameters: P = давление с датчика в миллибарах, p0 = давление, откорректированное по уровню моря.
 // Результат: a = высота над уровнем моря в метрах.
 
 a = pressure.altitude(P,p0);
 Serial.print("Рассчитанная высота над уровнем моря: ");
 Serial.print(a,0);
 Serial.print(" метров, ");
 Serial.print(a*3.28084,0);
 Serial.println(" футов");
 }
 else Serial.println("ошибка получение давления\n");
 }
 else Serial.println("ошибка запуска получения давления\n");
 }
 else Serial.println("ошибка получения температуры\n");
 }
 else Serial.println("ошибка запуска получения температуры\n");
 
 delay(5000); // пауза 5 секунд.

}