Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry Pi

Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry PiBME280 представляет собой интегрированный датчик окружающей среды, разработанный специально для мобильных устройств, где размер и низкое энергопотребление являются ключевыми.

Датчик BME280 очень похож с BMP280, различие в том, что BME280 имеет датчик влажности от чего его корпус шире чем у BMP280. Количество выводов и их расположение на корпусах совпадают. Более детальное описание датчика вы можете найти на странице BME280 — датчик давления, температуры и влажности.

Подключить датчик окружающей среды BME280 к Orange Pi PC можно по I2C и по SPI, их несколько как у Orange Pi, так и у Banana Pi и Raspberry Pi. Также для работы с GPIO необходимо установить WiringOP, если вы работаете с Orange Pi, а если у вас Banana Pi — BPI-WiringPi.

Схема подключения BME280 к Orange Pi/Banana Pi/Raspberry Pi

С этим датчиком я работаю только по I2C. Подключается BME280 к Orange Pi также, как к Banana Pi и Raspberry Pi, у всех GPIO (на 40 пинов) похожие. В данном случае я использовал порт /dev/i2c-2, потому что удобно расположен.

Подключение BME280 к Orange Pi, Banana Pi, Raspberry Pi - GPIO40

Код программы

Проект написан на С/С++. Использую среду разработки CodeLite IDE, так как среда Code::Blocks у меня не работает нормально.

BME280RawData.h

#include <stdint.h>

class BME280RawData {
private:
  uint8_t pmsb;
  uint8_t plsb;
  uint8_t pxsb;

  uint8_t tmsb;
  uint8_t tlsb;
  uint8_t txsb;

  uint8_t hmsb;
  uint8_t hlsb;

  uint32_t temperature;
  uint32_t pressure;
  uint32_t humidity;
public:
  BME280RawData(uint8_t pmsb, uint8_t plsb, uint8_t pxsb, uint8_t tmsb, uint8_t tlsb, uint8_t txsb, uint8_t hmsb, uint8_t hlsb, uint32_t temperature, uint32_t pressure,
      uint32_t humidity) {
    this->pmsb = pmsb;
    this->plsb = plsb;
    this->pxsb = pxsb;
    this->tmsb = tmsb;
    this->tlsb = tlsb;
    this->txsb = txsb;
    this->hmsb = hmsb;
    this->hlsb = hlsb;
    this->temperature = temperature;
    this->pressure = pressure;
    this->humidity = humidity;
  }

  BME280RawData() {
    this->pmsb = 0;
    this->plsb = 0;
    this->pxsb = 0;
    this->tmsb = 0;
    this->tlsb = 0;
    this->txsb = 0;
    this->hmsb = 0;
    this->hlsb = 0;
    this->temperature = 0;
    this->pressure = 0;
    this->humidity = 0;
  }

  virtual ~BME280RawData() {
  }

  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;
  }

  void setHlsb(uint8_t hlsb) {
    this->hlsb = hlsb;
  }
  void setHmsb(uint8_t hmsb) {
    this->hmsb = hmsb;
  }
  void setHumidity(uint32_t humidity) {
    this->humidity = humidity;
  }
  uint8_t getHlsb() {
    return hlsb;
  }
  uint8_t getHmsb() {
    return hmsb;
  }
  uint32_t getHumidity() {
    return humidity;
  }
};

BME280CalibrationData.h

#include <stdint.h>

class BME280CalibrationData {
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;

  uint8_t H1;
  int16_t H2;
  uint8_t H3;
  int16_t H4;
  int16_t H5;
  int8_t H6;

public:
  BME280CalibrationData() {
    T1 = 0;
    T2 = 0;
    T3 = 0;
    P1 = 0;
    P2 = 0;
    P3 = 0;
    P4 = 0;
    P5 = 0;
    P6 = 0;
    P7 = 0;
    P8 = 0;
    P9 = 0;
    H1 = 0;
    H2 = 0;
    H3 = 0;
    H4 = 0;
    H5 = 0;
    H6 = 0;
  }

  BME280CalibrationData(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,
      uint8_t H1, int16_t H2, uint8_t H3, int16_t H4, int16_t H5, int8_t H6) {
    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;
    this->H1 = H1;
    this->H2 = H2;
    this->H3 = H3;
    this->H4 = H4;
    this->H5 = H5;
    this->H6 = H6;
  }

  virtual ~BME280CalibrationData() {
  }

  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;
  }

  void setH1(uint8_t H1) {
    this->H1 = H1;
  }
  void setH2(int16_t H2) {
    this->H2 = H2;
  }
  void setH3(uint8_t H3) {
    this->H3 = H3;
  }
  void setH4(int16_t H4) {
    this->H4 = H4;
  }
  void setH5(int16_t H5) {
    this->H5 = H5;
  }
  void setH6(int8_t H6) {
    this->H6 = H6;
  }
  uint8_t getH1() {
    return H1;
  }
  int16_t getH2() {
    return H2;
  }
  uint8_t getH3() {
    return H3;
  }
  int16_t getH4() {
    return H4;
  }
  int16_t getH5() {
    return H5;
  }
  int8_t getH6() {
    return H6;
  }
};

BME280Data.h

class BMP280Data {
private:
  double pressure;    // hPa
  double temperature; // m
  double humidity;    // %
  double altitude;    // °C
public:
  BMP280Data() {
    pressure = 0;
    temperature = 0;
    altitude = 0;
    humidity = 0;
  }
  BMP280Data(double pressure, double temperature, double humidity, double altitude) {
    this->pressure = pressure;
    this->temperature = temperature;
    this->humidity = humidity;
    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;
  }
  void setHumidity(double humidity) {
    this->humidity = humidity;
  }
  double getHumidity() {
    return humidity;
  }
};

bme280.h

#include <stdint.h>
#include "BME280CalibrationData.h"
#include "BME280RawData.h"
#include "BME280Data.h"

#define MEAN_SEA_LEVEL_PRESSURE       1013

/**\name    CHIP ID DEFINITION       */
/***********************************************/
#define BME280_CHIP_ID1     (0x60)
/************************************************/
/**\name    I2C ADDRESS DEFINITION       */
/***********************************************/
#define BME280_I2C_ADDRESS1                  (0x76)
#define BME280_I2C_ADDRESS2                  (0x77)
/************************************************/
/**\name    POWER MODE DEFINITION       */
/***********************************************/
/* Sensor Specific constants */
#define BME280_SLEEP_MODE                    (0x00)
#define BME280_FORCED_MODE                   (0x01)
#define BME280_NORMAL_MODE                   (0x03)
#define BME280_SOFT_RESET_CODE               (0xB6)
/************************************************/
/**\name    STANDBY TIME DEFINITION       */
/***********************************************/
#define BME280_STANDBY_TIME_1_MS              (0x00)
#define BME280_STANDBY_TIME_63_MS             (0x01)
#define BME280_STANDBY_TIME_125_MS            (0x02)
#define BME280_STANDBY_TIME_250_MS            (0x03)
#define BME280_STANDBY_TIME_500_MS            (0x04)
#define BME280_STANDBY_TIME_1000_MS           (0x05)
#define BME280_STANDBY_TIME_2000_MS           (0x06)
#define BME280_STANDBY_TIME_4000_MS           (0x07)
/************************************************/
/**\name    OVERSAMPLING DEFINITION       */
/***********************************************/
#define BME280_OVERSAMP_SKIPPED          (0x00)
#define BME280_OVERSAMP_1X               (0x01)
#define BME280_OVERSAMP_2X               (0x02)
#define BME280_OVERSAMP_4X               (0x03)
#define BME280_OVERSAMP_8X               (0x04)
#define BME280_OVERSAMP_16X              (0x05)
/************************************************/
/**\name    WORKING MODE DEFINITION       */
/***********************************************/
#define BME280_ULTRA_LOW_POWER_MODE          (0x00)
#define BME280_LOW_POWER_MODE                (0x01)
#define BME280_STANDARD_RESOLUTION_MODE      (0x02)
#define BME280_HIGH_RESOLUTION_MODE          (0x03)
#define BME280_ULTRA_HIGH_RESOLUTION_MODE    (0x04)

#define BME280_ULTRALOWPOWER_OVERSAMP_PRESSURE          BME280_OVERSAMP_1X
#define BME280_ULTRALOWPOWER_OVERSAMP_HUMIDITY          BME280_OVERSAMP_1X
#define BME280_ULTRALOWPOWER_OVERSAMP_TEMPERATURE       BME280_OVERSAMP_1X

#define BME280_LOWPOWER_OVERSAMP_PRESSURE               BME280_OVERSAMP_2X
#define BME280_LOWPOWER_OVERSAMP_HUMIDITY               BME280_OVERSAMP_2X
#define BME280_LOWPOWER_OVERSAMP_TEMPERATURE            BME280_OVERSAMP_1X

#define BME280_STANDARDRESOLUTION_OVERSAMP_PRESSURE     BME280_OVERSAMP_4X
#define BME280_STANDARDRESOLUTION_OVERSAMP_HUMIDITY     BME280_OVERSAMP_4X
#define BME280_STANDARDRESOLUTION_OVERSAMP_TEMPERATURE  BME280_OVERSAMP_1X

#define BME280_HIGHRESOLUTION_OVERSAMP_PRESSURE         BME280_OVERSAMP_8X
#define BME280_HIGHRESOLUTION_OVERSAMP_HUMIDITY         BME280_OVERSAMP_8X
#define BME280_HIGHRESOLUTION_OVERSAMP_TEMPERATURE      BME280_OVERSAMP_1X

#define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE    BME280_OVERSAMP_16X
#define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_HUMIDITY    BME280_OVERSAMP_16X
#define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE BME280_OVERSAMP_2X
/************************************************/
/**\name    FILTER DEFINITION       */
/***********************************************/
#define BME280_FILTER_COEFF_OFF               (0x00)
#define BME280_FILTER_COEFF_2                 (0x01)
#define BME280_FILTER_COEFF_4                 (0x02)
#define BME280_FILTER_COEFF_8                 (0x03)
#define BME280_FILTER_COEFF_16                (0x04)
/************************************************/

/*
 * REGISTERS
 */
#define BME280_ADDRESS                      0x76
#define BME280_REGISTER_DIG_T1              0x88
#define BME280_REGISTER_DIG_T2              0x8A
#define BME280_REGISTER_DIG_T3              0x8C
#define BME280_REGISTER_DIG_P1              0x8E
#define BME280_REGISTER_DIG_P2              0x90
#define BME280_REGISTER_DIG_P3              0x92
#define BME280_REGISTER_DIG_P4              0x94
#define BME280_REGISTER_DIG_P5              0x96
#define BME280_REGISTER_DIG_P6              0x98
#define BME280_REGISTER_DIG_P7              0x9A
#define BME280_REGISTER_DIG_P8              0x9C
#define BME280_REGISTER_DIG_P9              0x9E
#define BME280_REGISTER_DIG_H1              0xA1
#define BME280_REGISTER_DIG_H2              0xE1
#define BME280_REGISTER_DIG_H3              0xE3
#define BME280_REGISTER_DIG_H4              0xE4
#define BME280_REGISTER_DIG_H5              0xE5
#define BME280_REGISTER_DIG_H6              0xE7
#define BME280_REGISTER_CHIPID              0xD0
#define BME280_REGISTER_VERSION             0xD1
#define BME280_REGISTER_SOFTRESET           0xE0
#define BME280_RESET                        0xB6
#define BME280_REGISTER_CAL26               0xE1
#define BME280_REGISTER_CONTROLHUMID        0xF2
#define BME280_REGISTER_STATUS              0xF3
#define BME280_REGISTER_CONTROL             0xF4
#define BME280_REGISTER_CONFIG              0xF5
#define BME280_REGISTER_PRESSUREDATA_MSB    0xF7
#define BME280_REGISTER_PRESSUREDATA_LSB    0xF8
#define BME280_REGISTER_PRESSUREDATA_XLSB   0xF9
#define BME280_REGISTER_TEMPDATA_MSB        0xFA
#define BME280_REGISTER_TEMPDATA_LSB        0xFB
#define BME280_REGISTER_TEMPDATA_XLSB       0xFC
#define BME280_REGISTER_HUMIDDATA_MSB       0xFD
#define BME280_REGISTER_HUMIDDATA_LSB       0xFE

class BME280 {
private:
  char * device;
  int devId;
  int fd;
  uint8_t chipId;
  BME280CalibrationData * bmp280CalibrationData;
  BME280RawData * bmp280RawData;

  void write8(uint8_t, uint8_t);
  int read8(uint8_t);
  uint8_t readU8(uint8_t);
  int8_t readS8(uint8_t);
  int 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 compensateTemperature(int32_t t_fine);
  double compensatePressure(int32_t adc_P, int32_t t_fine);
  double compensateHumidity(int32_t adc_H, int32_t t_fine);
  BME280CalibrationData * getCalibrationData();
  BME280RawData * getRawData();

public:
  BME280(const char*, int);
  BME280(int);
  virtual ~BME280();

  BME280CalibrationData * getBmp280CalibrationData();
  BMP280Data * getBMP280Data();

  int init();
  void reset();
  void spi3wEnable();
  void spi3wDisable();
  void setPowerMode(uint8_t);
  void setTemperatureOversampling(uint8_t);
  void setPressureOversampling(uint8_t);
  void setHumidityOversampling(uint8_t);
  void setStandbyTime(uint8_t);
  void setIrrFilter(uint8_t);
  uint8_t getPowerMode();
  uint8_t getPressureOversampling();
  uint8_t getHumidityOversampling();
  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 getControlHumidity();
  uint8_t getChipId();
  uint8_t getChipVersion();
  void setReset(uint8_t);
  void setConfig(uint8_t);
  void setStatus(uint8_t);
  void setControl(uint8_t);
  void setControlHumidity(uint8_t);
};

bme280.cpp

#include <string.h>
#include <stdint.h>
#include <stdexcept>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <wiringPiI2C.h>
#include "bme280.h"

void BME280::write8(uint8_t reg, uint8_t value) {
  wiringPiI2CWriteReg8(fd, reg, value);
}

int BME280::read8(uint8_t reg) {
  return wiringPiI2CReadReg8(fd, reg);
}

uint8_t BME280::readU8(uint8_t reg) {
  return (uint8_t) read8(reg);
}

int8_t BME280::readS8(uint8_t reg) {
  return (int8_t) read8(reg);
}

int BME280::read16(uint8_t reg) {
  return wiringPiI2CReadReg16(fd, reg);
}

int16_t BME280::readS16(uint8_t reg) {
  return (int16_t) read16(reg);
}

uint16_t BME280::readU16(uint8_t reg) {
  return (uint16_t) read16(reg);
}

BME280::BME280(const char * device, int devId) :
    fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) {
  this->device = new char[strlen(device)];
  strcpy(this->device, device);
  this->devId = devId;
}

BME280::BME280(int devId) :
    fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) {
  this->devId = devId;
}

BME280::~BME280() {
  delete bmp280CalibrationData;
  delete bmp280RawData;
  delete[] device;
}

int BME280::init() {
  int fd = wiringPiI2CSetup(devId);
  if (fd < 0) {
    char buffer[256];
    sprintf(buffer, "Device not found: device ID = %d", devId);
    throw std::logic_error(buffer);
  }
  this->fd = fd;
  uint8_t chipId = getChipId();
  switch (chipId) {
  case BME280_CHIP_ID1:
    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;
}

BME280CalibrationData * BME280::getCalibrationData() {
  int8_t H6;
  uint8_t H1, H3;
  int16_t T2, T3, P2, P3, P4, P5, P6, P7, P8, P9, H2, H4, H5;
  uint16_t T1, P1;

  T1 = readU16(BME280_REGISTER_DIG_T1);
  T2 = readS16(BME280_REGISTER_DIG_T2);
  T3 = readS16(BME280_REGISTER_DIG_T3);
  P1 = readU16(BME280_REGISTER_DIG_P1);
  P2 = readS16(BME280_REGISTER_DIG_P2);
  P3 = readS16(BME280_REGISTER_DIG_P3);
  P4 = readS16(BME280_REGISTER_DIG_P4);
  P5 = readS16(BME280_REGISTER_DIG_P5);
  P6 = readS16(BME280_REGISTER_DIG_P6);
  P7 = readS16(BME280_REGISTER_DIG_P7);
  P8 = readS16(BME280_REGISTER_DIG_P8);
  P9 = readS16(BME280_REGISTER_DIG_P9);
  H1 = readU8(BME280_REGISTER_DIG_H1);
  H2 = readS16(BME280_REGISTER_DIG_H2);
  H3 = readU8(BME280_REGISTER_DIG_H3);
  H4 = (int16_t)((read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF));
  H5 = (int16_t)((read8(BME280_REGISTER_DIG_H5 + 1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4));
  H6 = readS8(BME280_REGISTER_DIG_H6);

  return new BME280CalibrationData(T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9, H1, H2, H3, H4, H5, H6);
}

BME280CalibrationData * BME280::getBmp280CalibrationData() {
  return bmp280CalibrationData;
}

BME280RawData * BME280::getRawData() {
  uint8_t pmsb, plsb, pxsb;
  uint8_t tmsb, tlsb, txsb;
  uint8_t hmsb, hlsb;
  uint32_t temperature, pressure, humidity;

  plsb = readU8(BME280_REGISTER_PRESSUREDATA_LSB);
  pmsb = readU8(BME280_REGISTER_PRESSUREDATA_MSB);
  pxsb = readU8(BME280_REGISTER_PRESSUREDATA_XLSB);

  tmsb = readU8(BME280_REGISTER_TEMPDATA_MSB);
  tlsb = readU8(BME280_REGISTER_TEMPDATA_LSB);
  txsb = readU8(BME280_REGISTER_TEMPDATA_XLSB);

  hmsb = readU8(BME280_REGISTER_HUMIDDATA_MSB);
  hlsb = readU8(BME280_REGISTER_HUMIDDATA_LSB);

  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;

  humidity = 0;
  humidity = (humidity | hmsb) << 8;
  humidity = (humidity | hlsb);

  return new BME280RawData(pmsb, plsb, pxsb, tmsb, tlsb, txsb, hmsb, hlsb, temperature, pressure, humidity);
}

void BME280::reset() {
  setReset (BME280_SOFT_RESET_CODE);
}

void BME280::spi3wEnable() {
  uint8_t config = getConfig();
  setConfig(config | 0b00000001);
}

void BME280::spi3wDisable() {
  uint8_t config = getConfig();
  setConfig(config & 0b11111110);
}

void BME280::setPowerMode(uint8_t mode) {
  switch (mode) {
  case BME280_FORCED_MODE:
  case BME280_NORMAL_MODE:
  case BME280_SLEEP_MODE: {
    uint8_t curentMode = getControl() & 0b11111100;
    setControl(curentMode | mode);
    break;
  }
  default:
    break;
  }
}

void BME280::setTemperatureOversampling(uint8_t oversampling) {
  switch (oversampling) {
  case BME280_OVERSAMP_SKIPPED:
  case BME280_OVERSAMP_1X:
  case BME280_OVERSAMP_2X:
  case BME280_OVERSAMP_4X:
  case BME280_OVERSAMP_8X:
  case BME280_OVERSAMP_16X: {
    uint8_t curentOversampling = getControl() & 0b00011111;
    setControl(curentOversampling | (oversampling << 5));
    break;
  }
  default:
    break;
  }
}

void BME280::setPressureOversampling(uint8_t oversampling) {
  switch (oversampling) {
  case BME280_OVERSAMP_SKIPPED:
  case BME280_OVERSAMP_1X:
  case BME280_OVERSAMP_2X:
  case BME280_OVERSAMP_4X:
  case BME280_OVERSAMP_8X:
  case BME280_OVERSAMP_16X: {
    uint8_t curentOversampling = getControl() & 0b11100011;
    setControl(curentOversampling | (oversampling << 2));
    break;
  }
  default:
    break;
  }
}

void BME280::setHumidityOversampling(uint8_t oversampling) {
  switch (oversampling) {
  case BME280_OVERSAMP_SKIPPED:
  case BME280_OVERSAMP_1X:
  case BME280_OVERSAMP_2X:
  case BME280_OVERSAMP_4X:
  case BME280_OVERSAMP_8X:
  case BME280_OVERSAMP_16X: {
    setControlHumidity(0b00000111 & oversampling);
    break;
  }
  default:
    break;
  }
}

uint8_t BME280::getHumidityOversampling() {
  return getControlHumidity() & 0b00000111;
}

void BME280::setStandbyTime(uint8_t tStandby) {
  switch (tStandby) {
  case BME280_STANDBY_TIME_1_MS:
  case BME280_STANDBY_TIME_63_MS:
  case BME280_STANDBY_TIME_125_MS:
  case BME280_STANDBY_TIME_250_MS:
  case BME280_STANDBY_TIME_500_MS:
  case BME280_STANDBY_TIME_1000_MS:
  case BME280_STANDBY_TIME_2000_MS:
  case BME280_STANDBY_TIME_4000_MS: {
    uint8_t config = getConfig() & 0b00011111;
    setConfig(config | (tStandby << 5));
    break;
  }
  default:
    break;
  }
}

void BME280::setIrrFilter(uint8_t irrFilter) {
  switch (irrFilter) {
  case BME280_FILTER_COEFF_OFF:
  case BME280_FILTER_COEFF_2:
  case BME280_FILTER_COEFF_4:
  case BME280_FILTER_COEFF_8:
  case BME280_FILTER_COEFF_16: {
    uint8_t config = getConfig() & 0b11100011;
    setConfig(config | (irrFilter << 2));
    break;
  }
  default:
    break;
  }
}

uint8_t BME280::getPowerMode() {
  return getControl() & 0b00000011;
}

uint8_t BME280::getPressureOversampling() {
  return (getControl() & 0b00011100) >> 2;
}

uint8_t BME280::getTemperatureOversampling() {
  return (getControl() & 0b11100000) >> 5;
}

uint8_t BME280::getIrrFilter() {
  return (getConfig() & 0b00011100) >> 2;
}

uint8_t BME280::getStandbyTime() {
  return (getConfig() & 0b11100000) >> 5;
}

uint8_t BME280::getSpi3w() {
  return (getConfig() & 0b00000001) >> 5;
}

uint8_t BME280::getMeasuringStatus() {
  return (getStatus() >> 3) & 0b00000001;
}

uint8_t BME280::getImUpdateStatus() {
  return getStatus() & 0b00000001;
}

uint8_t BME280::getConfig() {
  return readU8(BME280_REGISTER_CONFIG);
}

uint8_t BME280::getStatus() {
  return readU8(BME280_REGISTER_STATUS);
}

uint8_t BME280::getControl() {
  return readU8(BME280_REGISTER_CONTROL);
}

uint8_t BME280::getControlHumidity() {
  return readU8(BME280_REGISTER_CONTROLHUMID);
}

uint8_t BME280::getChipId() {
  return readU8(BME280_REGISTER_CHIPID);
}

uint8_t BME280::getChipVersion() {
  return readU8(BME280_REGISTER_VERSION);
}

void BME280::setReset(uint8_t value) {
  write8(BME280_REGISTER_SOFTRESET, value);
}

void BME280::setConfig(uint8_t value) {
  write8(BME280_REGISTER_CONFIG, value);
}

void BME280::setStatus(uint8_t value) {
  write8(BME280_REGISTER_STATUS, value);
}

void BME280::setControl(uint8_t value) {
  write8(BME280_REGISTER_CONTROL, value);
}

void BME280::setControlHumidity(uint8_t value) {
  write8(BME280_REGISTER_CONTROLHUMID, value);
}

double BME280::getAltitude(double pressure) {
  return 44330.0 * (1.0 - pow(pressure / MEAN_SEA_LEVEL_PRESSURE, 0.190294957));
}

int32_t BME280::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 BME280::compensateTemperature(int32_t t_fine) {
  double T = (t_fine * 5 + 128) >> 8;
  return T / 100;
}

double BME280::compensatePressure(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;
}

double BME280::compensateHumidity(int32_t adc_H, int32_t t_fine) {
  int32_t v_x1_u32r;

  v_x1_u32r = (t_fine - ((int32_t) 76800));

  v_x1_u32r = (((((adc_H << 14) - (((int32_t) bmp280CalibrationData->getH4()) << 20) - (((int32_t) bmp280CalibrationData->getH5()) * v_x1_u32r)) + ((int32_t) 16384)) >> 15)
      * (((((((v_x1_u32r * ((int32_t) bmp280CalibrationData->getH6())) >> 10) * (((v_x1_u32r * ((int32_t) bmp280CalibrationData->getH3())) >> 11) + ((int32_t) 32768))) >> 10)
          + ((int32_t) 2097152)) * ((int32_t) bmp280CalibrationData->getH2()) + 8192) >> 14));

  v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t) bmp280CalibrationData->getH1())) >> 4));

  v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
  v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
  double h = (v_x1_u32r >> 12);
  return h / 1024.0;
}

BMP280Data * BME280::getBMP280Data() {
  int32_t t_fine;
  double t, p, h, a;
  while (getMeasuringStatus()) {
  }
  if (bmp280RawData) {
    delete bmp280RawData;
  }
  bmp280RawData = getRawData();
  t_fine = getTemperatureC(bmp280RawData->getTemperature());
  t = compensateTemperature(t_fine); // C
  p = compensatePressure(bmp280RawData->getPressure(), t_fine) / 100; // hPa
  h = compensateHumidity(bmp280RawData->getHumidity(), t_fine);
  a = getAltitude(p);                         // meters

  return new BMP280Data(p, t, h, a);
}

main.cpp

#include <stdio.h>
#include <string.h>
#include <stdexcept>
#include <iostream>
#include <stdint.h>
#include <time.h>
#include <math.h>
#include <wiringPiI2C.h>
#include <wiringPi.h>
#include "bme280.h"

int main() {
// char * device = "/dev/i2c-0";
// char * device = "/dev/i2c-1";
  char * device = "/dev/i2c-2";
// char * device = "/dev/i2c-3";
  int devId = BME280_I2C_ADDRESS1;
  try {
    BME280 * bme280 = new BME280(device, devId);
    int fd = bme280->init();
    bme280->reset();

    if (fd < 0) {
      printf("Device not found");
      return -1;
    }

    printf("fd       : 0x%02x\n", fd);
    printf("chip id  : 0x%02x\n", bme280->getChipId());
    printf("chip ver : 0x%02x\n", bme280->getChipVersion());

    bme280->reset();
    bme280->setPowerMode(BME280_NORMAL_MODE);
    bme280->setTemperatureOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE);
    bme280->setPressureOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE);
    bme280->setHumidityOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_HUMIDITY);
    bme280->setIrrFilter(BME280_FILTER_COEFF_16);
    bme280->setStandbyTime(BME280_STANDBY_TIME_250_MS);

    printf("---------------\n");
    printf("pw mode  : 0x%02x\n", bme280->getPowerMode());
    printf("osrs_p   : 0x%02x\n", bme280->getPressureOversampling());
    printf("osrs_t   : 0x%02x\n", bme280->getTemperatureOversampling());
    printf("osrs_h   : 0x%02x\n", bme280->getHumidityOversampling());
    printf("---------------\n");
    printf("filter   : 0x%02x\n", bme280->getIrrFilter());
    printf("t_sb     : 0x%02x\n", bme280->getStandbyTime());
    printf("---------------\n");
    printf("spi3w sts: 0x%02x\n", bme280->getSpi3w());
    printf("measuring: 0x%02x\n", bme280->getMeasuringStatus());
    printf("im_update: 0x%02x\n", bme280->getImUpdateStatus());
    printf("---------------\n");

    while (1) {
      delay(1000);
      BMP280Data * bme280Data = bme280->getBMP280Data();
      printf("pressure   : %.2f \tmm Hg\n", bme280Data->getPressure() / 1.3332239);
      printf("humidity   : %.2f \t%c\n", bme280Data->getHumidity(), '%');
      printf("temperature: %.2f \t°C\n", bme280Data->getTemperature());
      printf("altitude   : %.2f \tm\n\n", bme280Data->getAltitude());
    }
    delete bme280;
  } catch (std::exception & e) {
    printf("%s\n", e.what());
  }
  return 0;
}

Результат

Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry Pi
Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry Pi
Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry Pi
Подключение датчика окружающей среды BME280 к Orange Pi, Banana Pi, Raspberry Pi

Скачать проект CodeLite

CodeLite проект: BME280_Banana_Pi_M3.zip
Flyer: BST-BME280-FL000-02
Datasheet: BST-BME280-DS001-11
Handling, soldering & mounting instructions: BST-BME280-HS001-06
Shipment & packaging details: BST-BME280-SP000-00
Driver: BME280 driver

Купить BME280 на AliExpress

Похожие записи

Комментарии 170

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

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