|
@ -1,6 +1,5 @@ |
|
|
// ----------------------------------------------------------------------------- |
|
|
// ----------------------------------------------------------------------------- |
|
|
// BME280/BMP280 Sensor over I2C |
|
|
// BME280/BMP280 Sensor over I2C |
|
|
// Uses SparkFun BME280 library |
|
|
|
|
|
// Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com> |
|
|
// Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com> |
|
|
// ----------------------------------------------------------------------------- |
|
|
// ----------------------------------------------------------------------------- |
|
|
|
|
|
|
|
@ -10,10 +9,43 @@ |
|
|
|
|
|
|
|
|
#include "Arduino.h" |
|
|
#include "Arduino.h" |
|
|
#include "I2CSensor.h" |
|
|
#include "I2CSensor.h" |
|
|
#include <SparkFunBME280.h> |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_CHIP_BMP280 0x58 |
|
|
|
|
|
#define BMX280_CHIP_BME280 0x60 |
|
|
|
|
|
|
|
|
#define BMX280_CHIP_BMP280 0x58 |
|
|
|
|
|
#define BMX280_CHIP_BME280 0x60 |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_DIG_T1 0x88 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_T2 0x8A |
|
|
|
|
|
#define BMX280_REGISTER_DIG_T3 0x8C |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_DIG_P1 0x8E |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P2 0x90 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P3 0x92 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P4 0x94 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P5 0x96 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P6 0x98 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P7 0x9A |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P8 0x9C |
|
|
|
|
|
#define BMX280_REGISTER_DIG_P9 0x9E |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_DIG_H1 0xA1 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_H2 0xE1 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_H3 0xE3 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_H4 0xE4 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_H5 0xE5 |
|
|
|
|
|
#define BMX280_REGISTER_DIG_H6 0xE7 |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_CHIPID 0xD0 |
|
|
|
|
|
#define BMX280_REGISTER_VERSION 0xD1 |
|
|
|
|
|
#define BMX280_REGISTER_SOFTRESET 0xE0 |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_CAL26 0xE1 |
|
|
|
|
|
|
|
|
|
|
|
#define BMX280_REGISTER_CONTROLHUMID 0xF2 |
|
|
|
|
|
#define BMX280_REGISTER_CONTROL 0xF4 |
|
|
|
|
|
#define BMX280_REGISTER_CONFIG 0xF5 |
|
|
|
|
|
#define BMX280_REGISTER_PRESSUREDATA 0xF7 |
|
|
|
|
|
#define BMX280_REGISTER_TEMPDATA 0xFA |
|
|
|
|
|
#define BMX280_REGISTER_HUMIDDATA 0xFD |
|
|
|
|
|
|
|
|
class BMX280Sensor : public I2CSensor { |
|
|
class BMX280Sensor : public I2CSensor { |
|
|
|
|
|
|
|
@ -27,11 +59,6 @@ class BMX280Sensor : public I2CSensor { |
|
|
|
|
|
|
|
|
BMX280Sensor(): I2CSensor() { |
|
|
BMX280Sensor(): I2CSensor() { |
|
|
_sensor_id = SENSOR_BMX280_ID; |
|
|
_sensor_id = SENSOR_BMX280_ID; |
|
|
_bme = new BME280(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~BMX280Sensor() { |
|
|
|
|
|
delete _bme; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------- |
|
|
// --------------------------------------------------------------------- |
|
@ -91,8 +118,9 @@ class BMX280Sensor : public I2CSensor { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#if BMX280_MODE == 1 |
|
|
#if BMX280_MODE == 1 |
|
|
forceRead(); |
|
|
|
|
|
|
|
|
_forceRead(); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
_read(); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -103,19 +131,20 @@ class BMX280Sensor : public I2CSensor { |
|
|
_error = SENSOR_ERROR_OK; |
|
|
_error = SENSOR_ERROR_OK; |
|
|
unsigned char i = 0; |
|
|
unsigned char i = 0; |
|
|
#if BMX280_TEMPERATURE > 0 |
|
|
#if BMX280_TEMPERATURE > 0 |
|
|
if (index == i++) return _bme->readTempC(); |
|
|
|
|
|
|
|
|
if (index == i++) return _temperature; |
|
|
#endif |
|
|
#endif |
|
|
#if BMX280_PRESSURE > 0 |
|
|
#if BMX280_PRESSURE > 0 |
|
|
if (index == i++) return _bme->readFloatPressure() / 100; |
|
|
|
|
|
|
|
|
if (index == i++) return _pressure / 100; |
|
|
#endif |
|
|
#endif |
|
|
#if BMX280_HUMIDITY > 0 |
|
|
#if BMX280_HUMIDITY > 0 |
|
|
if (_chip == BMX280_CHIP_BME280) { |
|
|
if (_chip == BMX280_CHIP_BME280) { |
|
|
if (index == i) return _bme->readFloatHumidity(); |
|
|
|
|
|
|
|
|
if (index == i) return _humidity; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
_error = SENSOR_ERROR_OUT_OF_RANGE; |
|
|
_error = SENSOR_ERROR_OUT_OF_RANGE; |
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Load the configuration manifest |
|
|
// Load the configuration manifest |
|
@ -161,23 +190,11 @@ class BMX280Sensor : public I2CSensor { |
|
|
|
|
|
|
|
|
void _init() { |
|
|
void _init() { |
|
|
|
|
|
|
|
|
_bme->settings.commInterface = I2C_MODE; |
|
|
|
|
|
_bme->settings.I2CAddress = _address; |
|
|
|
|
|
_bme->settings.runMode = BMX280_MODE; |
|
|
|
|
|
_bme->settings.tStandby = 0; |
|
|
|
|
|
_bme->settings.filter = 0; |
|
|
|
|
|
_bme->settings.tempOverSample = BMX280_TEMPERATURE; |
|
|
|
|
|
_bme->settings.pressOverSample = BMX280_PRESSURE; |
|
|
|
|
|
_bme->settings.humidOverSample = BMX280_HUMIDITY; |
|
|
|
|
|
|
|
|
|
|
|
// Fix when not measuring temperature, t_fine should have a sensible value |
|
|
|
|
|
if (BMX280_TEMPERATURE == 0) _bme->t_fine = 100000; // aprox 20ºC |
|
|
|
|
|
|
|
|
|
|
|
// Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up |
|
|
// Make sure sensor had enough time to turn on. BMX280 requires 2ms to start up |
|
|
delay(10); |
|
|
delay(10); |
|
|
|
|
|
|
|
|
// Check sensor correctly initialized |
|
|
// Check sensor correctly initialized |
|
|
_chip = _bme->begin(); |
|
|
|
|
|
|
|
|
_chip = i2c_read_uint8(_address, BMX280_REGISTER_CHIPID); |
|
|
if ((_chip != BMX280_CHIP_BME280) && (_chip != BMX280_CHIP_BMP280)) { |
|
|
if ((_chip != BMX280_CHIP_BME280) && (_chip != BMX280_CHIP_BMP280)) { |
|
|
_chip = 0; |
|
|
_chip = 0; |
|
|
i2cReleaseLock(_address); |
|
|
i2cReleaseLock(_address); |
|
@ -194,11 +211,51 @@ class BMX280Sensor : public I2CSensor { |
|
|
if (_chip == BMX280_CHIP_BME280) ++_count; |
|
|
if (_chip == BMX280_CHIP_BME280) ++_count; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
_measurement_delay = measurementTime(); |
|
|
|
|
|
|
|
|
_readCoefficients(); |
|
|
|
|
|
|
|
|
|
|
|
unsigned char data = 0; |
|
|
|
|
|
i2c_write_uint8(_address, BMX280_REGISTER_CONTROL, data); |
|
|
|
|
|
|
|
|
|
|
|
data = (BMX280_STANDBY << 0x5) & 0xE0; |
|
|
|
|
|
data |= (BMX280_FILTER << 0x02) & 0x1C; |
|
|
|
|
|
i2c_write_uint8(_address, BMX280_REGISTER_CONFIG, data); |
|
|
|
|
|
|
|
|
|
|
|
data = (BMX280_HUMIDITY) & 0x07; |
|
|
|
|
|
i2c_write_uint8(_address, BMX280_REGISTER_CONTROLHUMID, data); |
|
|
|
|
|
|
|
|
|
|
|
data = (BMX280_TEMPERATURE << 5) & 0xE0; |
|
|
|
|
|
data |= (BMX280_PRESSURE << 2) & 0x1C; |
|
|
|
|
|
data |= (BMX280_MODE) & 0x03; |
|
|
|
|
|
i2c_write_uint8(_address, BMX280_REGISTER_CONTROL, data); |
|
|
|
|
|
|
|
|
|
|
|
_measurement_delay = _measurementTime(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void _readCoefficients() { |
|
|
|
|
|
_bmx280_calib.dig_T1 = i2c_read_uint16_le(_address, BMX280_REGISTER_DIG_T1); |
|
|
|
|
|
_bmx280_calib.dig_T2 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_T2); |
|
|
|
|
|
_bmx280_calib.dig_T3 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_T3); |
|
|
|
|
|
|
|
|
|
|
|
_bmx280_calib.dig_P1 = i2c_read_uint16_le(_address, BMX280_REGISTER_DIG_P1); |
|
|
|
|
|
_bmx280_calib.dig_P2 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P2); |
|
|
|
|
|
_bmx280_calib.dig_P3 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P3); |
|
|
|
|
|
_bmx280_calib.dig_P4 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P4); |
|
|
|
|
|
_bmx280_calib.dig_P5 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P5); |
|
|
|
|
|
_bmx280_calib.dig_P6 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P6); |
|
|
|
|
|
_bmx280_calib.dig_P7 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P7); |
|
|
|
|
|
_bmx280_calib.dig_P8 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P8); |
|
|
|
|
|
_bmx280_calib.dig_P9 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_P9); |
|
|
|
|
|
|
|
|
|
|
|
_bmx280_calib.dig_H1 = i2c_read_uint8(_address, BMX280_REGISTER_DIG_H1); |
|
|
|
|
|
_bmx280_calib.dig_H2 = i2c_read_int16_le(_address, BMX280_REGISTER_DIG_H2); |
|
|
|
|
|
_bmx280_calib.dig_H3 = i2c_read_uint8(_address, BMX280_REGISTER_DIG_H3); |
|
|
|
|
|
_bmx280_calib.dig_H4 = (i2c_read_uint8(_address, BMX280_REGISTER_DIG_H4) << 4) | (i2c_read_uint8(_address, BMX280_REGISTER_DIG_H4+1) & 0xF); |
|
|
|
|
|
_bmx280_calib.dig_H5 = (i2c_read_uint8(_address, BMX280_REGISTER_DIG_H5+1) << 4) | (i2c_read_uint8(_address, BMX280_REGISTER_DIG_H5) >> 4); |
|
|
|
|
|
_bmx280_calib.dig_H6 = (int8_t) i2c_read_uint8(_address, BMX280_REGISTER_DIG_H6); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
unsigned long measurementTime() { |
|
|
|
|
|
|
|
|
unsigned long _measurementTime() { |
|
|
|
|
|
|
|
|
// Measurement Time (as per BMX280 datasheet section 9.1) |
|
|
// Measurement Time (as per BMX280 datasheet section 9.1) |
|
|
// T_max(ms) = 1.25 |
|
|
// T_max(ms) = 1.25 |
|
@ -224,23 +281,135 @@ class BMX280Sensor : public I2CSensor { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void forceRead() { |
|
|
|
|
|
|
|
|
void _forceRead() { |
|
|
|
|
|
|
|
|
// We set the sensor in "forced mode" to force a reading. |
|
|
// We set the sensor in "forced mode" to force a reading. |
|
|
// After the reading the sensor will go back to sleep mode. |
|
|
// After the reading the sensor will go back to sleep mode. |
|
|
uint8_t value = _bme->readRegister(BME280_CTRL_MEAS_REG); |
|
|
|
|
|
|
|
|
uint8_t value = i2c_read_uint8(_address, BMX280_REGISTER_CONTROL); |
|
|
value = (value & 0xFC) + 0x01; |
|
|
value = (value & 0xFC) + 0x01; |
|
|
_bme->writeRegister(BME280_CTRL_MEAS_REG, value); |
|
|
|
|
|
|
|
|
i2c_write_uint8(_address, BMX280_REGISTER_CONTROL, value); |
|
|
|
|
|
|
|
|
delay(_measurement_delay); |
|
|
delay(_measurement_delay); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void _read() { |
|
|
|
|
|
|
|
|
|
|
|
#if BMX280_TEMPERATURE > 0 |
|
|
|
|
|
int32_t adc_T = i2c_read_uint16(_address, BMX280_REGISTER_TEMPDATA); |
|
|
|
|
|
adc_T <<= 8; |
|
|
|
|
|
adc_T |= i2c_read_uint8(_address, BMX280_REGISTER_TEMPDATA+2); |
|
|
|
|
|
adc_T >>= 4; |
|
|
|
|
|
|
|
|
|
|
|
int32_t var1t = ((((adc_T>>3) - |
|
|
|
|
|
((int32_t)_bmx280_calib.dig_T1 <<1))) * |
|
|
|
|
|
((int32_t)_bmx280_calib.dig_T2)) >> 11; |
|
|
|
|
|
|
|
|
|
|
|
int32_t var2t = (((((adc_T>>4) - |
|
|
|
|
|
((int32_t)_bmx280_calib.dig_T1)) * |
|
|
|
|
|
((adc_T>>4) - ((int32_t)_bmx280_calib.dig_T1))) >> 12) * |
|
|
|
|
|
((int32_t)_bmx280_calib.dig_T3)) >> 14; |
|
|
|
|
|
|
|
|
|
|
|
int32_t t_fine = var1t + var2t; |
|
|
|
|
|
|
|
|
|
|
|
double T = (t_fine * 5 + 128) >> 8; |
|
|
|
|
|
_temperature = T / 100; |
|
|
|
|
|
#else |
|
|
|
|
|
int32_t t_fine = 102374; // ~20ºC |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
#if BMX280_PRESSURE > 0 |
|
|
|
|
|
int64_t var1, var2, p; |
|
|
|
|
|
|
|
|
|
|
|
int32_t adc_P = i2c_read_uint16(_address, BMX280_REGISTER_PRESSUREDATA); |
|
|
|
|
|
adc_P <<= 8; |
|
|
|
|
|
adc_P |= i2c_read_uint8(_address, BMX280_REGISTER_PRESSUREDATA+2); |
|
|
|
|
|
adc_P >>= 4; |
|
|
|
|
|
|
|
|
|
|
|
var1 = ((int64_t)t_fine) - 128000; |
|
|
|
|
|
var2 = var1 * var1 * (int64_t)_bmx280_calib.dig_P6; |
|
|
|
|
|
var2 = var2 + ((var1*(int64_t)_bmx280_calib.dig_P5)<<17); |
|
|
|
|
|
var2 = var2 + (((int64_t)_bmx280_calib.dig_P4)<<35); |
|
|
|
|
|
var1 = ((var1 * var1 * (int64_t)_bmx280_calib.dig_P3)>>8) + |
|
|
|
|
|
((var1 * (int64_t)_bmx280_calib.dig_P2)<<12); |
|
|
|
|
|
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bmx280_calib.dig_P1)>>33; |
|
|
|
|
|
if (var1 == 0) return; // avoid exception caused by division by zero |
|
|
|
|
|
|
|
|
|
|
|
p = 1048576 - adc_P; |
|
|
|
|
|
p = (((p<<31) - var2)*3125) / var1; |
|
|
|
|
|
var1 = (((int64_t)_bmx280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25; |
|
|
|
|
|
var2 = (((int64_t)_bmx280_calib.dig_P8) * p) >> 19; |
|
|
|
|
|
|
|
|
|
|
|
p = ((p + var1 + var2) >> 8) + (((int64_t)_bmx280_calib.dig_P7)<<4); |
|
|
|
|
|
_pressure = (double) p / 256; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
#if BMX280_HUMIDITY > 0 |
|
|
|
|
|
if (_chip == BMX280_CHIP_BME280) { |
|
|
|
|
|
|
|
|
|
|
|
int32_t adc_H = i2c_read_uint16(_address, BMX280_REGISTER_HUMIDDATA); |
|
|
|
|
|
|
|
|
|
|
|
int32_t v_x1_u32r; |
|
|
|
|
|
|
|
|
|
|
|
v_x1_u32r = (t_fine - ((int32_t)76800)); |
|
|
|
|
|
|
|
|
|
|
|
v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bmx280_calib.dig_H4) << 20) - |
|
|
|
|
|
(((int32_t)_bmx280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * |
|
|
|
|
|
(((((((v_x1_u32r * ((int32_t)_bmx280_calib.dig_H6)) >> 10) * |
|
|
|
|
|
(((v_x1_u32r * ((int32_t)_bmx280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + |
|
|
|
|
|
((int32_t)2097152)) * ((int32_t)_bmx280_calib.dig_H2) + 8192) >> 14)); |
|
|
|
|
|
|
|
|
|
|
|
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * |
|
|
|
|
|
((int32_t)_bmx280_calib.dig_H1)) >> 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); |
|
|
|
|
|
_humidity = h / 1024.0; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------- |
|
|
// --------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
BME280 * _bme = NULL; |
|
|
|
|
|
unsigned char _chip; |
|
|
unsigned char _chip; |
|
|
unsigned long _measurement_delay; |
|
|
unsigned long _measurement_delay; |
|
|
|
|
|
double _temperature = 0; |
|
|
|
|
|
double _pressure = 0; |
|
|
|
|
|
double _humidity = 0; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
|
|
|
|
|
|
|
uint16_t dig_T1; |
|
|
|
|
|
int16_t dig_T2; |
|
|
|
|
|
int16_t dig_T3; |
|
|
|
|
|
|
|
|
|
|
|
uint16_t dig_P1; |
|
|
|
|
|
int16_t dig_P2; |
|
|
|
|
|
int16_t dig_P3; |
|
|
|
|
|
int16_t dig_P4; |
|
|
|
|
|
int16_t dig_P5; |
|
|
|
|
|
int16_t dig_P6; |
|
|
|
|
|
int16_t dig_P7; |
|
|
|
|
|
int16_t dig_P8; |
|
|
|
|
|
int16_t dig_P9; |
|
|
|
|
|
|
|
|
|
|
|
uint8_t dig_H1; |
|
|
|
|
|
int16_t dig_H2; |
|
|
|
|
|
uint8_t dig_H3; |
|
|
|
|
|
int16_t dig_H4; |
|
|
|
|
|
int16_t dig_H5; |
|
|
|
|
|
int8_t dig_H6; |
|
|
|
|
|
|
|
|
|
|
|
} bmx280_calib_t; |
|
|
|
|
|
|
|
|
|
|
|
bmx280_calib_t _bmx280_calib; |
|
|
|
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|