From 4b9f27d9e9863e445026318e09463f868f7fd44d Mon Sep 17 00:00:00 2001 From: Arnd Date: Fri, 4 Aug 2017 11:30:43 +0200 Subject: [PATCH] Streamlined code --- BME280.cpp | 75 +++++++++++++++++++++++++++--------------------------- BME280.h | 40 ++++++++++++++--------------- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/BME280.cpp b/BME280.cpp index 2520d7c..05c7743 100644 --- a/BME280.cpp +++ b/BME280.cpp @@ -10,31 +10,27 @@ ** ** *******************************************************************************************************************/ #include "BME280.h" // Include the header definition // - // // + //----------------------------------// +BME280_Class::BME280_Class() {} // Empty & unused class constructor // +BME280_Class::~BME280_Class() {} // Empty & unused class destructor // /******************************************************************************************************************* -** Class Constructor instantiates the class ** +** Method begin starts communications with the device. It is overloaded to allow for 3 different connection types ** +** to be used - I2C, Hardware SPI and Software SPI. When called with no parameters the I2C mode is enabled and ** +** the I2C bus is scanned for the first BME280 (typically at 0x76 or 0x77 unless an I2C expander is used to remap ** +** the address. ** *******************************************************************************************************************/ -BME280_Class::BME280_Class() {} // of class constructor // // -/******************************************************************************************************************* -** Class Destructor currently does nothing and is included for compatibility purposes ** -*******************************************************************************************************************/ -BME280_Class::~BME280_Class() {} // of class destructor // // -/******************************************************************************************************************* -** Method begin starts I2C communications with the device, using a default address if one is not specified and ** -** return true if the device has been detected and false if it was not ** -*******************************************************************************************************************/ -bool BME280_Class::begin(const uint8_t I2CAddress ) { // Start I2C communications // +bool BME280_Class::begin() { // Find I2C device // Wire.begin(); // Start I2C as master device // - _I2CAddress = I2CAddress; // Store actual I2C address to use // - Wire.beginTransmission(_I2CAddress); // Address the BME280 // - delay(BME280_I2C_DELAY); // Give the BME280 time to process // - uint8_t errorCode = Wire.endTransmission(); // See if there's a device present // - if (errorCode == 0) { // If we have a device at address, // - if (readByte(BME280_CHIPID_REG)==BME280_CHIPID) { // and it returns correct chip id, // - getCalibration(); // get the calibration values // - return true; // return success // - } // of if-then device is really a BME280 // // - } // of if-then device detected // // + for(_I2CAddress=0;_I2CAddress<127;_I2CAddress++) { // loop all possible addresses // + Wire.beginTransmission(_I2CAddress); // Check current address for BME280 // + if (Wire.endTransmission()==0) { // If no error we have a device // + if (readByte(BME280_CHIPID_REG)==BME280_CHIPID) { // check for correct chip id // + getCalibration(); // get the calibration values // + return true; // return success // + } // of if-then device is really a BME280 // // + } // of if-then we have found a device // // + } // of for-next each I2C address loop // // + _I2CAddress = 0; // Set to 0 to denote no I2C found // return false; // return failure if we get here // } // of method begin() // // /******************************************************************************************************************* @@ -133,8 +129,8 @@ uint8_t BME280_Class::getOversampling(const uint8_t sensor, // else // // returnValue = (readByte(BME280_CONTROL_REG)>>2)&B00000111; // // if (actual) { // If the actual flag has been set, // - if (returnValue==3) returnValue = 4; // then return the oversampling // - else if (returnValue==4) returnValue = 8; // multiplier instead of the table // + if (returnValue==3) returnValue = 4; // then return the oversampling // + else if (returnValue==4) returnValue = 8; // multiplier instead of the table // else if (returnValue>4) returnValue = 16; // index value // } // of if-then we return the actual count // // return(returnValue); // return oversampling bits // @@ -152,8 +148,9 @@ void BME280_Class::readSensors() { // if((_mode==ForcedMode||_mode==ForcedMode2)&&mode()==SleepMode) mode(_mode); // Force a reading if necessary // while(readByte(BME280_STATUS_REG)&B00001001!=0); // wait for measurement to complete // getData(BME280_PRESSUREDATA_REG,registerBuffer); // read all 8 bytes in one go // - /* First compute the temperature so that we can get the "_tfine" variable, which is used to compensate both the ** - ** humidity and pressure readings */ + //*******************************// // // + // First compute the temperature // // // + //*******************************// // // _Temperature = (int32_t)registerBuffer[3]<<12|(int32_t)registerBuffer[4]<<4|// // (int32_t)registerBuffer[5]>>4; // // i = ((((_Temperature>>3)-((int32_t)_cal_dig_T1 <<1)))* // // @@ -163,7 +160,9 @@ void BME280_Class::readSensors() { // *((int32_t)_cal_dig_T3))>>14; // // _tfine = i + j; // // _Temperature = (_tfine * 5 + 128) >> 8; // In centi-degrees Celsius // - /* Now compute the pressure value */ + //*******************************// // // + // Now compute the pressure // // // + //*******************************// // // _Pressure = (int32_t)registerBuffer[0]<<12|(int32_t)registerBuffer[1]<<4|// // (int32_t)registerBuffer[2]>>4; // // i = ((int64_t)_tfine) - 128000; // // @@ -181,7 +180,9 @@ void BME280_Class::readSensors() { // p = ((p + i + j) >> 8) + (((int64_t)_cal_dig_P7)<<4); // // _Pressure = p>>8; // in pascals // } // of if pressure would cause error // // - /* Now compute the Humidity value */ + //**********************************// // // + // And finally compute the humidity // // // + //**********************************// // // _Humidity = (int32_t)registerBuffer[6]<<8|(int32_t)registerBuffer[7]; // // i = (_tfine - ((int32_t)76800)); // // i = (((((_Humidity<<14)-(((int32_t)_cal_dig_H4)<<20)-(((int32_t)_cal_dig_H5)// // @@ -210,18 +211,16 @@ uint8_t BME280_Class::iirFilter(const uint8_t iirFilterSetting ) { // return(returnValue); // Return IIR Filter setting // } // of method iirFilter() // // /******************************************************************************************************************* -** Overloaded method inactiveTime() when called with no parameters returns the current inactive time setting, ** -** otherwise when called with one parameter will set the inactive time and return the new setting ** +** Method inactiveTime() when called with no parameters returns the current inactive time setting, otherwise uses ** +** the parameter to set the inactive time. ** *******************************************************************************************************************/ -uint8_t BME280_Class::inactiveTime() { // return the IIR Filter setting // - uint8_t returnValue = (readByte(BME280_CONFIG_REG)>>5)&B00000111; // Get 3 bits for the inactive time // - return(returnValue); // Return IIR Filter setting // -} // of method inactiveTime() // // uint8_t BME280_Class::inactiveTime(const uint8_t inactiveTimeSetting) { // return the IIR Filter setting // uint8_t returnValue = readByte(BME280_CONFIG_REG)&B10001111; // Get control reg, mask inactive // - returnValue |= (inactiveTimeSetting&B00000111)<<5; // use 3 bits of inactiveTimeSetting// - putData(BME280_CONFIG_REG,returnValue); // Write new control register value // - returnValue = (returnValue>>5)&B00000111; // Extract inactive setting // + if (inactiveTimeSetting!=UINT8_MAX) { // If we have a specified value // + returnValue |= (inactiveTimeSetting&B00000111)<<5; // use 3 bits of inactiveTimeSetting// + putData(BME280_CONFIG_REG,returnValue); // Write new control register value // + } // of if-then we have specified a new setting // // + returnValue = (returnValue>>5)&B00000111; // Extract 3 setting bits // return(returnValue); // Return inactive time setting // } // of method inactiveTime() // // /******************************************************************************************************************* @@ -272,5 +271,5 @@ void BME280_Class::getSensorData(int32_t &temp, int32_t &hum, int32_t &press){// *******************************************************************************************************************/ void BME280_Class::reset() { // reset device // putData(BME280_SOFTRESET_REG,BME280_SOFTWARE_CODE); // writing code here resets device // - begin(_I2CAddress); // Start device again // + if (_I2CAddress) begin(); // Start device again if I2C // } // of method reset() // // \ No newline at end of file diff --git a/BME280.h b/BME280.h index 80211c4..1f3818c 100644 --- a/BME280.h +++ b/BME280.h @@ -3,7 +3,8 @@ ** at https://www.bosch-sensortec.com/bst/products/all_products/bme280 and the datasheet is available from Bosch ** ** at https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf ** ** ** -** The BME280 can use either SPI or I2C for communications. The initial library version uses I2C exclusively. ** +** The BME280 can use either SPI or I2C for communications. The initial library version 1.0.0 defines only I2C ** +** while subsequent versions also allow SPI communications ** ** ** ** The most recent version of the library is available at https://github.com/SV-Zanshin/BME280 and extensive ** ** documentation of the library as well as example programs are described in the project's wiki pages located at ** @@ -28,6 +29,7 @@ ** Vers. Date Developer Comments ** ** ====== ========== =================== ======================================================================== ** ** 1.0.1 2017-08-03 Arnd@SV-Zanshin.Com All read/writes now use getData() and putData() templates in this header ** +** changed begin() method for I2C to search for first instance of BME280 ** ** 1.0.0 2017-08-03 Arnd@SV-Zanshin.Com Initial version with just I2C connectivity ** ** 1.0.0b 2017-07-31 Arnd@SV-Zanshin.Com Continued development ** ** 1.0.0a 2017-07-30 Arnd@SV-Zanshin.Com Started coding ** @@ -40,8 +42,17 @@ /***************************************************************************************************************** ** Declare constants used in the class ** *****************************************************************************************************************/ - const uint8_t BME280_ADDRESS = 0x77; // Device address power-up default // - const uint8_t BME280_I2C_DELAY = 0; // I2C and write time delay // + const uint8_t BME280_CHIPID_REG = 0xD0; // Chip-Id register // + const uint8_t BME280_CHIPID = 0x60; // Hard-coded value 0x60 for BME280 // + const uint8_t BME280_SOFTRESET_REG = 0xE0; // Reset when 0xB6 is written here // + const uint8_t BME280_CONTROLHUMID_REG = 0xF2; // Humidity control register // + const uint8_t BME280_STATUS_REG = 0xF3; // Device status register // + const uint8_t BME280_CONTROL_REG = 0xF4; // Device control register // + const uint8_t BME280_CONFIG_REG = 0xF5; // Device configuration register // + const uint8_t BME280_PRESSUREDATA_REG = 0xF7; // Pressure readings register // + const uint8_t BME280_TEMPDATA_REG = 0xFA; // Temperature readings register // + const uint8_t BME280_HUMIDDATA_REG = 0xFD; // Humidity readings register // + const uint8_t BME280_SOFTWARE_CODE = 0xB6; // Reset on this written to resetreg// //----------------------------------// const uint8_t BME280_T1_REG = 0x88; // Declare BME280 registers for the // const uint8_t BME280_T2_REG = 0x8A; // calibration data used to convert // @@ -61,17 +72,6 @@ const uint8_t BME280_H4_REG = 0xE4; // // const uint8_t BME280_H5_REG = 0xE5; // // const uint8_t BME280_H6_REG = 0xE7; //----------------------------------// - const uint8_t BME280_CHIPID_REG = 0xD0; // Chip-Id register // - const uint8_t BME280_CHIPID = 0x60; // Hard-coded value 0x60 for BME280 // - const uint8_t BME280_SOFTRESET_REG = 0xE0; // Reset when 0xB6 is written here // - const uint8_t BME280_SOFTWARE_CODE = 0xB6; // Reset when written to reset reg // - const uint8_t BME280_CONTROLHUMID_REG = 0xF2; // Humidity control register // - const uint8_t BME280_STATUS_REG = 0xF3; // Device status register // - const uint8_t BME280_CONTROL_REG = 0xF4; // Device control register // - const uint8_t BME280_CONFIG_REG = 0xF5; // Device configuration register // - const uint8_t BME280_PRESSUREDATA_REG = 0xF7; // Pressure readings register // - const uint8_t BME280_TEMPDATA_REG = 0xFA; // Temperature readings register // - const uint8_t BME280_HUMIDDATA_REG = 0xFD; // Humidity readings register // /***************************************************************************************************************** ** Declare enumerated types used in the class ** *****************************************************************************************************************/ @@ -93,7 +93,7 @@ public: // Publicly visible methods // BME280_Class(); // Class constructor // ~BME280_Class(); // Class destructor // - bool begin(const uint8_t I2CAddress = BME280_ADDRESS ); // I2C Communications at address // + bool begin(); // Start using I2C Communications // uint8_t mode(); // return device mode // uint8_t mode(const uint8_t operatingMode); // Set device mode // bool setOversampling(const uint8_t sensor, const uint8_t sampling); // Set enum sensorType Oversampling // @@ -101,8 +101,7 @@ const bool actual = false); // if "actual" set then return # // uint8_t iirFilter(); // Return the IIR Filter setting // uint8_t iirFilter(const uint8_t iirFilterSetting ); // Set IIR Filter and return value // - uint8_t inactiveTime(); // Return the inactive time setting // - uint8_t inactiveTime(const uint8_t inactiveTimeSetting ); // Set inactive time & return value // + uint8_t inactiveTime(const uint8_t inactiveTimeSetting=UINT8_MAX); // Set inactive time & return value // uint32_t measurementTime(const uint8_t measureTimeSetting=1); // Return measurement cycle time // void getSensorData(int32_t &temp, int32_t &hum, int32_t &press); // get most recent readings // void reset(); // Reset the BME280 // @@ -111,7 +110,7 @@ void readSensors(); // read the registers in one burst // void getCalibration(); // Load calibration from registers // bool _TransmissionStatus = false; // I2C communications status // - uint8_t _I2CAddress = BME280_ADDRESS; // Actual I2C address used w/default// + uint8_t _I2CAddress = 0; // Default is no I2C address known // uint8_t _cal_dig_H1,_cal_dig_H3; // Declare all of the calibration // int8_t _cal_dig_H6 = 0; // variables // uint16_t _cal_dig_T1,_cal_dig_P1; // // @@ -131,12 +130,11 @@ ** than in the c++ program library file. ** *************************************************************************************************************/ template< typename T > uint8_t &getData(const uint8_t addr,T &value) { // method to write a structure // - uint8_t* bytePtr = (uint8_t*)&value; // Pointer to structure beginning // + uint8_t* bytePtr = (uint8_t*)&value; // Pointer to structure beginning // uint8_t structSize = sizeof(T); // Number of bytes in structure // Wire.beginTransmission(_I2CAddress); // Address the I2C device // Wire.write(addr); // Send register address to read // _TransmissionStatus = Wire.endTransmission(); // Close transmission // - delayMicroseconds(BME280_I2C_DELAY); // delay required for sync // Wire.requestFrom(_I2CAddress, sizeof(T)); // Request 1 byte of data // while(!Wire.available()); // Wait until the first byte ready // for (uint16_t i=0;iuint8_t &putData(const uint8_t addr,const T &value){// method to write a structure // const uint8_t* bytePtr = (const uint8_t*)&value; // Pointer to structure beginning // - uint8_t structSize = sizeof(T); // Number of bytes in structure // + uint8_t structSize = sizeof(T); // Number of bytes in structure // Wire.beginTransmission(_I2CAddress); // Address the I2C device // Wire.write(addr); // Send register address to write // for (uint8_t i=0;i