Low power gas, pressure, temperature and humidity sensor
Dependents: MERGE Sensor_iAQ_sgp30_bme_si7051 POCBreath_V2_smd_commercial
BME680.h
- Committer:
- mcm
- Date:
- 2018-07-23
- Revision:
- 3:8aefe9304f85
- Parent:
- 1:4d60db802cfb
File content as of revision 3:8aefe9304f85:
/** * @brief BME680.h * @details Low power gas, pressure, temperature & humidity sensor. * Header file. * * * @return N/A * * @author Manuel Caballero * @date 21/July/2018 * @version 21/July/2018 The ORIGIN * @pre This is just a port from Bosh driver to mBed ( c++ ) * @warning N/A * @pre This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ). */ /** * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holder nor the names of the * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * The information provided is believed to be accurate and reliable. * The copyright holder assumes no responsibility * for the consequences of use * of such information nor for any infringement of patents or * other rights of third parties which may result from its use. * No license is granted by implication or otherwise under any patent or * patent rights of the copyright holder. * * @file bme680.h * @date 19 Jun 2018 * @version 3.5.9 * @brief * */ /*! @file bme680.h @brief Sensor driver for BME680 sensor */ /*! * @defgroup BME680 SENSOR API * @{*/ #ifndef BME680_H_ #define BME680_H_ #include "mbed.h" #include "bme680_defs.h" /** Example: @code #include "mbed.h" #include "BME680.h" BME680 myBME680 ( I2C_SDA, I2C_SCL, 400000 ); Serial pc ( USBTX, USBRX ); DigitalOut myled ( LED1 ); Ticker newReading; uint32_t myState = 0; //@brief FUNCTION PROTOTYPES void changeDATA ( void ); void user_delay_ms ( uint32_t period ); int8_t user_i2c_read ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ); int8_t user_i2c_write ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ); //@brief FUNCTION FOR APPLICATION MAIN ENTRY. int main() { pc.baud ( 115200 ); myled = 1; wait(3); myled = 0; struct bme680_dev gas_sensor; gas_sensor.dev_id = BME680_I2C_ADDR_PRIMARY; gas_sensor.intf = BME680_I2C_INTF; gas_sensor.read = user_i2c_read; gas_sensor.write = user_i2c_write; gas_sensor.delay_ms = user_delay_ms; // amb_temp can be set to 25 prior to configuring the gas sensor // or by performing a few temperature readings without operating the gas sensor. gas_sensor.amb_temp = 25; int8_t rslt = BME680_OK; rslt = myBME680.bme680_init ( &gas_sensor ); uint8_t set_required_settings; // Set the temperature, pressure and humidity settings gas_sensor.tph_sett.os_hum = BME680_OS_2X; gas_sensor.tph_sett.os_pres = BME680_OS_4X; gas_sensor.tph_sett.os_temp = BME680_OS_8X; gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3; // Set the remaining gas sensor settings and link the heating profile gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; // Create a ramp heat waveform in 3 steps gas_sensor.gas_sett.heatr_temp = 320; // degree Celsius gas_sensor.gas_sett.heatr_dur = 150; // milliseconds // Select the power mode // Must be set before writing the sensor configuration gas_sensor.power_mode = BME680_FORCED_MODE; // Set the required sensor settings needed set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; // Set the desired sensor configuration rslt = myBME680.bme680_set_sensor_settings ( set_required_settings, &gas_sensor ); // Set the power mode rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); // Get the total measurement duration so as to sleep or wait till the measurement is complete uint16_t meas_period; myBME680.bme680_get_profile_dur ( &meas_period, &gas_sensor ); struct bme680_field_data data; newReading.attach( &changeDATA, 1 ); // the address of the function to be attached ( changeDATA ) and the interval ( 1s ) // Let the callbacks take care of everything while(1) { sleep(); myled = 1; if ( myState == 1 ) { // Delay till the measurement is ready user_delay_ms ( meas_period ); rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); // Prepare the data to be sent through the UART. NOTE: sprintf does NOT allow float numbers, that is why we round the number and plot them as integer // Avoid using measurements from an unstable heating setup if ( data.status & BME680_GASM_VALID_MSK ) { pc.printf( "T: %.2f degC, P: %.2f hPa, H %.2f %%rH, G: %d ohms\r\n", ( data.temperature/100.0f ), ( data.pressure / 100.0f ), ( data.humidity / 1000.0f ), data.gas_resistance ); } else { pc.printf( "T: %.2f degC, P: %.2f hPa, H %.2f %%rH\r\n", ( data.temperature/100.0f ), ( data.pressure / 100.0f ), ( data.humidity / 1000.0f ) ); } // Trigger the next measurement if you would like to read data out continuously if ( gas_sensor.power_mode == BME680_FORCED_MODE ) { rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); } myState = 0; // Reset the variable } myled = 0; } } // @brief changeDATA ( void ) // // @details It changes myState variable // // @param[in] N/A // // @param[out] N/A. // // // @return N/A.. // // // @author Manuel Caballero // @date 21/July/2018 // @version 21/July/2018 The ORIGIN // @pre N/A // @warning N/A. void changeDATA ( void ) { myState = 1; } // @brief user_delay_ms ( uint32_t ) // // @details Return control or wait, for a period amount of milliseconds // // @param[in] period: Delay in milliseconds. // // @param[out] N/A. // // // @return N/A.. // // // @author Manuel Caballero // @date 21/July/2018 // @version 21/July/2018 The ORIGIN // @pre This is a Bosh pointer function adapted to our system. // @warning N/A. void user_delay_ms ( uint32_t period ) { // Return control or wait, // for a period amount of milliseconds wait_ms ( period ); } // @brief user_i2c_read ( uint8_t , uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) // // @details It adapts I2C reading functionality. // // @param[in] dev_id: I2C address. // @param[in] reg_addr: Register to be read. // @param[in] len: How many bytes to read. // // @param[out] reg_data: Result. // // // @return Status of user_i2c_read. // // // @author Manuel Caballero // @date 21/July/2018 // @version 21/July/2018 The ORIGIN // @pre This is a Bosh pointer function adapted to our system. // @warning N/A. int8_t user_i2c_read ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) { int8_t rslt = 0; // Return 0 for Success, non-zero for failure // The parameter dev_id can be used as a variable to store the I2C address of the device // Data on the bus should be like // |------------+---------------------| // | I2C action | Data | // |------------+---------------------| // | Start | - | // | Write | (reg_addr) | // | Stop | - | // | Start | - | // | Read | (reg_data[0]) | // | Read | (....) | // | Read | (reg_data[len - 1]) | // | Stop | - | // |------------+---------------------| // Read data uint32_t aux = 0; aux = myBME680._i2c.write ( dev_id, (char*)®_addr, 1, true ); aux = myBME680._i2c.read ( dev_id, (char*)®_data[0], len ); if ( aux == 0 ) { rslt = 0; } else { rslt = 0xFF; } return rslt; } // @brief user_i2c_write ( uint8_t , uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) // // @details It adapts I2C writing functionality. // // @param[in] dev_id: I2C address. // @param[in] reg_addr: Register to be read. // @param[out] reg_data: Data to be written. // @param[in] len: How many bytes to read. // // @param[out] N/A. // // // @return Status of user_i2c_write. // // // @author Manuel Caballero // @date 21/July/2018 // @version 21/July/2018 The ORIGIN // @pre This is a Bosh pointer function adapted to our system. // @warning N/A. int8_t user_i2c_write ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) { int8_t rslt = 0; // Return 0 for Success, non-zero for failure // The parameter dev_id can be used as a variable to store the I2C address of the device // Data on the bus should be like // |------------+---------------------| // | I2C action | Data | // |------------+---------------------| // | Start | - | // | Write | (reg_addr) | // | Write | (reg_data[0]) | // | Write | (....) | // | Write | (reg_data[len - 1]) | // | Stop | - | // |------------+---------------------| uint32_t aux = 0; char cmd[16] = { 0 }; uint32_t i = 0; // Prepare the data to be sent cmd[0] = reg_addr; for ( i = 1; i <= len; i++ ) { cmd[i] = reg_data[i - 1]; } // Write data aux = myBME680._i2c.write ( dev_id, &cmd[0], len + 1, false ); if ( aux == 0 ) { rslt = 0; } else { rslt = 0xFF; } return rslt; } @endcode */ /*! Library for BME680 Low power gas, pressure, temperature & humidity sensor. */ class BME680 { public: /** Create an BME680 object connected to the specified I2C pins. * * @param sda I2C data pin * @param scl I2C clock pin * @param freq I2C frequency */ BME680 ( PinName sda, PinName scl, uint32_t freq ); /** Delete BME680 object. */ ~BME680(); /* function prototype declarations */ /*! * @brief This API is the entry point. * It reads the chip-id and calibration data from the sensor. * * @param[in,out] dev : Structure instance of bme680_dev * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_init(struct bme680_dev *dev); /*! * @brief This API writes the given data to the register address * of the sensor. * * @param[in] reg_addr : Register address from where the data to be written. * @param[in] reg_data : Pointer to data buffer which is to be written * in the sensor. * @param[in] len : No of bytes of data to write.. * @param[in] dev : Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev); /*! * @brief This API reads the data from the given register address of the sensor. * * @param[in] reg_addr : Register address from where the data to be read * @param[out] reg_data : Pointer to data buffer to store the read data. * @param[in] len : No of bytes of data to be read. * @param[in] dev : Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev); /*! * @brief This API performs the soft reset of the sensor. * * @param[in] dev : Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. */ int8_t bme680_soft_reset(struct bme680_dev *dev); /*! * @brief This API is used to set the power mode of the sensor. * * @param[in] dev : Structure instance of bme680_dev * @note : Pass the value to bme680_dev.power_mode structure variable. * * value | mode * -------------|------------------ * 0x00 | BME680_SLEEP_MODE * 0x01 | BME680_FORCED_MODE * * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_set_sensor_mode(struct bme680_dev *dev); /*! * @brief This API is used to get the power mode of the sensor. * * @param[in] dev : Structure instance of bme680_dev * @note : bme680_dev.power_mode structure variable hold the power mode. * * value | mode * ---------|------------------ * 0x00 | BME680_SLEEP_MODE * 0x01 | BME680_FORCED_MODE * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_get_sensor_mode(struct bme680_dev *dev); /*! * @brief This API is used to set the profile duration of the sensor. * * @param[in] dev : Structure instance of bme680_dev. * @param[in] duration : Duration of the measurement in ms. * * @return Nothing */ void bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev); /*! * @brief This API is used to get the profile duration of the sensor. * * @param[in] dev : Structure instance of bme680_dev. * @param[in] duration : Duration of the measurement in ms. * * @return Nothing */ void bme680_get_profile_dur(uint16_t *duration, const struct bme680_dev *dev); /*! * @brief This API reads the pressure, temperature and humidity and gas data * from the sensor, compensates the data and store it in the bme680_data * structure instance passed by the user. * * @param[out] data: Structure instance to hold the data. * @param[in] dev : Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev); /*! * @brief This API is used to set the oversampling, filter and T,P,H, gas selection * settings in the sensor. * * @param[in] dev : Structure instance of bme680_dev. * @param[in] desired_settings : Variable used to select the settings which * are to be set in the sensor. * * Macros | Functionality *---------------------------------|---------------------------------------------- * BME680_OST_SEL | To set temperature oversampling. * BME680_OSP_SEL | To set pressure oversampling. * BME680_OSH_SEL | To set humidity oversampling. * BME680_GAS_MEAS_SEL | To set gas measurement setting. * BME680_FILTER_SEL | To set filter setting. * BME680_HCNTRL_SEL | To set humidity control setting. * BME680_RUN_GAS_SEL | To set run gas setting. * BME680_NBCONV_SEL | To set NB conversion setting. * BME680_GAS_SENSOR_SEL | To set all gas sensor related settings * * @note : Below are the macros to be used by the user for selecting the * desired settings. User can do OR operation of these macros for configuring * multiple settings. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. */ int8_t bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); /*! * @brief This API is used to get the oversampling, filter and T,P,H, gas selection * settings in the sensor. * * @param[in] dev : Structure instance of bme680_dev. * @param[in] desired_settings : Variable used to select the settings which * are to be get from the sensor. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. */ int8_t bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); I2C _i2c; private: /*! * @brief This internal API is used to read the calibrated data from the sensor. * * This function is used to retrieve the calibration * data from the image registers of the sensor. * * @note Registers 89h to A1h for calibration data 1 to 24 * from bit 0 to 7 * @note Registers E1h to F0h for calibration data 25 to 40 * from bit 0 to 7 * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t get_calib_data(struct bme680_dev *dev); /*! * @brief This internal API is used to set the gas configuration of the sensor. * * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t set_gas_config(struct bme680_dev *dev); /*! * @brief This internal API is used to get the gas configuration of the sensor. * @note heatr_temp and heatr_dur values are currently register data * and not the actual values set * * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t get_gas_config(struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the Heat duration value. * * @param[in] dur :Value of the duration to be shared. * * @return uint8_t threshold duration after calculation. */ uint8_t calc_heater_dur(uint16_t dur); #ifndef BME680_FLOAT_POINT_COMPENSATION /*! * @brief This internal API is used to calculate the temperature value. * * @param[in] dev :Structure instance of bme680_dev. * @param[in] temp_adc :Contains the temperature ADC value . * * @return uint32_t calculated temperature. */ int16_t calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the pressure value. * * @param[in] dev :Structure instance of bme680_dev. * @param[in] pres_adc :Contains the pressure ADC value . * * @return uint32_t calculated pressure. */ uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the humidity value. * * @param[in] dev :Structure instance of bme680_dev. * @param[in] hum_adc :Contains the humidity ADC value. * * @return uint32_t calculated humidity. */ uint32_t calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the Gas Resistance value. * * @param[in] dev :Structure instance of bme680_dev. * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. * @param[in] gas_range :Contains the range of gas values. * * @return uint32_t calculated gas resistance. */ uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the Heat Resistance value. * * @param[in] dev : Structure instance of bme680_dev * @param[in] temp : Contains the target temperature value. * * @return uint8_t calculated heater resistance. */ uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev); #else /*! * @brief This internal API is used to calculate the * temperature value value in float format * * @param[in] dev :Structure instance of bme680_dev. * @param[in] temp_adc :Contains the temperature ADC value . * * @return Calculated temperature in float */ float calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the * pressure value value in float format * * @param[in] dev :Structure instance of bme680_dev. * @param[in] pres_adc :Contains the pressure ADC value . * * @return Calculated pressure in float. */ float calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the * humidity value value in float format * * @param[in] dev :Structure instance of bme680_dev. * @param[in] hum_adc :Contains the humidity ADC value. * * @return Calculated humidity in float. */ float calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the * gas resistance value value in float format * * @param[in] dev :Structure instance of bme680_dev. * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. * @param[in] gas_range :Contains the range of gas values. * * @return Calculated gas resistance in float. */ float calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); /*! * @brief This internal API is used to calculate the * heater resistance value in float format * * @param[in] temp : Contains the target temperature value. * @param[in] dev : Structure instance of bme680_dev. * * @return Calculated heater resistance in float. */ float calc_heater_res(uint16_t temp, const struct bme680_dev *dev); #endif /*! * @brief This internal API is used to calculate the field data of sensor. * * @param[out] data :Structure instance to hold the data * @param[in] dev :Structure instance of bme680_dev. * * @return int8_t result of the field data from sensor. */ int8_t read_field_data(struct bme680_field_data *data, struct bme680_dev *dev); /*! * @brief This internal API is used to set the memory page * based on register address. * * The value of memory page * value | Description * --------|-------------- * 0 | BME680_PAGE0_SPI * 1 | BME680_PAGE1_SPI * * @param[in] dev :Structure instance of bme680_dev. * @param[in] reg_addr :Contains the register address array. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t set_mem_page(uint8_t reg_addr, struct bme680_dev *dev); /*! * @brief This internal API is used to get the memory page based * on register address. * * The value of memory page * value | Description * --------|-------------- * 0 | BME680_PAGE0_SPI * 1 | BME680_PAGE1_SPI * * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t get_mem_page(struct bme680_dev *dev); /*! * @brief This internal API is used to validate the device pointer for * null conditions. * * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t null_ptr_check(const struct bme680_dev *dev); /*! * @brief This internal API is used to check the boundary * conditions. * * @param[in] value :pointer to the value. * @param[in] min :minimum value. * @param[in] max :maximum value. * @param[in] dev :Structure instance of bme680_dev. * * @return Result of API execution status * @retval zero -> Success / +ve value -> Warning / -ve value -> Error */ int8_t boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev); uint32_t _BME680_Addr; }; #endif /** @}*/