Подключить датчик атмосферного давления BMP280 к Orange Pi PC можно как по I2C, так и по SPI, благо их несколько у Orange Pi PC. Также для работы с GPIO необходимо установить WiringOP, если вы работаете с Orange Pi, а если у вас Banana Pi — BPI-WiringPi.
Барометр на BMP280
BMP280 – это датчик атмосферного давления от BOSCH Sensortec и является улучшенной версией датчика BMP180. Отличается от него меньшими размерами (2 x 2.5 x 0.95 мм), пониженным энергопотреблением, высокой точностью работы и наличием точной заводской калибровки и двумя последовательными интерфейсами: I2C и SPI.
Логика работы датчика BMP280 осталась такой же, но претерпела некоторые долгожданные улучшения.
В таблице приведены улучшения, которые претерпел датчик BMP280:
| Параметр | BMP180 | BMP280 |
|---|---|---|
| Размеры | 3.6 x 3.8 mm | 2.0 x 2.5 mm |
| Мин VDD | 1.80 V | 1.71 V |
| Мин VDDIO | 1.62 V | 1.20 V |
| Потребляемый ток @3 Pa RMS шум | 12 μA | 2.7 μA |
| RMS Шум | 3 Pa | 1.3 Pa |
| Разрешение давления | 1 Pa | 0.16 Pa |
| Разрешение температуры | 0.1°C | 0.01°C |
| Интерфейсы | I²C | I²C & SPI (3 и 4 линии связи, mode ‘00’ and ‘11’) |
| Режимы измерения | Только P или T, принудительное | P и T, принудительное или периодическое |
| Частота измерений | до 120 Гц | до 157 Гц |
| Параметры фильтра | Нет | Пять параметров фильтрации |
Режимами работы
От предыдущих моделей (BMP085 и BMP180) датчик отличается тремя режимами работы:
- SLEEP — режим пониженного энергопотребления
- FORCED – режим, аналогичный, режиму работы датчиков BMP085 и BMP180. По команде контроллера датчик выходит из режима сна, производит измерения, выдает результаты измерения контроллеру и переходит в режим пониженного энергопотребления
- NORMAL — уникальный для этого датчика режим. Датчик самостоятельно просыпается, производит измерения давления и температуры и засыпает. Все временные параметры этого режима программируются независимо. Считывать данные в этом режиме можно в любое время.
Фильтрация результатов измерений
В датчике предусмотрена фильтрация результатов измерений с настройкой таких параметров фильтрации:
- OVERSAMPLING для температуры (16, 17, 18, 19, 20 бит)
- OVERSAMPLING для давления (16, 17, 18, 19, 20 бит)
- TSB – время между между измерениями (0.5, 62.5, 125, 250, 500, 1000, 2000, 4000 мс)
- FILTER_COEFFICIENT – коэффициент фильтрации
Характеристики:
- Напряжение питания: от 1.71 В до 3.6 В
- Макс скорость I2C интерфейса: 3.4 МГц
- Потребляемый ток: 2.7 мкA при частоте отсчетов в 1 Гц
- Интерфейс: I2C, SPI (4 Провода), SPI (3 Провода)
- Калибровка: заводская
- Уровень шума: до 0.2 Па (1.7 см) и 0.01 температуры
- Диапазон измеряемого давления: от 300 hPa до 1100 hPa (9000 м до -500 м)
- Размер: 2.5 мм х 2.0 мм х 0.95 мм
BMP280 библиотека
BMP280RawData.h
#include <stdint.h>
class BMP280RawData {
private:
uint8_t pmsb;
uint8_t plsb;
uint8_t pxsb;
uint8_t tmsb;
uint8_t tlsb;
uint8_t txsb;
uint32_t temperature;
uint32_t pressure;
public:
BMP280RawData(
uint8_t pmsb, uint8_t plsb, uint8_t pxsb,
uint8_t tmsb, uint8_t tlsb, uint8_t txsb,
uint32_t temperature, uint32_t pressure) {
this->pmsb = pmsb;
this->plsb = plsb;
this->pxsb = pxsb;
this->tmsb = tmsb;
this->tlsb = tlsb;
this->txsb = txsb;
this->temperature = temperature;
this->pressure = pressure;
}
BMP280RawData() {
this->pmsb = 0;
this->plsb = 0;
this->pxsb = 0;
this->tmsb = 0;
this->tlsb = 0;
this->txsb = 0;
this->temperature = 0;
this->pressure = 0;
}
virtual ~BMP280RawData() {
}
void setPlsb(uint8_t plsb) {
this->plsb = plsb;
}
void setPmsb(uint8_t pmsb) {
this->pmsb = pmsb;
}
void setPressure(uint32_t pressure) {
this->pressure = pressure;
}
void setPxsb(uint8_t pxsb) {
this->pxsb = pxsb;
}
void setTemperature(uint32_t temperature) {
this->temperature = temperature;
}
void setTlsb(uint8_t tlsb) {
this->tlsb = tlsb;
}
void setTmsb(uint8_t tmsb) {
this->tmsb = tmsb;
}
void setTxsb(uint8_t txsb) {
this->txsb = txsb;
}
uint8_t getPlsb() {
return plsb;
}
uint8_t getPmsb() {
return pmsb;
}
uint32_t getPressure() {
return pressure;
}
uint8_t getPxsb() {
return pxsb;
}
uint32_t getTemperature() {
return temperature;
}
uint8_t getTlsb() {
return tlsb;
}
uint8_t getTmsb() {
return tmsb;
}
uint8_t getTxsb() {
return txsb;
}
};
BMP280CalibrationData.h
#include <stdint.h>
class BMP280CalibrationData {
private:
uint16_t T1;
int16_t T2;
int16_t T3;
uint16_t P1;
int16_t P2;
int16_t P3;
int16_t P4;
int16_t P5;
int16_t P6;
int16_t P7;
int16_t P8;
int16_t P9;
public:
BMP280CalibrationData() {
T1 = 0;
T2 = 0;
T3 = 0;
P1 = 0;
P2 = 0;
P3 = 0;
P4 = 0;
P5 = 0;
P6 = 0;
P7 = 0;
P8 = 0;
P9 = 0;
}
BMP280CalibrationData(
uint16_t T1, int16_t T2, int16_t T3,
uint16_t P1, int16_t P2, int16_t P3,
int16_t P4, int16_t P5, int16_t P6,
int16_t P7, int16_t P8, int16_t P9) {
this->P1 = P1;
this->P2 = P2;
this->P3 = P3;
this->P4 = P4;
this->P5 = P5;
this->P6 = P6;
this->P7 = P7;
this->P8 = P8;
this->P9 = P9;
this->T1 = T1;
this->T2 = T2;
this->T3 = T3;
}
virtual ~BMP280CalibrationData() {
}
void setP1(uint16_t P1) {
this->P1 = P1;
}
void setP2(int16_t P2) {
this->P2 = P2;
}
void setP3(int16_t P3) {
this->P3 = P3;
}
void setP4(int16_t P4) {
this->P4 = P4;
}
void setP5(int16_t P5) {
this->P5 = P5;
}
void setP6(int16_t P6) {
this->P6 = P6;
}
void setP7(int16_t P7) {
this->P7 = P7;
}
void setP8(int16_t P8) {
this->P8 = P8;
}
void setP9(int16_t P9) {
this->P9 = P9;
}
void setT1(uint16_t T1) {
this->T1 = T1;
}
void setT2(int16_t T2) {
this->T2 = T2;
}
void setT3(int16_t T3) {
this->T3 = T3;
}
uint16_t getP1() {
return P1;
}
int16_t getP2() {
return P2;
}
int16_t getP3() {
return P3;
}
int16_t getP4() {
return P4;
}
int16_t getP5() {
return P5;
}
int16_t getP6() {
return P6;
}
int16_t getP7() {
return P7;
}
int16_t getP8() {
return P8;
}
int16_t getP9() {
return P9;
}
uint16_t getT1() {
return T1;
}
int16_t getT2() {
return T2;
}
int16_t getT3() {
return T3;
}
};
BMP280Data.h
class BMP280Data {
private:
double pressure; // hPa
double temperature; // m
double altitude; // °C
public:
BMP280Data() {
pressure = 0;
temperature = 0;
altitude = 0;
}
BMP280Data(double pressure, double temperature, double altitude) {
this->pressure = pressure;
this->temperature = temperature;
this->altitude = altitude;
}
virtual ~BMP280Data() {
}
void setAltitude(double altitude) {
this->altitude = altitude;
}
void setPressure(double pressure) {
this->pressure = pressure;
}
void setTemperature(double temperature) {
this->temperature = temperature;
}
double getAltitude() {
return altitude;
}
double getPressure() {
return pressure;
}
double getTemperature() {
return temperature;
}
};
bmp280.h
#include <stdint.h>
#include "BMP280CalibrationData.h"
#include "BMP280RawData.h"
#include "BMP280Data.h"
#define MEAN_SEA_LEVEL_PRESSURE 1013
/**\name CHIP ID DEFINITION */
/***********************************************/
#define BMP280_CHIP_ID1 (0x56)
#define BMP280_CHIP_ID2 (0x57)
#define BMP280_CHIP_ID3 (0x58)
/************************************************/
/**\name I2C ADDRESS DEFINITION */
/***********************************************/
#define BMP280_I2C_ADDRESS1 (0x76)
#define BMP280_I2C_ADDRESS2 (0x77)
/************************************************/
/**\name POWER MODE DEFINITION */
/***********************************************/
/* Sensor Specific constants */
#define BMP280_SLEEP_MODE (0x00)
#define BMP280_FORCED_MODE (0x01)
#define BMP280_NORMAL_MODE (0x03)
#define BMP280_SOFT_RESET_CODE (0xB6)
/************************************************/
/**\name STANDBY TIME DEFINITION */
/***********************************************/
#define BMP280_STANDBY_TIME_1_MS (0x00)
#define BMP280_STANDBY_TIME_63_MS (0x01)
#define BMP280_STANDBY_TIME_125_MS (0x02)
#define BMP280_STANDBY_TIME_250_MS (0x03)
#define BMP280_STANDBY_TIME_500_MS (0x04)
#define BMP280_STANDBY_TIME_1000_MS (0x05)
#define BMP280_STANDBY_TIME_2000_MS (0x06)
#define BMP280_STANDBY_TIME_4000_MS (0x07)
/************************************************/
/**\name OVERSAMPLING DEFINITION */
/***********************************************/
#define BMP280_OVERSAMP_SKIPPED (0x00)
#define BMP280_OVERSAMP_1X (0x01)
#define BMP280_OVERSAMP_2X (0x02)
#define BMP280_OVERSAMP_4X (0x03)
#define BMP280_OVERSAMP_8X (0x04)
#define BMP280_OVERSAMP_16X (0x05)
/************************************************/
/**\name WORKING MODE DEFINITION */
/***********************************************/
#define BMP280_ULTRA_LOW_POWER_MODE (0x00)
#define BMP280_LOW_POWER_MODE (0x01)
#define BMP280_STANDARD_RESOLUTION_MODE (0x02)
#define BMP280_HIGH_RESOLUTION_MODE (0x03)
#define BMP280_ULTRA_HIGH_RESOLUTION_MODE (0x04)
#define BMP280_ULTRALOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_1X
#define BMP280_ULTRALOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X
#define BMP280_LOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_2X
#define BMP280_LOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X
#define BMP280_STANDARDRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_4X
#define BMP280_STANDARDRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X
#define BMP280_HIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_8X
#define BMP280_HIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X
#define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_16X
#define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_2X
/************************************************/
/**\name FILTER DEFINITION */
/***********************************************/
#define BMP280_FILTER_COEFF_OFF (0x00)
#define BMP280_FILTER_COEFF_2 (0x01)
#define BMP280_FILTER_COEFF_4 (0x02)
#define BMP280_FILTER_COEFF_8 (0x03)
#define BMP280_FILTER_COEFF_16 (0x04)
/************************************************/
/*
* REGISTERS
*/
enum {
BMP280_REGISTER_DIG_T1 = 0x88,
BMP280_REGISTER_DIG_T2 = 0x8A,
BMP280_REGISTER_DIG_T3 = 0x8C,
BMP280_REGISTER_DIG_P1 = 0x8E,
BMP280_REGISTER_DIG_P2 = 0x90,
BMP280_REGISTER_DIG_P3 = 0x92,
BMP280_REGISTER_DIG_P4 = 0x94,
BMP280_REGISTER_DIG_P5 = 0x96,
BMP280_REGISTER_DIG_P6 = 0x98,
BMP280_REGISTER_DIG_P7 = 0x9A,
BMP280_REGISTER_DIG_P8 = 0x9C,
BMP280_REGISTER_DIG_P9 = 0x9E,
BMP280_REGISTER_CHIPID = 0xD0,
BMP280_REGISTER_VERSION = 0xD1,
BMP280_REGISTER_SOFTRESET = 0xE0,
BMP280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0
BMP280_REGISTER_STATUS = 0xF3,
BMP280_REGISTER_CONTROL = 0xF4,
BMP280_REGISTER_CONFIG = 0xF5,
BMP280_REGISTER_PRESSUREDATA_MSB = 0xF7,
BMP280_REGISTER_PRESSUREDATA_LSB = 0xF8,
BMP280_REGISTER_PRESSUREDATA_XLSB = 0xF9,
BMP280_REGISTER_TEMPDATA_MSB = 0xFA,
BMP280_REGISTER_TEMPDATA_LSB = 0xFB,
BMP280_REGISTER_TEMPDATA_XLSB = 0xFC
};
class BMP280 {
private:
char * device;
int devId;
int fd;
uint8_t chipId;
BMP280CalibrationData * bmp280CalibrationData;
BMP280RawData * bmp280RawData;
void write8(uint8_t, uint8_t);
uint8_t read8(uint8_t);
uint16_t read16(uint8_t);
int16_t readS16(uint8_t);
uint16_t readU16(uint8_t);
int32_t getTemperatureC(int32_t adc_T);
double getAltitude(double pressure);
double compensateT(int32_t t_fine);
double compensateP(int32_t adc_P, int32_t t_fine);
BMP280CalibrationData * getCalibrationData();
BMP280RawData * getRawData();
public:
BMP280(int);
BMP280(char *, int);
virtual ~BMP280();
BMP280CalibrationData * getBmp280CalibrationData();
BMP280Data * getBMP280Data();
int init();
void reset();
void spi3wEnable();
void spi3wDisable();
void setPowerMode(uint8_t);
void setTemperatureOversampling(uint8_t);
void setPressureOversampling(uint8_t);
void setStandbyTime(uint8_t);
void setIrrFilter(uint8_t);
uint8_t getPowerMode();
uint8_t getPressureOversampling();
uint8_t getTemperatureOversampling();
uint8_t getIrrFilter();
uint8_t getStandbyTime();
uint8_t getSpi3w();
uint8_t getMeasuringStatus();
uint8_t getImUpdateStatus();
uint8_t getConfig();
uint8_t getStatus();
uint8_t getControl();
uint8_t getChipId();
uint8_t getChipVersion();
void setReset(uint8_t);
void setConfig(uint8_t);
void setStatus(uint8_t);
void setControl(uint8_t);
void setDevice(char *);
};
bmp280.cpp
#include <string.h>
#include <stdint.h>
#include <stdexcept>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <wiringPiI2C.h>
#include <wiringPi.h>
#include "bmp280.h"
BMP280::BMP280(char * device, int devId) : fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) {
setDevice(device);
this->devId = devId;
}
BMP280::BMP280(int devId) : device(0), fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) {
this->devId = devId;
}
BMP280::~BMP280() {
delete bmp280CalibrationData;
delete bmp280RawData;
delete[] device;
}
int BMP280::init() {
int fd = -1;
if (device) {
fd = wiringPiI2CSetupInterface(device, devId);
} else {
int rev = piBoardRev();
if (rev == 1) {
setDevice("/dev/i2c-0");
} else if (rev == 2) {
setDevice("/dev/i2c-1");
} else if (rev == 3) {
setDevice("/dev/i2c-2");
} else {
setDevice("/dev/i2c-3");
}
fd = wiringPiI2CSetupInterface(device, devId);
}
if (fd < 0) {
char buffer[256];
sprintf(buffer, "Device not found: I2C device: %s, device ID: %d", device, devId);
throw std::logic_error(buffer);
}
this->fd = fd;
uint8_t chipId = getChipId();
switch (chipId) {
case BMP280_CHIP_ID1:
case BMP280_CHIP_ID2:
case BMP280_CHIP_ID3:
this->chipId = chipId;
break;
default:
{
char buffer[256];
sprintf(buffer, "Device Chip ID error: chip ID = %d", chipId);
throw std::logic_error(buffer);
}
}
if (bmp280CalibrationData) {
delete bmp280CalibrationData;
}
bmp280CalibrationData = getCalibrationData();
return fd;
}
BMP280CalibrationData * BMP280::getCalibrationData() {
uint16_t T1, P1;
int16_t T2, T3, P2, P3, P4, P5, P6, P7, P8, P9;
T1 = readU16(BMP280_REGISTER_DIG_T1);
T2 = readS16(BMP280_REGISTER_DIG_T2);
T3 = readS16(BMP280_REGISTER_DIG_T3);
P1 = readU16(BMP280_REGISTER_DIG_P1);
P2 = readS16(BMP280_REGISTER_DIG_P2);
P3 = readS16(BMP280_REGISTER_DIG_P3);
P4 = readS16(BMP280_REGISTER_DIG_P4);
P5 = readS16(BMP280_REGISTER_DIG_P5);
P6 = readS16(BMP280_REGISTER_DIG_P6);
P7 = readS16(BMP280_REGISTER_DIG_P7);
P8 = readS16(BMP280_REGISTER_DIG_P8);
P9 = readS16(BMP280_REGISTER_DIG_P9);
return new BMP280CalibrationData(T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9);
}
BMP280CalibrationData * BMP280::getBmp280CalibrationData() {
return bmp280CalibrationData;
}
BMP280RawData * BMP280::getRawData() {
uint8_t pmsb, plsb, pxsb;
uint8_t tmsb, tlsb, txsb;
uint32_t temperature, pressure;
plsb = read8(BMP280_REGISTER_PRESSUREDATA_LSB);
pmsb = read8(BMP280_REGISTER_PRESSUREDATA_MSB);
pxsb = read8(BMP280_REGISTER_PRESSUREDATA_XLSB);
tmsb = read8(BMP280_REGISTER_TEMPDATA_MSB);
tlsb = read8(BMP280_REGISTER_TEMPDATA_LSB);
txsb = read8(BMP280_REGISTER_TEMPDATA_XLSB);
temperature = 0;
temperature = (temperature | tmsb) << 8;
temperature = (temperature | tlsb) << 8;
temperature = (temperature | txsb) >> 4;
pressure = 0;
pressure = (pressure | pmsb) << 8;
pressure = (pressure | plsb) << 8;
pressure = (pressure | pxsb) >> 4;
return new BMP280RawData(pmsb, plsb, pxsb, tmsb, tlsb, txsb, temperature, pressure);
}
void BMP280::reset() {
setReset(BMP280_SOFT_RESET_CODE);
}
void BMP280::spi3wEnable() {
uint8_t config = getConfig();
setConfig(config | 0b00000001);
}
void BMP280::spi3wDisable() {
uint8_t config = getConfig();
setConfig(config & 0b11111110);
}
void BMP280::setPowerMode(uint8_t mode) {
switch (mode) {
case BMP280_FORCED_MODE:
case BMP280_NORMAL_MODE:
case BMP280_SLEEP_MODE:
{
uint8_t curentMode = getControl() & 0b11111100;
setControl(curentMode | mode);
break;
}
default:break;
}
}
void BMP280::setTemperatureOversampling(uint8_t oversampling) {
switch (oversampling) {
case BMP280_OVERSAMP_SKIPPED:
case BMP280_OVERSAMP_1X:
case BMP280_OVERSAMP_2X:
case BMP280_OVERSAMP_4X:
case BMP280_OVERSAMP_8X:
case BMP280_OVERSAMP_16X:
{
uint8_t curentOversampling = getControl() & 0b00011111;
setControl(curentOversampling | (oversampling << 5));
break;
}
default:break;
}
}
void BMP280::setPressureOversampling(uint8_t oversampling) {
switch (oversampling) {
case BMP280_OVERSAMP_SKIPPED:
case BMP280_OVERSAMP_1X:
case BMP280_OVERSAMP_2X:
case BMP280_OVERSAMP_4X:
case BMP280_OVERSAMP_8X:
case BMP280_OVERSAMP_16X:
{
uint8_t curentOversampling = getControl() & 0b11100011;
setControl(curentOversampling | (oversampling << 2));
break;
}
default:break;
}
}
void BMP280::setStandbyTime(uint8_t tStandby) {
switch (tStandby) {
case BMP280_STANDBY_TIME_1_MS:
case BMP280_STANDBY_TIME_63_MS:
case BMP280_STANDBY_TIME_125_MS:
case BMP280_STANDBY_TIME_250_MS:
case BMP280_STANDBY_TIME_500_MS:
case BMP280_STANDBY_TIME_1000_MS:
case BMP280_STANDBY_TIME_2000_MS:
case BMP280_STANDBY_TIME_4000_MS:
{
uint8_t config = getConfig() & 0b00011111;
setConfig(config | (tStandby << 5));
break;
}
default:break;
}
}
void BMP280::setIrrFilter(uint8_t irrFilter) {
switch (irrFilter) {
case BMP280_FILTER_COEFF_OFF:
case BMP280_FILTER_COEFF_2:
case BMP280_FILTER_COEFF_4:
case BMP280_FILTER_COEFF_8:
case BMP280_FILTER_COEFF_16:
{
uint8_t config = getConfig() & 0b11100011;
setConfig(config | (irrFilter << 2));
break;
}
default:break;
}
}
uint8_t BMP280::getPowerMode() {
return getControl() & 0b00000011;
}
uint8_t BMP280::getPressureOversampling() {
return (getControl() & 0b00011100) >> 2;
}
uint8_t BMP280::getTemperatureOversampling() {
return (getControl() & 0b11100000) >> 5;
}
uint8_t BMP280::getIrrFilter() {
return (getConfig() & 0b00011100) >> 2;
}
uint8_t BMP280::getStandbyTime() {
return (getConfig() & 0b11100000) >> 5;
}
uint8_t BMP280::getSpi3w() {
return (getConfig() & 0b00000001);
}
uint8_t BMP280::getMeasuringStatus() {
return (getStatus() >> 3) & 0b00000001;
}
uint8_t BMP280::getImUpdateStatus() {
return getStatus() & 0b00000001;
}
uint8_t BMP280::getConfig() {
return read8(BMP280_REGISTER_CONFIG);
}
uint8_t BMP280::getStatus() {
return read8(BMP280_REGISTER_STATUS);
}
uint8_t BMP280::getControl() {
return read8(BMP280_REGISTER_CONTROL);
}
uint8_t BMP280::getChipId() {
return read8(BMP280_REGISTER_CHIPID);
}
uint8_t BMP280::getChipVersion() {
return read8(BMP280_REGISTER_VERSION);
}
void BMP280::setReset(uint8_t value) {
write8(BMP280_REGISTER_SOFTRESET, value);
}
void BMP280::setConfig(uint8_t value) {
return write8(BMP280_REGISTER_CONFIG, value);
}
void BMP280::setStatus(uint8_t value) {
return write8(BMP280_REGISTER_STATUS, value);
}
void BMP280::setControl(uint8_t value) {
return write8(BMP280_REGISTER_CONTROL, value);
}
double BMP280::getAltitude(double pressure) {
return 44330.0 * (1.0 - pow(pressure / MEAN_SEA_LEVEL_PRESSURE, 0.190294957));
}
int32_t BMP280::getTemperatureC(int32_t adc_T) {
int32_t var1 = ((((adc_T >> 3) - ((int32_t) bmp280CalibrationData->getT1() << 1))) *
((int32_t) bmp280CalibrationData->getT2())) >> 11;
int32_t var2 = (((((adc_T >> 4) - ((int32_t) bmp280CalibrationData->getT1())) *
((adc_T >> 4) - ((int32_t) bmp280CalibrationData->getT1()))) >> 12) *
((int32_t) bmp280CalibrationData->getT3())) >> 14;
return var1 + var2;
}
double BMP280::compensateT(int32_t t_fine) {
double T = (t_fine * 5 + 128) >> 8;
return T / 100;
}
double BMP280::compensateP(int32_t adc_P, int32_t t_fine) {
int64_t var1, var2, p;
var1 = ((int64_t) t_fine) - 128000;
var2 = var1 * var1 * (int64_t) bmp280CalibrationData->getP6();
var2 = var2 + ((var1 * (int64_t) bmp280CalibrationData->getP5()) << 17);
var2 = var2 + (((int64_t) bmp280CalibrationData->getP4()) << 35);
var1 = ((var1 * var1 * (int64_t) bmp280CalibrationData->getP3()) >> 8) +
((var1 * (int64_t) bmp280CalibrationData->getP2()) << 12);
var1 = (((((int64_t) 1) << 47) + var1))*((int64_t) bmp280CalibrationData->getP1()) >> 33;
if (var1 == 0) {
return 0; // avoid exception caused by division by zero
}
p = 1048576 - adc_P;
p = (((p << 31) - var2)*3125) / var1;
var1 = (((int64_t) bmp280CalibrationData->getP9()) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((int64_t) bmp280CalibrationData->getP8()) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t) bmp280CalibrationData->getP7()) << 4);
return (double) p / 256;
}
BMP280Data * BMP280::getBMP280Data() {
int32_t t_fine;
double t, p, a;
while (getMeasuringStatus()) {
}
if (bmp280RawData) {
delete bmp280RawData;
}
bmp280RawData = getRawData();
t_fine = getTemperatureC(bmp280RawData->getTemperature());
t = compensateT(t_fine); // C
p = compensateP(bmp280RawData->getPressure(), t_fine) / 100; // hPa
a = getAltitude(p); // meters
return new BMP280Data(p, t, a);
}
void BMP280::setDevice(char * device) {
if (device) {
this->device = new char[strlen(device)];
strcpy(this->device, device);
}
}
void BMP280::write8(uint8_t reg, uint8_t value) {
wiringPiI2CWriteReg8(fd, reg, value);
}
uint8_t BMP280::read8(uint8_t reg) {
return wiringPiI2CReadReg8(fd, reg);
}
uint16_t BMP280::read16(uint8_t reg) {
return wiringPiI2CReadReg16(fd, reg);
}
int16_t BMP280::readS16(uint8_t reg) {
return (int16_t) read16(reg);
}
uint16_t BMP280::readU16(uint8_t reg) {
return (uint16_t) read16(reg);
}
Схема подключения BMP280 к Orange Pi
Я с этими датчиками работаю только по I2C. Подключяется BMP280 к Orange Pi очень просто: на Vcc даём 3.3 В, GND, SCL и SDA.
Рабочее напряжение датчика от 1.71 В до 3.6 В. Не стоит питать от 5 В, так как вероятность того, что он выйдет из строя, очень высока.
Ниже приведён пример программы для проверки вышеуказанной библиотеки.
Данная программа создаёт новый объект для работы с датчиком:
BMP280 * bmp280 = new BMP280(device, devId);
соединяется с датчиком:
int fd = bmp280->init();
и сбрасывает все его настройки:
bmp280->reset();
после чего задаёт новые настройки (режим работы, фильтры и др.):
bmp280->setPowerMode(BMP280_NORMAL_MODE); bmp280->setTemperatureOversampling(BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE); bmp280->setPressureOversampling(BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE); bmp280->setIrrFilter(BMP280_FILTER_COEFF_16); bmp280->setStandbyTime(BMP280_STANDBY_TIME_250_MS);
и раз в секунду читает и выводит на экран данные с BMP280:
while (1) {
delay(1000);
BMP280Data * bmp280Data = bmp280->getBMP280Data();
printf("pressure : %.2f hPa\n", bmp280Data->getPressure());
printf("temperature: %.2f °C\n", bmp280Data->getTemperature());
printf("altitude : %.2f m\n\n", bmp280Data->getAltitude());
delete bmp280Data;
}
main.cpp
#include <stdio.h>
#include <iostream>
#include <stdexcept>
#include <wiringPi.h>
#include "bmp280.h"
int main(int argc, char **argv) {
// char * device = "/dev/i2c-0";
// char * device = "/dev/i2c-1";
char * device = "/dev/i2c-2";
// char * device = "/dev/i2c-3";
int devId = BMP280_I2C_ADDRESS1;
try {
BMP280 * bmp280 = new BMP280(device, devId);
int fd = bmp280->init();
if (fd < 0) {
printf("Device not found");
return -1;
}
printf("fd : 0x%02x\n", fd);
printf("chip id : 0x%02x\n", bmp280->getChipId());
printf("chip ver : 0x%02x\n", bmp280->getChipVersion());
bmp280->reset();
bmp280->setPowerMode(BMP280_NORMAL_MODE);
bmp280->setTemperatureOversampling(BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE);
bmp280->setPressureOversampling(BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE);
bmp280->setIrrFilter(BMP280_FILTER_COEFF_16);
bmp280->setStandbyTime(BMP280_STANDBY_TIME_250_MS);
printf("---------------\n");
printf("pw mode : 0x%02x\n", bmp280->getPowerMode());
printf("osrs_p : 0x%02x\n", bmp280->getPressureOversampling());
printf("osrs_t : 0x%02x\n", bmp280->getTemperatureOversampling());
printf("---------------\n");
printf("filter : 0x%02x\n", bmp280->getIrrFilter());
printf("t_sb : 0x%02x\n", bmp280->getStandbyTime());
printf("---------------\n");
printf("spi3w sts: 0x%02x\n", bmp280->getSpi3w());
printf("measuring: 0x%02x\n", bmp280->getMeasuringStatus());
printf("im_update: 0x%02x\n", bmp280->getImUpdateStatus());
printf("---------------\n");
while (1) {
delay(1000);
BMP280Data * bmp280Data = bmp280->getBMP280Data();
printf("pressure : %.2f hPa\n", bmp280Data->getPressure());
printf("temperature: %.2f °C\n", bmp280Data->getTemperature());
printf("altitude : %.2f m\n\n", bmp280Data->getAltitude());
delete bmp280Data;
}
delete bmp280;
} catch (std::exception & e) {
printf("%s\n", e.what());
}
return 0;
}
Результат
Скачать проект CodeLite
Для программирования на С/С++ я использую CodeLite IDE, так как с Code::Blocks у меня были проблемы.
Проект: BMP280_Banana_Pi_M3.zip
Flyer: BST-BMP280-FL000-00 (Bosch_Sensortec_Flyer_BMP280_onl.pdf)
Datasheet: BST-BMP280-DS001-12 (BST-BMP280-DS001-12.pdf)
Driver: BMP280 driver










