Merge branch 'master' of https://github.com/mozzbozz/Adafruit_BME280_Library into mozzbozz-master

This commit is contained in:
ladyada 2017-02-06 18:38:02 -05:00
commit 54b1c5125c
3 changed files with 621 additions and 291 deletions

View File

@ -19,180 +19,238 @@
#include <SPI.h> #include <SPI.h>
#include "Adafruit_BME280.h" #include "Adafruit_BME280.h"
/*************************************************************************** /***************************************************************************
PRIVATE FUNCTIONS PRIVATE FUNCTIONS
***************************************************************************/ ***************************************************************************/
Adafruit_BME280::Adafruit_BME280() Adafruit_BME280::Adafruit_BME280()
: _cs(-1), _mosi(-1), _miso(-1), _sck(-1) : _cs(-1), _mosi(-1), _miso(-1), _sck(-1)
{ } { }
Adafruit_BME280::Adafruit_BME280(int8_t cspin) Adafruit_BME280::Adafruit_BME280(int8_t cspin)
: _cs(cspin), _mosi(-1), _miso(-1), _sck(-1) : _cs(cspin), _mosi(-1), _miso(-1), _sck(-1)
{ } { }
Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin) Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin)
: _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin)
{ } { }
bool Adafruit_BME280::begin(uint8_t a) { /**************************************************************************/
_i2caddr = a; /*!
@brief Initialise sensor with given parameters / settings
*/
/**************************************************************************/
bool Adafruit_BME280::begin(uint8_t addr,
sensor_mode mode,
sensor_sampling tempSampling,
sensor_sampling pressSampling,
sensor_sampling humSampling,
sensor_filter filter,
standby_duration duration
)
{
_i2caddr = addr;
if (_cs == -1) { // init I2C or SPI sensor interface
// i2c if (_cs == -1) {
Wire.begin(); // I2C
} else { Wire.begin();
digitalWrite(_cs, HIGH);
pinMode(_cs, OUTPUT);
if (_sck == -1) {
// hardware SPI
SPI.begin();
} else { } else {
// software SPI digitalWrite(_cs, HIGH);
pinMode(_sck, OUTPUT); pinMode(_cs, OUTPUT);
pinMode(_mosi, OUTPUT); if (_sck == -1) {
pinMode(_miso, INPUT); // hardware SPI
SPI.begin();
} else {
// software SPI
pinMode(_sck, OUTPUT);
pinMode(_mosi, OUTPUT);
pinMode(_miso, INPUT);
}
} }
}
if (read8(BME280_REGISTER_CHIPID) != 0x60) // check if sensor, i.e. the chip ID is correct
return false; if (read8(BME280_REGISTER_CHIPID) != 0x60)
return false;
readCoefficients(); readCoefficients(); // read trimming parameters, see DS 4.2.2
_measReg.mode = mode;
_measReg.osrs_t = tempSampling;
_measReg.osrs_p = pressSampling;
_humReg.osrs_h = humSampling;
_configReg.filter = filter;
_configReg.t_sb = duration;
//Set before CONTROL_meas (DS 5.4.3)
write8(BME280_REGISTER_CONTROLHUMID, 0x05); //16x oversampling // you must make sure to also set REGISTER_CONTROL after setting the
// CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3)
write8(BME280_REGISTER_CONTROLHUMID, _humReg.get());
write8(BME280_REGISTER_CONFIG, _configReg.get());
write8(BME280_REGISTER_CONTROL, _measReg.get());
write8(BME280_REGISTER_CONTROL, 0xB7); // 16x ovesampling, normal mode return true;
return true;
} }
/**************************************************************************/
/*!
@brief Initialise sensor with given parameters / settings
This is simply a overload to the normal begin()-function, so SPI users
don't get confused about the library requiring an address.
*/
/**************************************************************************/
bool Adafruit_BME280::begin(sensor_mode mode,
sensor_sampling tempSampling,
sensor_sampling pressSampling,
sensor_sampling humSampling,
sensor_filter filter,
standby_duration duration
)
{
return begin(BME280_ADDRESS, mode, tempSampling, pressSampling, humSampling, filter, duration);
}
/**************************************************************************/
/*!
@brief Encapsulate hardware and software SPI transfer into one function
*/
/**************************************************************************/
uint8_t Adafruit_BME280::spixfer(uint8_t x) { uint8_t Adafruit_BME280::spixfer(uint8_t x) {
if (_sck == -1) // hardware SPI
return SPI.transfer(x); if (_sck == -1)
return SPI.transfer(x);
// software spi // software SPI
//Serial.println("Software SPI"); uint8_t reply = 0;
uint8_t reply = 0; for (int i=7; i>=0; i--) {
for (int i=7; i>=0; i--) { reply <<= 1;
reply <<= 1; digitalWrite(_sck, LOW);
digitalWrite(_sck, LOW); digitalWrite(_mosi, x & (1<<i));
digitalWrite(_mosi, x & (1<<i)); digitalWrite(_sck, HIGH);
digitalWrite(_sck, HIGH); if (digitalRead(_miso))
if (digitalRead(_miso)) reply |= 1;
reply |= 1; }
} return reply;
return reply;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Writes an 8 bit value over I2C/SPI @brief Writes an 8 bit value over I2C or SPI
*/ */
/**************************************************************************/ /**************************************************************************/
void Adafruit_BME280::write8(byte reg, byte value) void Adafruit_BME280::write8(byte reg, byte value) {
{ if (_cs == -1) {
if (_cs == -1) { Wire.beginTransmission((uint8_t)_i2caddr);
Wire.beginTransmission((uint8_t)_i2caddr); Wire.write((uint8_t)reg);
Wire.write((uint8_t)reg); Wire.write((uint8_t)value);
Wire.write((uint8_t)value); Wire.endTransmission();
Wire.endTransmission(); } else {
} else { if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW);
spixfer(reg & ~0x80); // write, bit 7 low
spixfer(value);
digitalWrite(_cs, HIGH);
if (_sck == -1) if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); SPI.endTransaction(); // release the SPI bus
digitalWrite(_cs, LOW); }
spixfer(reg & ~0x80); // write, bit 7 low
spixfer(value);
digitalWrite(_cs, HIGH);
if (_sck == -1)
SPI.endTransaction(); // release the SPI bus
}
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Reads an 8 bit value over I2C @brief Reads an 8 bit value over I2C or SPI
*/ */
/**************************************************************************/ /**************************************************************************/
uint8_t Adafruit_BME280::read8(byte reg) uint8_t Adafruit_BME280::read8(byte reg) {
{ uint8_t value;
uint8_t value;
if (_cs == -1) {
if (_cs == -1) { Wire.beginTransmission((uint8_t)_i2caddr);
Wire.beginTransmission((uint8_t)_i2caddr); Wire.write((uint8_t)reg);
Wire.write((uint8_t)reg); Wire.endTransmission();
Wire.endTransmission(); Wire.requestFrom((uint8_t)_i2caddr, (byte)1);
Wire.requestFrom((uint8_t)_i2caddr, (byte)1); value = Wire.read();
value = Wire.read(); } else {
if (_sck == -1)
} else { SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
if (_sck == -1) digitalWrite(_cs, LOW);
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); spixfer(reg | 0x80); // read, bit 7 high
digitalWrite(_cs, LOW); value = spixfer(0);
spixfer(reg | 0x80); // read, bit 7 high digitalWrite(_cs, HIGH);
value = spixfer(0); if (_sck == -1)
digitalWrite(_cs, HIGH); SPI.endTransaction(); // release the SPI bus
if (_sck == -1) }
SPI.endTransaction(); // release the SPI bus return value;
}
return value;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Reads a 16 bit value over I2C @brief Reads a 16 bit value over I2C or SPI
*/ */
/**************************************************************************/ /**************************************************************************/
uint16_t Adafruit_BME280::read16(byte reg) uint16_t Adafruit_BME280::read16(byte reg)
{ {
uint16_t value; uint16_t value;
if (_cs == -1) { if (_cs == -1) {
Wire.beginTransmission((uint8_t)_i2caddr); Wire.beginTransmission((uint8_t)_i2caddr);
Wire.write((uint8_t)reg); Wire.write((uint8_t)reg);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom((uint8_t)_i2caddr, (byte)2); Wire.requestFrom((uint8_t)_i2caddr, (byte)2);
value = (Wire.read() << 8) | Wire.read(); value = (Wire.read() << 8) | Wire.read();
} else {
if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW);
spixfer(reg | 0x80); // read, bit 7 high
value = (spixfer(0) << 8) | spixfer(0);
digitalWrite(_cs, HIGH);
if (_sck == -1)
SPI.endTransaction(); // release the SPI bus
}
} else { return value;
if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW);
spixfer(reg | 0x80); // read, bit 7 high
value = (spixfer(0) << 8) | spixfer(0);
digitalWrite(_cs, HIGH);
if (_sck == -1)
SPI.endTransaction(); // release the SPI bus
}
return value;
} }
uint16_t Adafruit_BME280::read16_LE(byte reg) {
uint16_t temp = read16(reg);
return (temp >> 8) | (temp << 8);
}
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Reads a signed 16 bit value over I2C
*/
/**************************************************************************/
uint16_t Adafruit_BME280::read16_LE(byte reg) {
uint16_t temp = read16(reg);
return (temp >> 8) | (temp << 8);
}
/**************************************************************************/
/*!
@brief Reads a signed 16 bit value over I2C or SPI
*/ */
/**************************************************************************/ /**************************************************************************/
int16_t Adafruit_BME280::readS16(byte reg) int16_t Adafruit_BME280::readS16(byte reg)
{ {
return (int16_t)read16(reg); return (int16_t)read16(reg);
} }
/**************************************************************************/
/*!
*/
/**************************************************************************/
int16_t Adafruit_BME280::readS16_LE(byte reg) int16_t Adafruit_BME280::readS16_LE(byte reg)
{ {
return (int16_t)read16_LE(reg); return (int16_t)read16_LE(reg);
} }
@ -201,41 +259,60 @@ int16_t Adafruit_BME280::readS16_LE(byte reg)
@brief Reads a 24 bit value over I2C @brief Reads a 24 bit value over I2C
*/ */
/**************************************************************************/ /**************************************************************************/
uint32_t Adafruit_BME280::read24(byte reg) uint32_t Adafruit_BME280::read24(byte reg)
{ {
uint32_t value; uint32_t value;
if (_cs == -1) { if (_cs == -1) {
Wire.beginTransmission((uint8_t)_i2caddr); Wire.beginTransmission((uint8_t)_i2caddr);
Wire.write((uint8_t)reg); Wire.write((uint8_t)reg);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom((uint8_t)_i2caddr, (byte)3); Wire.requestFrom((uint8_t)_i2caddr, (byte)3);
value = Wire.read();
value <<= 8;
value |= Wire.read();
value <<= 8;
value |= Wire.read();
} else { value = Wire.read();
if (_sck == -1) value <<= 8;
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); value |= Wire.read();
digitalWrite(_cs, LOW); value <<= 8;
spixfer(reg | 0x80); // read, bit 7 high value |= Wire.read();
} else {
value = spixfer(0); if (_sck == -1)
value <<= 8; SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
value |= spixfer(0); digitalWrite(_cs, LOW);
value <<= 8; spixfer(reg | 0x80); // read, bit 7 high
value |= spixfer(0);
digitalWrite(_cs, HIGH); value = spixfer(0);
if (_sck == -1) value <<= 8;
SPI.endTransaction(); // release the SPI bus value |= spixfer(0);
} value <<= 8;
value |= spixfer(0);
return value; digitalWrite(_cs, HIGH);
if (_sck == -1)
SPI.endTransaction(); // release the SPI bus
}
return value;
}
/**************************************************************************/
/*!
@brief Take a new measurement (only possible in forced mode)
*/
/**************************************************************************/
void Adafruit_BME280::takeForcedMeasurement()
{
// If we are in forced mode, the BME sensor goes back to sleep after each
// measurement and we need to set it to forced mode once at this point, so
// it will take the next measurement and then return to sleep again.
// In normal mode simply does new measurements periodically.
if (_measReg.mode == MODE_FORCED) {
// set to forced mode, i.e. "take next measurement"
write8(BME280_REGISTER_CONTROL, _measReg.get());
// wait until measurement has been completed, otherwise we would read
// the values from the last measurement
while (read8(BME280_REGISTER_STATUS) & 0x08);
}
} }
@ -268,95 +345,103 @@ void Adafruit_BME280::readCoefficients(void)
_bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6);
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Returns the temperature from the sensor
*/ */
/**************************************************************************/ /**************************************************************************/
float Adafruit_BME280::readTemperature(void) float Adafruit_BME280::readTemperature(void)
{ {
int32_t var1, var2; int32_t var1, var2;
int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
adc_T >>= 4; if (adc_T == 0x800000) // value in case temp measurement was disabled
return NAN;
adc_T >>= 4;
var1 = ((((adc_T>>3) - ((int32_t)_bme280_calib.dig_T1 <<1))) * var1 = ((((adc_T>>3) - ((int32_t)_bme280_calib.dig_T1 <<1))) *
((int32_t)_bme280_calib.dig_T2)) >> 11; ((int32_t)_bme280_calib.dig_T2)) >> 11;
var2 = (((((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1)) *
((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1))) >> 12) *
((int32_t)_bme280_calib.dig_T3)) >> 14;
var2 = (((((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1)) * t_fine = var1 + var2;
((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1))) >> 12) *
((int32_t)_bme280_calib.dig_T3)) >> 14;
t_fine = var1 + var2; float T = (t_fine * 5 + 128) >> 8;
return T/100;
float T = (t_fine * 5 + 128) >> 8;
return T/100;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Returns the temperature from the sensor
*/ */
/**************************************************************************/ /**************************************************************************/
float Adafruit_BME280::readPressure(void) { float Adafruit_BME280::readPressure(void) {
int64_t var1, var2, p; int64_t var1, var2, p;
readTemperature(); // must be done first to get t_fine readTemperature(); // must be done first to get t_fine
int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);
adc_P >>= 4; if (adc_P == 0x800000) // value in case pressure measurement was disabled
return NAN;
adc_P >>= 4;
var1 = ((int64_t)t_fine) - 128000; var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6;
var2 = var2 + ((var1*(int64_t)_bme280_calib.dig_P5)<<17); var2 = var2 + ((var1*(int64_t)_bme280_calib.dig_P5)<<17);
var2 = var2 + (((int64_t)_bme280_calib.dig_P4)<<35); var2 = var2 + (((int64_t)_bme280_calib.dig_P4)<<35);
var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3)>>8) + var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3)>>8) +
((var1 * (int64_t)_bme280_calib.dig_P2)<<12); ((var1 * (int64_t)_bme280_calib.dig_P2)<<12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bme280_calib.dig_P1)>>33; var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bme280_calib.dig_P1)>>33;
if (var1 == 0) { if (var1 == 0) {
return 0; // avoid exception caused by division by zero return 0; // avoid exception caused by division by zero
} }
p = 1048576 - adc_P; p = 1048576 - adc_P;
p = (((p<<31) - var2)*3125) / var1; p = (((p<<31) - var2)*3125) / var1;
var1 = (((int64_t)_bme280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25; var1 = (((int64_t)_bme280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25;
var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7)<<4); p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7)<<4);
return (float)p/256; return (float)p/256;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Returns the humidity from the sensor
*/ */
/**************************************************************************/ /**************************************************************************/
float Adafruit_BME280::readHumidity(void) { float Adafruit_BME280::readHumidity(void) {
readTemperature(); // must be done first to get t_fine
readTemperature(); // must be done first to get t_fine int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
if (adc_H == 0x8000) // value in case humidity measurement was disabled
return NAN;
int32_t v_x1_u32r;
int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); v_x1_u32r = (t_fine - ((int32_t)76800));
int32_t v_x1_u32r; v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) -
(((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
(((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) *
(((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
((int32_t)2097152)) * ((int32_t)_bme280_calib.dig_H2) + 8192) >> 14));
v_x1_u32r = (t_fine - ((int32_t)76800)); v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
((int32_t)_bme280_calib.dig_H1)) >> 4));
v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
(((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
(((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * float h = (v_x1_u32r>>12);
(((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + return h / 1024.0;
((int32_t)2097152)) * ((int32_t)_bme280_calib.dig_H2) + 8192) >> 14));
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
((int32_t)_bme280_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;
float h = (v_x1_u32r>>12);
return h / 1024.0;
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
Calculates the altitude (in meters) from the specified atmospheric Calculates the altitude (in meters) from the specified atmospheric
@ -368,17 +453,18 @@ float Adafruit_BME280::readHumidity(void) {
/**************************************************************************/ /**************************************************************************/
float Adafruit_BME280::readAltitude(float seaLevel) float Adafruit_BME280::readAltitude(float seaLevel)
{ {
// Equation taken from BMP180 datasheet (page 16): // Equation taken from BMP180 datasheet (page 16):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
// Note that using the equation from wikipedia can give bad results // Note that using the equation from wikipedia can give bad results
// at high altitude. See this thread for more information: // at high altitude. See this thread for more information:
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064 // http://forums.adafruit.com/viewtopic.php?f=22&t=58064
float atmospheric = readPressure() / 100.0F; float atmospheric = readPressure() / 100.0F;
return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
} }
/**************************************************************************/ /**************************************************************************/
/*! /*!
Calculates the pressure at sea level (in hPa) from the specified altitude Calculates the pressure at sea level (in hPa) from the specified altitude
@ -389,12 +475,12 @@ float Adafruit_BME280::readAltitude(float seaLevel)
/**************************************************************************/ /**************************************************************************/
float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric)
{ {
// Equation taken from BMP180 datasheet (page 17): // Equation taken from BMP180 datasheet (page 17):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
// Note that using the equation from wikipedia can give bad results // Note that using the equation from wikipedia can give bad results
// at high altitude. See this thread for more information: // at high altitude. See this thread for more information:
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064 // http://forums.adafruit.com/viewtopic.php?f=22&t=58064
return atmospheric / pow(1.0 - (altitude/44330.0), 5.255); return atmospheric / pow(1.0 - (altitude/44330.0), 5.255);
} }

View File

@ -37,39 +37,40 @@
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
enum enum
{ {
BME280_REGISTER_DIG_T1 = 0x88, BME280_REGISTER_DIG_T1 = 0x88,
BME280_REGISTER_DIG_T2 = 0x8A, BME280_REGISTER_DIG_T2 = 0x8A,
BME280_REGISTER_DIG_T3 = 0x8C, BME280_REGISTER_DIG_T3 = 0x8C,
BME280_REGISTER_DIG_P1 = 0x8E, BME280_REGISTER_DIG_P1 = 0x8E,
BME280_REGISTER_DIG_P2 = 0x90, BME280_REGISTER_DIG_P2 = 0x90,
BME280_REGISTER_DIG_P3 = 0x92, BME280_REGISTER_DIG_P3 = 0x92,
BME280_REGISTER_DIG_P4 = 0x94, BME280_REGISTER_DIG_P4 = 0x94,
BME280_REGISTER_DIG_P5 = 0x96, BME280_REGISTER_DIG_P5 = 0x96,
BME280_REGISTER_DIG_P6 = 0x98, BME280_REGISTER_DIG_P6 = 0x98,
BME280_REGISTER_DIG_P7 = 0x9A, BME280_REGISTER_DIG_P7 = 0x9A,
BME280_REGISTER_DIG_P8 = 0x9C, BME280_REGISTER_DIG_P8 = 0x9C,
BME280_REGISTER_DIG_P9 = 0x9E, BME280_REGISTER_DIG_P9 = 0x9E,
BME280_REGISTER_DIG_H1 = 0xA1, BME280_REGISTER_DIG_H1 = 0xA1,
BME280_REGISTER_DIG_H2 = 0xE1, BME280_REGISTER_DIG_H2 = 0xE1,
BME280_REGISTER_DIG_H3 = 0xE3, BME280_REGISTER_DIG_H3 = 0xE3,
BME280_REGISTER_DIG_H4 = 0xE4, BME280_REGISTER_DIG_H4 = 0xE4,
BME280_REGISTER_DIG_H5 = 0xE5, BME280_REGISTER_DIG_H5 = 0xE5,
BME280_REGISTER_DIG_H6 = 0xE7, BME280_REGISTER_DIG_H6 = 0xE7,
BME280_REGISTER_CHIPID = 0xD0, BME280_REGISTER_CHIPID = 0xD0,
BME280_REGISTER_VERSION = 0xD1, BME280_REGISTER_VERSION = 0xD1,
BME280_REGISTER_SOFTRESET = 0xE0, BME280_REGISTER_SOFTRESET = 0xE0,
BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0
BME280_REGISTER_CONTROLHUMID = 0xF2, BME280_REGISTER_CONTROLHUMID = 0xF2,
BME280_REGISTER_CONTROL = 0xF4, BME280_REGISTER_STATUS = 0XF3,
BME280_REGISTER_CONFIG = 0xF5, BME280_REGISTER_CONTROL = 0xF4,
BME280_REGISTER_PRESSUREDATA = 0xF7, BME280_REGISTER_CONFIG = 0xF5,
BME280_REGISTER_TEMPDATA = 0xFA, BME280_REGISTER_PRESSUREDATA = 0xF7,
BME280_REGISTER_HUMIDDATA = 0xFD, BME280_REGISTER_TEMPDATA = 0xFA,
BME280_REGISTER_HUMIDDATA = 0xFD
}; };
/*=========================================================================*/ /*=========================================================================*/
@ -79,26 +80,26 @@
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
typedef struct typedef struct
{ {
uint16_t dig_T1; uint16_t dig_T1;
int16_t dig_T2; int16_t dig_T2;
int16_t dig_T3; int16_t dig_T3;
uint16_t dig_P1; uint16_t dig_P1;
int16_t dig_P2; int16_t dig_P2;
int16_t dig_P3; int16_t dig_P3;
int16_t dig_P4; int16_t dig_P4;
int16_t dig_P5; int16_t dig_P5;
int16_t dig_P6; int16_t dig_P6;
int16_t dig_P7; int16_t dig_P7;
int16_t dig_P8; int16_t dig_P8;
int16_t dig_P9; int16_t dig_P9;
uint8_t dig_H1; uint8_t dig_H1;
int16_t dig_H2; int16_t dig_H2;
uint8_t dig_H3; uint8_t dig_H3;
int16_t dig_H4; int16_t dig_H4;
int16_t dig_H5; int16_t dig_H5;
int8_t dig_H6; int8_t dig_H6;
} bme280_calib_data; } bme280_calib_data;
/*=========================================================================*/ /*=========================================================================*/
@ -123,41 +124,179 @@ class Adafruit_BME280_Unified : public Adafruit_Sensor
*/ */
class Adafruit_BME280 class Adafruit_BME280 {
{ public:
public: enum sensor_sampling {
Adafruit_BME280(void); SAMPLING_NONE = 0b000,
Adafruit_BME280(int8_t cspin); SAMPLING_X1 = 0b001,
Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); SAMPLING_X2 = 0b010,
SAMPLING_X4 = 0b011,
SAMPLING_X8 = 0b100,
SAMPLING_X16 = 0b101
};
bool begin(uint8_t addr = BME280_ADDRESS); enum sensor_mode {
float readTemperature(void); MODE_SLEEP = 0b00,
float readPressure(void); MODE_FORCED = 0b01,
float readHumidity(void); MODE_NORMAL = 0b11
float readAltitude(float seaLevel); };
float seaLevelForAltitude(float altitude, float atmospheric);
private: enum sensor_filter {
FILTER_OFF = 0b000,
FILTER_X2 = 0b001,
FILTER_X4 = 0b010,
FILTER_X8 = 0b011,
FILTER_X16 = 0b100
};
void readCoefficients(void); // standby durations in ms
uint8_t spixfer(uint8_t x); enum standby_duration {
STANDBY_MS_0_5 = 0b000,
STANDBY_MS_10 = 0b110,
STANDBY_MS_20 = 0b111,
STANDBY_MS_62_5 = 0b001,
STANDBY_MS_125 = 0b010,
STANDBY_MS_250 = 0b011,
STANDBY_MS_500 = 0b100,
STANDBY_MS_1000 = 0b101
};
// constructors
Adafruit_BME280(void);
Adafruit_BME280(int8_t cspin);
Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin);
bool begin(uint8_t addr = BME280_ADDRESS,
sensor_mode mode = MODE_NORMAL,
sensor_sampling tempSampling = SAMPLING_X16,
sensor_sampling pressSampling = SAMPLING_X16,
sensor_sampling humSampling = SAMPLING_X16,
sensor_filter filter = FILTER_OFF,
standby_duration duration = STANDBY_MS_0_5
);
// overload function without address (-> for SPI users)
bool begin(sensor_mode mode = MODE_NORMAL,
sensor_sampling tempSampling = SAMPLING_X16,
sensor_sampling pressSampling = SAMPLING_X16,
sensor_sampling humSampling = SAMPLING_X16,
sensor_filter filter = FILTER_OFF,
standby_duration duration = STANDBY_MS_0_5
);
void takeForcedMeasurement();
float readTemperature(void);
float readPressure(void);
float readHumidity(void);
float readAltitude(float seaLevel);
float seaLevelForAltitude(float altitude, float pressure);
void write8(byte reg, byte value);
uint8_t read8(byte reg); private:
uint16_t read16(byte reg); void readCoefficients(void);
uint32_t read24(byte reg); uint8_t spixfer(uint8_t x);
int16_t readS16(byte reg);
uint16_t read16_LE(byte reg); // little endian
int16_t readS16_LE(byte reg); // little endian
uint8_t _i2caddr; void write8(byte reg, byte value);
int32_t _sensorID; uint8_t read8(byte reg);
int32_t t_fine; uint16_t read16(byte reg);
uint32_t read24(byte reg);
int16_t readS16(byte reg);
uint16_t read16_LE(byte reg); // little endian
int16_t readS16_LE(byte reg); // little endian
int8_t _cs, _mosi, _miso, _sck; uint8_t _i2caddr;
int32_t _sensorID;
int32_t t_fine;
bme280_calib_data _bme280_calib; int8_t _cs, _mosi, _miso, _sck;
bme280_calib_data _bme280_calib;
// The config register
struct config {
// inactive duration (standby time) in normal mode
// 000 = 0.5 ms
// 001 = 62.5 ms
// 010 = 125 ms
// 011 = 250 ms
// 100 = 500 ms
// 101 = 1000 ms
// 110 = 10 ms
// 111 = 20 ms
unsigned int t_sb : 3;
// filter settings
// 000 = filter off
// 001 = 2x filter
// 010 = 4x filter
// 011 = 8x filter
// 100 and above = 16x filter
unsigned int filter : 3;
// unused - don't set
unsigned int none : 1;
unsigned int spi3w_en : 1;
unsigned int get() {
return (t_sb << 5) | (filter << 3) | spi3w_en;
}
};
config _configReg;
// The ctrl_meas register
struct ctrl_meas {
// temperature oversampling
// 000 = skipped
// 001 = x1
// 010 = x2
// 011 = x4
// 100 = x8
// 101 and above = x16
unsigned int osrs_t : 3;
// pressure oversampling
// 000 = skipped
// 001 = x1
// 010 = x2
// 011 = x4
// 100 = x8
// 101 and above = x16
unsigned int osrs_p : 3;
// device mode
// 00 = sleep
// 01 or 10 = forced
// 11 = normal
unsigned int mode : 2;
unsigned int get() {
return (osrs_t << 5) | (osrs_p << 3) | mode;
}
};
ctrl_meas _measReg;
// The ctrl_hum register
struct ctrl_hum {
// unused - don't set
unsigned int none : 5;
// pressure oversampling
// 000 = skipped
// 001 = x1
// 010 = x2
// 011 = x4
// 100 = x8
// 101 and above = x16
unsigned int osrs_h : 3;
unsigned int get() {
return (osrs_h);
}
};
ctrl_hum _humReg;
}; };
#endif #endif

View File

@ -5,7 +5,7 @@
----> http://www.adafruit.com/products/2650 ----> http://www.adafruit.com/products/2650
These sensors use I2C or SPI to communicate, 2 or 4 pins are required These sensors use I2C or SPI to communicate, 2 or 4 pins are required
to interface. to interface. The device's I2C address is either 0x76 or 0x77.
Adafruit invests time and resources providing this open source code, Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products please support Adafruit andopen-source hardware by purchasing products
@ -29,19 +29,125 @@
Adafruit_BME280 bme; // I2C Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI //Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
unsigned long delayTime;
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
Serial.println(F("BME280 test")); Serial.println(F("BME280 test"));
if (!bme.begin()) { bool status;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1); // default settings
} status = bme.begin();
Serial.println("-- Default Test --");
Serial.println("normal mode, 16x oversampling for all, filter off,");
Serial.println("0.5ms standby period");
delayTime = 5000;
// For more details on the following scenarious, see chapter
// 3.5 "Recommended modes of operation" in the datasheet
/*
// weather monitoring
Serial.println("-- Weather Station Scenario --");
Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
Serial.println("filter off");
status = bme.begin(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_X1, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_OFF
);
// suggested rate is 1/60Hz (1m)
delayTime = 60e3;
*/
/*
// humidity sensing
Serial.println("-- Humidity Sensing Scenario --");
Serial.println("forced mode, 1x temperature / 1x humidity / 0x pressure oversampling");
Serial.println("= pressure off, filter off");
status = bme.begin(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_NONE, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_OFF
);
// suggested rate is 1Hz (1s)
delayTime = 1e3;
*/
/*
// indoor navigation
Serial.println("-- Indoor Navigation Scenario --");
Serial.println("normal mode, 16x pressure / 2x temperature / 1x humidity oversampling,");
Serial.println("0.5ms standby period, filter 16x");
status = bme.begin(Adafruit_BME280::MODE_NORMAL,
Adafruit_BME280::SAMPLING_X2, // temperature
Adafruit_BME280::SAMPLING_X16, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_X16,
Adafruit_BME280::STANDBY_MS_0_5
);
// suggested rate is 25Hz
// 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) + (2 * H_ovs + 0.5)
// T_ovs = 2
// P_ovs = 16
// H_ovs = 1
// = 40ms (25Hz)
// with standby time that should really be 24.16913... Hz
delayTime = 41;
*/
/*
// gaming
Serial.println("-- Gaming Scenario --");
Serial.println("normal mode, 4x pressure / 1x temperature / 0x humidity oversampling,");
Serial.println("= humidity off, 0.5ms standby period, filter 16x");
status = bme.begin(Adafruit_BME280::MODE_NORMAL,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_X4, // pressure
Adafruit_BME280::SAMPLING_NONE, // humidity
Adafruit_BME280::FILTER_X16,
Adafruit_BME280::STANDBY_MS_0_5
);
// Suggested rate is 83Hz
// 1 + (2 * T_ovs) + (2 * P_ovs + 0.5)
// T_ovs = 1
// P_ovs = 4
// = 11.5ms + 0.5ms standby
delayTime = 12;
*/
Serial.println();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
} }
void loop() { void loop() {
// Only needed in forced mode! In normal mode, you can remove the next line.
bme.takeForcedMeasurement(); // has no effect in normal mode
printValues();
delay(delayTime);
}
void printValues() {
Serial.print("Temperature = "); Serial.print("Temperature = ");
Serial.print(bme.readTemperature()); Serial.print(bme.readTemperature());
Serial.println(" *C"); Serial.println(" *C");
@ -60,5 +166,4 @@ void loop() {
Serial.println(" %"); Serial.println(" %");
Serial.println(); Serial.println();
delay(2000);
} }