From 7e39c445f040ae059e5b2e2911466ee420ea7a3c Mon Sep 17 00:00:00 2001 From: Jan Hoffmann Date: Thu, 20 Jun 2019 18:26:48 +0200 Subject: [PATCH] added spi fixes --- Adafruit_BME280.cpp | 931 ++++++++++++++++++++------------------------ Adafruit_BME280.h | 534 ++++++++++++------------- 2 files changed, 687 insertions(+), 778 deletions(-) diff --git a/Adafruit_BME280.cpp b/Adafruit_BME280.cpp index cb06850..7b89736 100644 --- a/Adafruit_BME280.cpp +++ b/Adafruit_BME280.cpp @@ -6,15 +6,15 @@ * @section intro_sec Introduction * * Driver for the BME280 humidity, temperature & pressure sensor - * + * * These sensors use I2C or SPI to communicate, 2 or 4 pins are required * to interface. * * Designed specifically to work with the Adafruit BME280 Breakout * ----> http://www.adafruit.com/products/2652 - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * * @section author Author @@ -28,606 +28,533 @@ * */ -#include "Arduino.h" -#include -#include #include "Adafruit_BME280.h" +#include "Arduino.h" +#include +#include -/**************************************************************************/ -/*! - @brief class constructor -*/ -/**************************************************************************/ -Adafruit_BME280::Adafruit_BME280() - : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) -{ } - -/**************************************************************************/ -/*! - @brief class constructor if using hardware SPI - @param cspin the chip select pin to use -*/ -/**************************************************************************/ -Adafruit_BME280::Adafruit_BME280(int8_t cspin) - : _cs(cspin), _mosi(-1), _miso(-1), _sck(-1) -{ } - -/**************************************************************************/ -/*! - @brief class constructor if using software SPI - @param cspin the chip select pin to use - @param mosipin the MOSI pin to use - @param misopin the MISO pin to use - @param sckpin the SCK pin to use -*/ -/**************************************************************************/ -Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin) - : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) -{ } - - -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings - @param theWire the I2C object to use - @returns true on success, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::begin(TwoWire *theWire) -{ - _wire = theWire; - _i2caddr = BME280_ADDRESS; - return init(); + * @brief class constructor + */ +Adafruit_BME280::Adafruit_BME280() : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) {} + +/*! + * @brief class constructor if using hardware SPI + * @param cspin the chip select pin to use + * @param *theSPI + * optional SPI object + */ +Adafruit_BME280::Adafruit_BME280(int8_t cspin, SPIClass *theSPI) { + _cs = cspin; + _mosi = _miso = _sck = -1; + _spi = theSPI; } -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings - @param addr the I2C address the device can be found on - @returns true on success, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::begin(uint8_t addr) -{ - _i2caddr = addr; - _wire = &Wire; - return init(); + * @brief class constructor if using software SPI + * @param cspin the chip select pin to use + * @param mosipin the MOSI pin to use + * @param misopin the MISO pin to use + * @param sckpin the SCK pin to use + */ +Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, + int8_t sckpin) + : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) {} + +/*! + * @brief Initialise sensor with given parameters / settings + * @param theWire the I2C object to use + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(TwoWire *theWire) { + _wire = theWire; + _i2caddr = BME280_ADDRESS; + return init(); } -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings - @param addr the I2C address the device can be found on - @param theWire the I2C object to use - @returns true on success, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) -{ - _i2caddr = addr; - _wire = theWire; - return init(); + * @brief Initialise sensor with given parameters / settings + * @param addr the I2C address the device can be found on + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(uint8_t addr) { + _i2caddr = addr; + _wire = &Wire; + return init(); } -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings - @returns true on success, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::begin(void) -{ - bool status = false; - _i2caddr = BME280_ADDRESS; - _wire = &Wire; - status = init(); - if(!status){ - _i2caddr = BME280_ADDRESS_ALTERNATE; - status = init(); - } - return status; + * @brief Initialise sensor with given parameters / settings + * @param addr the I2C address the device can be found on + * @param theWire the I2C object to use + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) { + _i2caddr = addr; + _wire = theWire; + return init(); } -/**************************************************************************/ /*! - @brief Initialise sensor with given parameters / settings - @returns true on success, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::init() -{ - // init I2C or SPI sensor interface - if (_cs == -1) { - // I2C - _wire -> begin(); + * @brief Initialise sensor with given parameters / settings + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::begin(void) { + bool status = false; + _i2caddr = BME280_ADDRESS; + _wire = &Wire; + status = init(); + if (!status) { + _i2caddr = BME280_ADDRESS_ALTERNATE; + status = init(); + } + return status; +} + +/*! + * @brief Initialise sensor with given parameters / settings + * @returns true on success, false otherwise + */ +bool Adafruit_BME280::init() { + // init I2C or SPI sensor interface + if (_cs == -1) { + // I2C + _wire->begin(); + } else { + digitalWrite(_cs, HIGH); + pinMode(_cs, OUTPUT); + if (_sck == -1) { + // hardware SPI + _spi->begin(); } else { - digitalWrite(_cs, HIGH); - pinMode(_cs, OUTPUT); - if (_sck == -1) { - // hardware SPI - SPI.begin(); - } else { - // software SPI - pinMode(_sck, OUTPUT); - pinMode(_mosi, OUTPUT); - pinMode(_miso, INPUT); - } + // software SPI + pinMode(_sck, OUTPUT); + pinMode(_mosi, OUTPUT); + pinMode(_miso, INPUT); } + } - // check if sensor, i.e. the chip ID is correct - _sensorID = read8(BME280_REGISTER_CHIPID); - if (_sensorID != 0x60) - return false; + // check if sensor, i.e. the chip ID is correct + _sensorID = read8(BME280_REGISTER_CHIPID); + if (_sensorID != 0x60) + return false; - // reset the device using soft-reset - // this makes sure the IIR is off, etc. - write8(BME280_REGISTER_SOFTRESET, 0xB6); + // reset the device using soft-reset + // this makes sure the IIR is off, etc. + write8(BME280_REGISTER_SOFTRESET, 0xB6); - // wait for chip to wake up. - delay(300); - - // if chip is still reading calibration, delay - while (isReadingCalibration()) - delay(100); - - readCoefficients(); // read trimming parameters, see DS 4.2.2 - - setSampling(); // use defaults + // wait for chip to wake up. + delay(300); + // if chip is still reading calibration, delay + while (isReadingCalibration()) delay(100); - return true; + readCoefficients(); // read trimming parameters, see DS 4.2.2 + + setSampling(); // use defaults + + delay(100); + + return true; } -/**************************************************************************/ /*! - @brief setup 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. - @param mode the power mode to use for the sensor - @param tempSampling the temp samping rate to use - @param pressSampling the pressure sampling rate to use - @param humSampling the humidity sampling rate to use - @param filter the filter mode to use - @param duration the standby duration to use -*/ -/**************************************************************************/ -void Adafruit_BME280::setSampling(sensor_mode mode, - sensor_sampling tempSampling, - sensor_sampling pressSampling, - sensor_sampling humSampling, - sensor_filter filter, - standby_duration duration) { - _measReg.mode = mode; - _measReg.osrs_t = tempSampling; - _measReg.osrs_p = pressSampling; - - - _humReg.osrs_h = humSampling; - _configReg.filter = filter; - _configReg.t_sb = duration; + * @brief setup 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. + * @param mode the power mode to use for the sensor + * @param tempSampling the temp samping rate to use + * @param pressSampling the pressure sampling rate to use + * @param humSampling the humidity sampling rate to use + * @param filter the filter mode to use + * @param duration the standby duration to use + */ +void Adafruit_BME280::setSampling(sensor_mode mode, + sensor_sampling tempSampling, + sensor_sampling pressSampling, + sensor_sampling humSampling, + sensor_filter filter, + standby_duration duration) { + _measReg.mode = mode; + _measReg.osrs_t = tempSampling; + _measReg.osrs_p = pressSampling; - - // 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()); + _humReg.osrs_h = humSampling; + _configReg.filter = filter; + _configReg.t_sb = duration; + + // 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()); } - -/**************************************************************************/ /*! - @brief Encapsulate hardware and software SPI transfer into one function - @param x the data byte to transfer - @returns the data byte read from the device -*/ -/**************************************************************************/ + * @brief Encapsulate hardware and software SPI transfer into one + * function + * @param x the data byte to transfer + * @returns the data byte read from the device + */ uint8_t Adafruit_BME280::spixfer(uint8_t x) { - // hardware SPI - if (_sck == -1) - return SPI.transfer(x); + // hardware SPI + if (_sck == -1) + return _spi->transfer(x); - // software SPI - uint8_t reply = 0; - for (int i=7; i>=0; i--) { - reply <<= 1; - digitalWrite(_sck, LOW); - digitalWrite(_mosi, x & (1<= 0; i--) { + reply <<= 1; + digitalWrite(_sck, LOW); + digitalWrite(_mosi, x & (1 << i)); + digitalWrite(_sck, HIGH); + if (digitalRead(_miso)) + reply |= 1; + } + return reply; } - -/**************************************************************************/ /*! - @brief Writes an 8 bit value over I2C or SPI - @param reg the register address to write to - @param value the value to write to the register -*/ -/**************************************************************************/ + * @brief Writes an 8 bit value over I2C or SPI + * @param reg the register address to write to + * @param value the value to write to the register + */ void Adafruit_BME280::write8(byte reg, byte value) { - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> write((uint8_t)value); - _wire -> endTransmission(); - } 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 (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->write((uint8_t)value); + _wire->endTransmission(); + } else { if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } + _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) + _spi->endTransaction(); // release the SPI bus + } } - -/**************************************************************************/ /*! - @brief Reads an 8 bit value over I2C or SPI - @param reg the register address to read from - @returns the data byte read from the device -*/ -/**************************************************************************/ + * @brief Reads an 8 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the data byte read from the device + */ uint8_t Adafruit_BME280::read8(byte reg) { - uint8_t value; - - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)1); - value = _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); - digitalWrite(_cs, HIGH); - if (_sck == -1) - SPI.endTransaction(); // release the SPI bus - } - return value; + uint8_t value; + + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)1); + value = _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); + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } + return value; } - -/**************************************************************************/ /*! - @brief Reads a 16 bit value over I2C or SPI - @param reg the register address to read from - @returns the 16 bit data value read from the device -*/ -/**************************************************************************/ -uint16_t Adafruit_BME280::read16(byte reg) -{ - uint16_t value; + * @brief Reads a 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +uint16_t Adafruit_BME280::read16(byte reg) { + uint16_t value; - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)2); - 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 - } + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)2); + 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 + } - return value; + return value; } - -/**************************************************************************/ /*! - @brief Reads a signed 16 bit little endian value over I2C or SPI - @param reg the register address to read from - @returns the 16 bit data value read from the device -*/ -/**************************************************************************/ + * @brief Reads a signed 16 bit little endian value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ uint16_t Adafruit_BME280::read16_LE(byte reg) { - uint16_t temp = read16(reg); - return (temp >> 8) | (temp << 8); + uint16_t temp = read16(reg); + return (temp >> 8) | (temp << 8); } - -/**************************************************************************/ /*! - @brief Reads a signed 16 bit value over I2C or SPI - @param reg the register address to read from - @returns the 16 bit data value read from the device -*/ -/**************************************************************************/ -int16_t Adafruit_BME280::readS16(byte reg) -{ - return (int16_t)read16(reg); + * @brief Reads a signed 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); } + +/*! + * @brief Reads a signed little endian 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16_LE(byte reg) { + return (int16_t)read16_LE(reg); } - -/**************************************************************************/ /*! - @brief Reads a signed little endian 16 bit value over I2C or SPI - @param reg the register address to read from - @returns the 16 bit data value read from the device -*/ -/**************************************************************************/ -int16_t Adafruit_BME280::readS16_LE(byte reg) -{ - return (int16_t)read16_LE(reg); + * @brief Reads a 24 bit value over I2C + * @param reg the register address to read from + * @returns the 24 bit data value read from the device + */ +uint32_t Adafruit_BME280::read24(byte reg) { + uint32_t value; + + if (_cs == -1) { + _wire->beginTransmission((uint8_t)_i2caddr); + _wire->write((uint8_t)reg); + _wire->endTransmission(); + _wire->requestFrom((uint8_t)_i2caddr, (byte)3); + + value = _wire->read(); + value <<= 8; + value |= _wire->read(); + value <<= 8; + value |= _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); + value <<= 8; + value |= spixfer(0); + value <<= 8; + value |= spixfer(0); + + digitalWrite(_cs, HIGH); + if (_sck == -1) + _spi->endTransaction(); // release the SPI bus + } + + return value; } - -/**************************************************************************/ /*! - @brief Reads a 24 bit value over I2C - @param reg the register address to read from - @returns the 24 bit data value read from the device -*/ -/**************************************************************************/ -uint32_t Adafruit_BME280::read24(byte reg) -{ - uint32_t value; - - if (_cs == -1) { - _wire -> beginTransmission((uint8_t)_i2caddr); - _wire -> write((uint8_t)reg); - _wire -> endTransmission(); - _wire -> requestFrom((uint8_t)_i2caddr, (byte)3); - - value = _wire -> read(); - value <<= 8; - value |= _wire -> read(); - value <<= 8; - value |= _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); - value <<= 8; - value |= spixfer(0); - value <<= 8; - value |= spixfer(0); - - 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) + delay(1); + } } - -/**************************************************************************/ /*! - @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) - delay(1); - } + * @brief Reads the factory-set coefficients + */ +void Adafruit_BME280::readCoefficients(void) { + _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); + _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); + _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); + + _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); + _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); + _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); + _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); + _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); + _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); + _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); + _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); + _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); + + _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); + _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); + _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); + _bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) | + (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); + _bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5 + 1) << 4) | + (read8(BME280_REGISTER_DIG_H5) >> 4); + _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); } - -/**************************************************************************/ /*! - @brief Reads the factory-set coefficients -*/ -/**************************************************************************/ -void Adafruit_BME280::readCoefficients(void) -{ - _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); - _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); - _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); - - _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); - _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); - _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); - _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); - _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); - _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); - _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); - _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); - _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); - - _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); - _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); - _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); - _bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4+1) & 0xF); - _bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5+1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4); - _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); -} - -/**************************************************************************/ -/*! - @brief return true if chip is busy reading cal data - @returns true if reading calibration, false otherwise -*/ -/**************************************************************************/ -bool Adafruit_BME280::isReadingCalibration(void) -{ + * @brief return true if chip is busy reading cal data + * @returns true if reading calibration, false otherwise + */ +bool Adafruit_BME280::isReadingCalibration(void) { uint8_t const rStatus = read8(BME280_REGISTER_STATUS); return (rStatus & (1 << 0)) != 0; } - -/**************************************************************************/ /*! - @brief Returns the temperature from the sensor - @returns the temperature read from the device -*/ -/**************************************************************************/ -float Adafruit_BME280::readTemperature(void) -{ - int32_t var1, var2; + * @brief Returns the temperature from the sensor + * @returns the temperature read from the device + */ +float Adafruit_BME280::readTemperature(void) { + int32_t var1, var2; - int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); - if (adc_T == 0x800000) // value in case temp measurement was disabled - return NAN; - adc_T >>= 4; + int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); + 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))) * - ((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; + var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib.dig_T1 << 1))) * + ((int32_t)_bme280_calib.dig_T2)) >> + 11; - t_fine = var1 + var2; + 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; - float T = (t_fine * 5 + 128) >> 8; - return T/100; + t_fine = var1 + var2; + + float T = (t_fine * 5 + 128) >> 8; + return T / 100; } - -/**************************************************************************/ /*! - @brief Returns the pressure from the sensor - @returns the pressure value (in Pascal) read from the device -*/ -/**************************************************************************/ + * @brief Returns the pressure from the sensor + * @returns the pressure value (in Pascal) read from the device + */ 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); - if (adc_P == 0x800000) // value in case pressure measurement was disabled - return NAN; - adc_P >>= 4; + int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); + if (adc_P == 0x800000) // value in case pressure measurement was disabled + return NAN; + adc_P >>= 4; - var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; - var2 = var2 + ((var1*(int64_t)_bme280_calib.dig_P5)<<17); - var2 = var2 + (((int64_t)_bme280_calib.dig_P4)<<35); - var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3)>>8) + - ((var1 * (int64_t)_bme280_calib.dig_P2)<<12); - var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bme280_calib.dig_P1)>>33; + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; + var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) << 17); + var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) + + ((var1 * (int64_t)_bme280_calib.dig_P2) << 12); + var1 = + (((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 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)_bme280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25; - var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; + 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)_bme280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7)<<4); - return (float)p/256; + p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7) << 4); + return (float)p / 256; } - -/**************************************************************************/ /*! - @brief Returns the humidity from the sensor - @returns the humidity value read from the device -*/ -/**************************************************************************/ + * @brief Returns the humidity from the sensor + * @returns the humidity value read from the device + */ 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); + if (adc_H == 0x8000) // value in case humidity measurement was disabled + return NAN; - 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) - + (((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 = (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; + 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 - pressure (in hPa), and sea-level pressure (in hPa). + * Calculates the altitude (in meters) from the specified atmospheric + * pressure (in hPa), and sea-level pressure (in hPa). + * @param seaLevel Sea-level pressure in hPa + * @returns the altitude value read from the device + */ +float Adafruit_BME280::readAltitude(float seaLevel) { + // Equation taken from BMP180 datasheet (page 16): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf - @param seaLevel Sea-level pressure in hPa - @returns the altitude value read from the device -*/ -/**************************************************************************/ -float Adafruit_BME280::readAltitude(float seaLevel) -{ - // Equation taken from BMP180 datasheet (page 16): - // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 - // Note that using the equation from wikipedia can give bad results - // at high altitude. See this thread for more information: - // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 - - float atmospheric = readPressure() / 100.0F; - return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); + float atmospheric = readPressure() / 100.0F; + return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); } - -/**************************************************************************/ /*! - Calculates the pressure at sea level (in hPa) from the specified altitude - (in meters), and atmospheric pressure (in hPa). - @param altitude Altitude in meters - @param atmospheric Atmospheric pressure in hPa - @returns the pressure at sea level (in hPa) from the specified altitude -*/ -/**************************************************************************/ -float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) -{ - // Equation taken from BMP180 datasheet (page 17): - // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + * Calculates the pressure at sea level (in hPa) from the specified + * altitude (in meters), and atmospheric pressure (in hPa). + * @param altitude Altitude in meters + * @param atmospheric Atmospheric pressure in hPa + * @returns the pressure at sea level (in hPa) from the specified altitude + */ +float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) { + // Equation taken from BMP180 datasheet (page 17): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf - // Note that using the equation from wikipedia can give bad results - // at high altitude. See this thread for more information: - // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // 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); } - -/**************************************************************************/ + /*! - Returns Sensor ID found by init() for diagnostics - @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 -*/ -/**************************************************************************/ -uint32_t Adafruit_BME280::sensorID(void) -{ - return _sensorID; -} + * Returns Sensor ID found by init() for diagnostics + * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 + */ +uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; } diff --git a/Adafruit_BME280.h b/Adafruit_BME280.h index 5113c4a..0309f1a 100644 --- a/Adafruit_BME280.h +++ b/Adafruit_BME280.h @@ -3,12 +3,12 @@ * * Designed specifically to work with the Adafruit BME280 Breakout * ----> http://www.adafruit.com/products/2650 - * + * * These sensors use I2C or SPI to communicate, 2 or 4 pins are required * to interface. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * * Written by Kevin "KTOWN" Townsend for Adafruit Industries. @@ -21,100 +21,88 @@ #ifndef __BME280_H__ #define __BME280_H__ -#if (ARDUINO >= 100) - #include "Arduino.h" -#else - #include "WProgram.h" -#endif +#include "Arduino.h" #include +#include #include -/**************************************************************************/ -/*! - @brief default I2C address -*/ -/**************************************************************************/ - #define BME280_ADDRESS (0x77) // Primary I2C Address -/**************************************************************************/ -/*! - @brief alternate I2C address -*/ -/**************************************************************************/ - #define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address -/*=========================================================================*/ +/*! + * @brief default I2C address + */ +#define BME280_ADDRESS (0x77) // Primary I2C Address + /*! + * @brief alternate I2C address + */ +#define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address + +/*! + * @brief Register addresses + */ +enum { + BME280_REGISTER_DIG_T1 = 0x88, + BME280_REGISTER_DIG_T2 = 0x8A, + BME280_REGISTER_DIG_T3 = 0x8C, + + BME280_REGISTER_DIG_P1 = 0x8E, + BME280_REGISTER_DIG_P2 = 0x90, + BME280_REGISTER_DIG_P3 = 0x92, + BME280_REGISTER_DIG_P4 = 0x94, + BME280_REGISTER_DIG_P5 = 0x96, + BME280_REGISTER_DIG_P6 = 0x98, + BME280_REGISTER_DIG_P7 = 0x9A, + BME280_REGISTER_DIG_P8 = 0x9C, + BME280_REGISTER_DIG_P9 = 0x9E, + + BME280_REGISTER_DIG_H1 = 0xA1, + BME280_REGISTER_DIG_H2 = 0xE1, + BME280_REGISTER_DIG_H3 = 0xE3, + BME280_REGISTER_DIG_H4 = 0xE4, + BME280_REGISTER_DIG_H5 = 0xE5, + BME280_REGISTER_DIG_H6 = 0xE7, + + BME280_REGISTER_CHIPID = 0xD0, + BME280_REGISTER_VERSION = 0xD1, + BME280_REGISTER_SOFTRESET = 0xE0, + + BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 + + BME280_REGISTER_CONTROLHUMID = 0xF2, + BME280_REGISTER_STATUS = 0XF3, + BME280_REGISTER_CONTROL = 0xF4, + BME280_REGISTER_CONFIG = 0xF5, + BME280_REGISTER_PRESSUREDATA = 0xF7, + BME280_REGISTER_TEMPDATA = 0xFA, + BME280_REGISTER_HUMIDDATA = 0xFD +}; /**************************************************************************/ -/*! - @brief Register addresses -*/ -/**************************************************************************/ - enum - { - BME280_REGISTER_DIG_T1 = 0x88, - BME280_REGISTER_DIG_T2 = 0x8A, - BME280_REGISTER_DIG_T3 = 0x8C, - - BME280_REGISTER_DIG_P1 = 0x8E, - BME280_REGISTER_DIG_P2 = 0x90, - BME280_REGISTER_DIG_P3 = 0x92, - BME280_REGISTER_DIG_P4 = 0x94, - BME280_REGISTER_DIG_P5 = 0x96, - BME280_REGISTER_DIG_P6 = 0x98, - BME280_REGISTER_DIG_P7 = 0x9A, - BME280_REGISTER_DIG_P8 = 0x9C, - BME280_REGISTER_DIG_P9 = 0x9E, - - BME280_REGISTER_DIG_H1 = 0xA1, - BME280_REGISTER_DIG_H2 = 0xE1, - BME280_REGISTER_DIG_H3 = 0xE3, - BME280_REGISTER_DIG_H4 = 0xE4, - BME280_REGISTER_DIG_H5 = 0xE5, - BME280_REGISTER_DIG_H6 = 0xE7, - - BME280_REGISTER_CHIPID = 0xD0, - BME280_REGISTER_VERSION = 0xD1, - BME280_REGISTER_SOFTRESET = 0xE0, - - BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 - - BME280_REGISTER_CONTROLHUMID = 0xF2, - BME280_REGISTER_STATUS = 0XF3, - BME280_REGISTER_CONTROL = 0xF4, - BME280_REGISTER_CONFIG = 0xF5, - BME280_REGISTER_PRESSUREDATA = 0xF7, - BME280_REGISTER_TEMPDATA = 0xFA, - BME280_REGISTER_HUMIDDATA = 0xFD - }; - -/**************************************************************************/ -/*! +/*! @brief calibration data */ /**************************************************************************/ - typedef struct - { - uint16_t dig_T1; ///< temperature compensation value - int16_t dig_T2; ///< temperature compensation value - int16_t dig_T3; ///< temperature compensation value +typedef struct { + uint16_t dig_T1; ///< temperature compensation value + int16_t dig_T2; ///< temperature compensation value + int16_t dig_T3; ///< temperature compensation value - uint16_t dig_P1; ///< pressure compensation value - int16_t dig_P2; ///< pressure compensation value - int16_t dig_P3; ///< pressure compensation value - int16_t dig_P4; ///< pressure compensation value - int16_t dig_P5; ///< pressure compensation value - int16_t dig_P6; ///< pressure compensation value - int16_t dig_P7; ///< pressure compensation value - int16_t dig_P8; ///< pressure compensation value - int16_t dig_P9; ///< pressure compensation value + uint16_t dig_P1; ///< pressure compensation value + int16_t dig_P2; ///< pressure compensation value + int16_t dig_P3; ///< pressure compensation value + int16_t dig_P4; ///< pressure compensation value + int16_t dig_P5; ///< pressure compensation value + int16_t dig_P6; ///< pressure compensation value + int16_t dig_P7; ///< pressure compensation value + int16_t dig_P8; ///< pressure compensation value + int16_t dig_P9; ///< pressure compensation value - uint8_t dig_H1; ///< humidity compensation value - int16_t dig_H2; ///< humidity compensation value - uint8_t dig_H3; ///< humidity compensation value - int16_t dig_H4; ///< humidity compensation value - int16_t dig_H5; ///< humidity compensation value - int8_t dig_H6; ///< humidity compensation value - } bme280_calib_data; + uint8_t dig_H1; ///< humidity compensation value + int16_t dig_H2; ///< humidity compensation value + uint8_t dig_H3; ///< humidity compensation value + int16_t dig_H4; ///< humidity compensation value + int16_t dig_H5; ///< humidity compensation value + int8_t dig_H6; ///< humidity compensation value +} bme280_calib_data; /*=========================================================================*/ /* @@ -139,219 +127,213 @@ class Adafruit_BME280_Unified : public Adafruit_Sensor */ /**************************************************************************/ -/*! +/*! @brief Class that stores state and functions for interacting with BME280 IC */ /**************************************************************************/ class Adafruit_BME280 { - public: - /**************************************************************************/ - /*! - @brief sampling rates - */ - /**************************************************************************/ - enum sensor_sampling { - SAMPLING_NONE = 0b000, - SAMPLING_X1 = 0b001, - SAMPLING_X2 = 0b010, - SAMPLING_X4 = 0b011, - SAMPLING_X8 = 0b100, - SAMPLING_X16 = 0b101 - }; +public: + /**************************************************************************/ + /*! + @brief sampling rates + */ + /**************************************************************************/ + enum sensor_sampling { + SAMPLING_NONE = 0b000, + SAMPLING_X1 = 0b001, + SAMPLING_X2 = 0b010, + SAMPLING_X4 = 0b011, + SAMPLING_X8 = 0b100, + SAMPLING_X16 = 0b101 + }; - /**************************************************************************/ - /*! - @brief power modes - */ - /**************************************************************************/ - enum sensor_mode { - MODE_SLEEP = 0b00, - MODE_FORCED = 0b01, - MODE_NORMAL = 0b11 - }; + /**************************************************************************/ + /*! + @brief power modes + */ + /**************************************************************************/ + enum sensor_mode { + MODE_SLEEP = 0b00, + MODE_FORCED = 0b01, + MODE_NORMAL = 0b11 + }; - /**************************************************************************/ - /*! - @brief filter values - */ - /**************************************************************************/ - enum sensor_filter { - FILTER_OFF = 0b000, - FILTER_X2 = 0b001, - FILTER_X4 = 0b010, - FILTER_X8 = 0b011, - FILTER_X16 = 0b100 - }; + /**************************************************************************/ + /*! + @brief filter values + */ + /**************************************************************************/ + enum sensor_filter { + FILTER_OFF = 0b000, + FILTER_X2 = 0b001, + FILTER_X4 = 0b010, + FILTER_X8 = 0b011, + FILTER_X16 = 0b100 + }; - /**************************************************************************/ - /*! - @brief standby duration in ms - */ - /**************************************************************************/ - 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(void); - bool begin(TwoWire *theWire); - bool begin(uint8_t addr); - bool begin(uint8_t addr, TwoWire *theWire); - bool init(); + /**************************************************************************/ + /*! + @brief standby duration in ms + */ + /**************************************************************************/ + 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 + }; - void setSampling(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); - uint32_t sensorID(void); - - protected: - TwoWire *_wire; //!< pointer to a TwoWire object - void readCoefficients(void); - bool isReadingCalibration(void); - uint8_t spixfer(uint8_t x); + // constructors + Adafruit_BME280(); + Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI) + Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, + int8_t sckpin); - void write8(byte reg, byte value); - uint8_t read8(byte reg); - 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 + bool begin(); + bool begin(TwoWire *theWire); + bool begin(uint8_t addr); + bool begin(uint8_t addr, TwoWire *theWire); + bool init(); - uint8_t _i2caddr; //!< I2C addr for the TwoWire interface - int32_t _sensorID; //!< ID of the BME Sensor - int32_t t_fine; //!< temperature with high resolution, stored as an attribute as this is used for temperature compensation reading humidity and pressure + void setSampling(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); - int8_t _cs; //!< for the SPI interface - int8_t _mosi; //!< for the SPI interface - int8_t _miso; //!< for the SPI interface - int8_t _sck; //!< for the SPI interface + void takeForcedMeasurement(); + float readTemperature(void); + float readPressure(void); + float readHumidity(void); - bme280_calib_data _bme280_calib; //!< here calibration data is stored + float readAltitude(float seaLevel); + float seaLevelForAltitude(float altitude, float pressure); + uint32_t sensorID(void); +protected: + TwoWire *_wire; //!< pointer to a TwoWire object + SPIClass *_spi; //!< pointer to SPI object + void readCoefficients(void); + bool isReadingCalibration(void); + uint8_t spixfer(uint8_t x); - /**************************************************************************/ - /*! - @brief 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; ///< inactive duration (standby time) in normal mode + void write8(byte reg, byte value); + uint8_t read8(byte reg); + 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 - // filter settings - // 000 = filter off - // 001 = 2x filter - // 010 = 4x filter - // 011 = 8x filter - // 100 and above = 16x filter - unsigned int filter : 3; ///< filter settings + uint8_t _i2caddr; //!< I2C addr for the TwoWire interface + int32_t _sensorID; //!< ID of the BME Sensor + int32_t t_fine; //!< temperature with high resolution, stored as an attribute + //!< as this is used for temperature compensation reading + //!< humidity and pressure - // unused - don't set - unsigned int none : 1; ///< unused - don't set - unsigned int spi3w_en : 1; ///< unused - don't set + int8_t _cs; //!< for the SPI interface + int8_t _mosi; //!< for the SPI interface + int8_t _miso; //!< for the SPI interface + int8_t _sck; //!< for the SPI interface - /// @return combined config register - unsigned int get() { - return (t_sb << 5) | (filter << 2) | spi3w_en; - } - }; - config _configReg; //!< config register object + bme280_calib_data _bme280_calib; //!< here calibration data is stored - - /**************************************************************************/ - /*! - @brief 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; ///< temperature oversampling + /**************************************************************************/ + /*! + @brief 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; ///< inactive duration (standby time) in normal mode - // pressure oversampling - // 000 = skipped - // 001 = x1 - // 010 = x2 - // 011 = x4 - // 100 = x8 - // 101 and above = x16 - unsigned int osrs_p : 3; ///< pressure oversampling + // filter settings + // 000 = filter off + // 001 = 2x filter + // 010 = 4x filter + // 011 = 8x filter + // 100 and above = 16x filter + unsigned int filter : 3; ///< filter settings - // device mode - // 00 = sleep - // 01 or 10 = forced - // 11 = normal - unsigned int mode : 2; ///< device mode + // unused - don't set + unsigned int none : 1; ///< unused - don't set + unsigned int spi3w_en : 1; ///< unused - don't set - /// @return combined ctrl register - unsigned int get() { - return (osrs_t << 5) | (osrs_p << 2) | mode; - } - }; - ctrl_meas _measReg; //!< measurement register object + /// @return combined config register + unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; } + }; + config _configReg; //!< config register object - - /**************************************************************************/ - /*! - @brief ctrl_hum register - */ - /**************************************************************************/ - struct ctrl_hum { - /// unused - don't set - unsigned int none : 5; + /**************************************************************************/ + /*! + @brief 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; ///< temperature oversampling - // pressure oversampling - // 000 = skipped - // 001 = x1 - // 010 = x2 - // 011 = x4 - // 100 = x8 - // 101 and above = x16 - unsigned int osrs_h : 3; ///< pressure oversampling + // pressure oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_p : 3; ///< pressure oversampling - /// @return combined ctrl hum register - unsigned int get() { - return (osrs_h); - } - }; - ctrl_hum _humReg; //!< hum register object + // device mode + // 00 = sleep + // 01 or 10 = forced + // 11 = normal + unsigned int mode : 2; ///< device mode + + /// @return combined ctrl register + unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; } + }; + ctrl_meas _measReg; //!< measurement register object + + /**************************************************************************/ + /*! + @brief 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; ///< pressure oversampling + + /// @return combined ctrl hum register + unsigned int get() { return (osrs_h); } + }; + ctrl_hum _humReg; //!< hum register object }; #endif