From 3ba9abb813660f900365b56e15cac5b7848bb6c4 Mon Sep 17 00:00:00 2001 From: Bosch Sensortec Date: Mon, 17 Apr 2023 10:50:33 +0200 Subject: [PATCH] Updated to new architecture. Added examples. Updated contributed examples. --- README.md | 316 +-------- bme280.c | 544 ++++++++------- bme280.h | 130 ++-- bme280_defs.h | 304 +++++---- examples/Makefile | 8 - examples/common/common.c | 216 ++++++ examples/common/common.h | 140 ++++ examples/contributed/Makefile | 8 + examples/{ => contributed}/bsd_userspace.c | 666 +++++++++--------- examples/{ => contributed}/linux_userspace.c | 669 ++++++++++--------- examples/humidity/Makefile | 15 + examples/humidity/humidity.c | 129 ++++ examples/pressure/Makefile | 15 + examples/pressure/pressure.c | 129 ++++ examples/temperature/Makefile | 15 + examples/temperature/temperature.c | 129 ++++ 16 files changed, 1987 insertions(+), 1446 deletions(-) delete mode 100644 examples/Makefile create mode 100644 examples/common/common.c create mode 100644 examples/common/common.h create mode 100644 examples/contributed/Makefile rename examples/{ => contributed}/bsd_userspace.c (91%) rename examples/{ => contributed}/linux_userspace.c (90%) create mode 100644 examples/humidity/Makefile create mode 100644 examples/humidity/humidity.c create mode 100644 examples/pressure/Makefile create mode 100644 examples/pressure/pressure.c create mode 100644 examples/temperature/Makefile create mode 100644 examples/temperature/temperature.c diff --git a/README.md b/README.md index 0a0e398..8f36583 100644 --- a/README.md +++ b/README.md @@ -1,300 +1,30 @@ # BME280 sensor API -## Introduction -This package contains the Bosch Sensortec's BME280 pressure sensor driver (sensor API) -The sensor driver package includes bme280.c, bme280.h and bme280_defs.h files. +### Sensor overview +BME280 is a combined digital humidity, pressure and temperature sensor based on proven sensing principles. +Its small dimensions and its low power consumption allow the implementation in battery driven devices such as +handsets, GPS modules or watches. -## Integration details -* Integrate bme280.h, bme280_defs.h and bme280.c file in to the project. -* Include the bme280.h file in your code like below. -``` c -#include "bme280.h" -``` +### Target Application +- Context awareness, e.g.skin detection, room change detection. +- Fitness monitoring / well-being +- Home automation control +- Internet of things +- GPS enhancement(e.g.time-to-first-fix improvement, dead reckoning, slope detection) +- Indoor navigation(change of floor detection, elevation detection) +- Outdoor navigation, leisure and sports applications +- Weather forecast +- Vertical velocity indication(rise/sink speed) -## File information -* bme280_defs.h : This header file has the constants, macros and datatype declarations. -* bme280.h : This header file contains the declarations of the sensor driver APIs. -* bme280.c : This source file contains the definitions of the sensor driver APIs. +### Feature +- Pressure +- Temperature +- Humidity -## Supported sensor interfaces -* SPI 4-wire -* I2C +### Important links -SPI 3-wire is currently not supported in the API. -## Usage guide -### Initializing the sensor -To initialize the sensor, user need to create a device structure. User can do this by -creating an instance of the structure bme280_dev. After creating the device strcuture, user -need to fill in the various parameters as shown below. - -#### Example for SPI 4-Wire -``` c -struct bme280_dev dev; -int8_t rslt = BME280_OK; - -/* Sensor_0 interface over SPI with native chip select line */ -uint8_t dev_addr = 0; - -dev.intf_ptr = &dev_addr; -dev.intf = BME280_SPI_INTF; -dev.read = user_spi_read; -dev.write = user_spi_write; -dev.delay_ms = user_delay_ms; - -rslt = bme280_init(&dev); -``` -#### Example for I2C -``` c -struct bme280_dev dev; -int8_t rslt = BME280_OK; -uint8_t dev_addr = BME280_I2C_ADDR_PRIM; - -dev.intf_ptr = &dev_addr; -dev.intf = BME280_I2C_INTF; -dev.read = user_i2c_read; -dev.write = user_i2c_write; -dev.delay_ms = user_delay_ms; - -rslt = bme280_init(&dev); -``` -Regarding compensation functions for temperature,pressure and humidity we have two implementations. -1) Double precision floating point version -2) Integer version - -By default, integer version is used in the API. If the user needs the floating point version, the user has to uncomment BME280_FLOAT_ENABLE macro in bme280_defs.h file or add that to the compiler flags. - -In integer compensation functions, we also have below two implementations for pressure. -1) For 32 bit machine. -2) For 64 bit machine. - -By default, 64 bit variant is used in the API. If the user wants 32 bit variant, the user can disable the -macro BME280_64BIT_ENABLE in bme280_defs.h file. - -### Sensor data units -> The sensor data units depends on the following macros being enabled or not, -> (in bme280_defs.h file or as compiler macros) -> * BME280_FLOAT_ENABLE -> * BME280_64BIT_ENABLE - -In case of the macro "BME280_FLOAT_ENABLE" enabled, -The outputs are in double and the units are - - - °C for temperature - - % relative humidity - - Pascal for pressure - -In case if "BME280_FLOAT_ENABLE" is not enabled, then it is - - - int32_t for temperature with the units 100 * °C - - uint32_t for humidity with the units 1024 * % relative humidity - - uint32_t for pressure - If macro "BME280_64BIT_ENABLE" is enabled, which it is by default, the unit is 100 * Pascal - If this macro is disabled, Then the unit is in Pascal - -### Stream sensor data -#### Stream sensor data in forced mode - -``` c -int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) -{ - int8_t rslt; - uint8_t settings_sel; - uint32_t req_delay; - struct bme280_data comp_data; - - /* Recommended mode of operation: Indoor navigation */ - dev->settings.osr_h = BME280_OVERSAMPLING_1X; - dev->settings.osr_p = BME280_OVERSAMPLING_16X; - dev->settings.osr_t = BME280_OVERSAMPLING_2X; - dev->settings.filter = BME280_FILTER_COEFF_16; - - settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL; - - rslt = bme280_set_sensor_settings(settings_sel, dev); - - /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled - * and the oversampling configuration. */ - req_delay = bme280_cal_meas_delay(&dev->settings); - - printf("Temperature, Pressure, Humidity\r\n"); - /* Continuously stream sensor data */ - while (1) { - rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); - /* Wait for the measurement to complete and print data @25Hz */ - dev->delay_ms(req_delay, dev->intf_ptr); - rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); - print_sensor_data(&comp_data); - } - return rslt; -} - -void print_sensor_data(struct bme280_data *comp_data) -{ -#ifdef BME280_FLOAT_ENABLE - printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); -#else - printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); -#endif -} -``` -##### Stream sensor data in normal mode -``` c -int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev) -{ - int8_t rslt; - uint8_t settings_sel; - struct bme280_data comp_data; - - /* Recommended mode of operation: Indoor navigation */ - dev->settings.osr_h = BME280_OVERSAMPLING_1X; - dev->settings.osr_p = BME280_OVERSAMPLING_16X; - dev->settings.osr_t = BME280_OVERSAMPLING_2X; - dev->settings.filter = BME280_FILTER_COEFF_16; - dev->settings.standby_time = BME280_STANDBY_TIME_62_5_MS; - - settings_sel = BME280_OSR_PRESS_SEL; - settings_sel |= BME280_OSR_TEMP_SEL; - settings_sel |= BME280_OSR_HUM_SEL; - settings_sel |= BME280_STANDBY_SEL; - settings_sel |= BME280_FILTER_SEL; - rslt = bme280_set_sensor_settings(settings_sel, dev); - rslt = bme280_set_sensor_mode(BME280_NORMAL_MODE, dev); - - printf("Temperature, Pressure, Humidity\r\n"); - while (1) { - /* Delay while the sensor completes a measurement */ - dev->delay_ms(70, dev->intf_ptr); - rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); - print_sensor_data(&comp_data); - } - - return rslt; -} - -void print_sensor_data(struct bme280_data *comp_data) -{ -#ifdef BME280_FLOAT_ENABLE - printf("%0.2f, %0.2f, %0.2f\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); -#else - printf("%ld, %ld, %ld\r\n",comp_data->temperature, comp_data->pressure, comp_data->humidity); -#endif -} -``` - -### Templates for function pointers -``` c - -void user_delay_ms(uint32_t period, void *intf_ptr) -{ - /* - * Return control or wait, - * for a period amount of milliseconds - */ -} - -int8_t user_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter intf_ptr can be used as a variable to select which Chip Select pin has - * to be set low to activate the relevant device on the SPI bus - */ - - /* - * Data on the bus should be like - * |----------------+---------------------+-------------| - * | MOSI | MISO | Chip Select | - * |----------------+---------------------|-------------| - * | (don't care) | (don't care) | HIGH | - * | (reg_addr) | (don't care) | LOW | - * | (don't care) | (reg_data[0]) | LOW | - * | (....) | (....) | LOW | - * | (don't care) | (reg_data[len - 1]) | LOW | - * | (don't care) | (don't care) | HIGH | - * |----------------+---------------------|-------------| - */ - - return rslt; -} - -int8_t user_spi_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter intf_ptr can be used as a variable to select which Chip Select pin has - * to be set low to activate the relevant device on the SPI bus - */ - - /* - * Data on the bus should be like - * |---------------------+--------------+-------------| - * | MOSI | MISO | Chip Select | - * |---------------------+--------------|-------------| - * | (don't care) | (don't care) | HIGH | - * | (reg_addr) | (don't care) | LOW | - * | (reg_data[0]) | (don't care) | LOW | - * | (....) | (....) | LOW | - * | (reg_data[len - 1]) | (don't care) | LOW | - * | (don't care) | (don't care) | HIGH | - * |---------------------+--------------|-------------| - */ - - return rslt; -} - -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter intf_ptr 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 | - | - * |------------+---------------------| - */ - - return rslt; -} - -int8_t user_i2c_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - - /* - * The parameter intf_ptr 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 | - | - * |------------+---------------------| - */ - - return rslt; -} - -``` \ No newline at end of file +- [BME280 product page](https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/) +- [BME280 datasheet](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf) +- [BME280 shuttle board flyer](https://www.bosch-sensortec.com/media/boschsensortec/downloads/shuttle_board_flyer/application_board_3_1/bst-bme280-sf000.pdf) +- [Community support page](https://community.bosch-sensortec.com) \ No newline at end of file diff --git a/bme280.c b/bme280.c index cabefc2..515d174 100644 --- a/bme280.c +++ b/bme280.c @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme280.c -* @date 2020-03-28 -* @version v3.5.0 +* @date 2020-12-17 +* @version v3.5.1 * */ @@ -104,7 +104,7 @@ static int8_t null_ptr_check(const struct bme280_dev *dev); * @param[in] len : No of bytes of data to be written for burst write. * */ -static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len); +static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint32_t len); /*! * @brief This internal API reads the calibration data from the sensor, parse @@ -141,90 +141,6 @@ static void parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_d */ static void parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev); -#ifdef BME280_FLOAT_ENABLE - -/*! - * @brief This internal API is used to compensate the raw pressure data and - * return the compensated pressure data in double data type. - * - * @param[in] uncomp_data : Contains the uncompensated pressure data. - * @param[in] calib_data : Pointer to the calibration data structure. - * - * @return Compensated pressure data in double. - * - */ -static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data, - const struct bme280_calib_data *calib_data); - -/*! - * @brief This internal API is used to compensate the raw humidity data and - * return the compensated humidity data in double data type. - * - * @param[in] uncomp_data : Contains the uncompensated humidity data. - * @param[in] calib_data : Pointer to the calibration data structure. - * - * @return Compensated humidity data in double. - * - */ -static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data, - const struct bme280_calib_data *calib_data); - -/*! - * @brief This internal API is used to compensate the raw temperature data and - * return the compensated temperature data in double data type. - * - * @param[in] uncomp_data : Contains the uncompensated temperature data. - * @param[in] calib_data : Pointer to calibration data structure. - * - * @return Compensated temperature data in double. - * - */ -static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data, - struct bme280_calib_data *calib_data); - -#else - -/*! - * @brief This internal API is used to compensate the raw temperature data and - * return the compensated temperature data in integer data type. - * - * @param[in] uncomp_data : Contains the uncompensated temperature data. - * @param[in] calib_data : Pointer to calibration data structure. - * - * @return Compensated temperature data in integer. - * - */ -static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data, - struct bme280_calib_data *calib_data); - -/*! - * @brief This internal API is used to compensate the raw pressure data and - * return the compensated pressure data in integer data type. - * - * @param[in] uncomp_data : Contains the uncompensated pressure data. - * @param[in] calib_data : Pointer to the calibration data structure. - * - * @return Compensated pressure data in integer. - * - */ -static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data, - const struct bme280_calib_data *calib_data); - -/*! - * @brief This internal API is used to compensate the raw humidity data and - * return the compensated humidity data in integer data type. - * - * @param[in] uncomp_data : Contains the uncompensated humidity data. - * @param[in] calib_data : Pointer to the calibration data structure. - * - * @return Compensated humidity data in integer. - * - */ -static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data, - const struct bme280_calib_data *calib_data); - -#endif - /*! * @brief This internal API is used to identify the settings which the user * wants to modify in the sensor. @@ -378,6 +294,15 @@ static void fill_standby_settings(uint8_t *reg_data, const struct bme280_setting */ static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings); +/*! + * @brief This API is used to parse the pressure, temperature and + * humidity data and store it in the bme280_uncomp_data structure instance. + * + * @param[in] reg_data : Contains register data which needs to be parsed + * @param[out] uncomp_data : Contains the uncompensated pressure, temperature and humidity data + */ +static void parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data); + /*! * @brief This internal API reloads the already existing device settings in the * sensor after soft reset. @@ -395,6 +320,90 @@ static void parse_device_settings(const uint8_t *reg_data, struct bme280_setting */ static int8_t reload_device_settings(const struct bme280_settings *settings, struct bme280_dev *dev); +#ifdef BME280_DOUBLE_ENABLE + +/*! + * @brief This internal API is used to compensate the raw pressure data and + * return the compensated pressure data in double data type. + * + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated pressure data in double. + * + */ +static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data, + const struct bme280_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the raw humidity data and + * return the compensated humidity data in double data type. + * + * @param[in] uncomp_data : Contains the uncompensated humidity data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated humidity data in double. + * + */ +static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data, + const struct bme280_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data in double data type. + * + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] calib_data : Pointer to calibration data structure. + * + * @return Compensated temperature data in double. + * + */ +static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data, + struct bme280_calib_data *calib_data); + +#else + +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data in integer data type. + * + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] calib_data : Pointer to calibration data structure. + * + * @return Compensated temperature data in integer. + * + */ +static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data, + struct bme280_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the raw pressure data and + * return the compensated pressure data in integer data type. + * + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated pressure data in integer. + * + */ +static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data, + const struct bme280_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the raw humidity data and + * return the compensated humidity data in integer data type. + * + * @param[in] uncomp_data : Contains the uncompensated humidity data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated humidity data in integer. + * + */ +static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data, + const struct bme280_calib_data *calib_data); + +#endif + /****************** Global Function Definitions *******************************/ /*! @@ -404,46 +413,28 @@ static int8_t reload_device_settings(const struct bme280_settings *settings, str int8_t bme280_init(struct bme280_dev *dev) { int8_t rslt; - - /* chip id read try count */ - uint8_t try_count = 5; uint8_t chip_id = 0; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); + /* Read the chip-id of bme280 sensor */ + rslt = bme280_get_regs(BME280_REG_CHIP_ID, &chip_id, 1, dev); - /* Proceed if null check is fine */ + /* Check for chip id validity */ if (rslt == BME280_OK) { - while (try_count) + if (chip_id == BME280_CHIP_ID) { - /* Read the chip-id of bme280 sensor */ - rslt = bme280_get_regs(BME280_CHIP_ID_ADDR, &chip_id, 1, dev); + dev->chip_id = chip_id; - /* Check for chip id validity */ - if ((rslt == BME280_OK) && (chip_id == BME280_CHIP_ID)) + /* Reset the sensor */ + rslt = bme280_soft_reset(dev); + + if (rslt == BME280_OK) { - dev->chip_id = chip_id; - - /* Reset the sensor */ - rslt = bme280_soft_reset(dev); - - if (rslt == BME280_OK) - { - /* Read the calibration data */ - rslt = get_calib_data(dev); - } - - break; + /* Read the calibration data */ + rslt = get_calib_data(dev); } - - /* Wait for 1 ms */ - dev->delay_us(1000, dev->intf_ptr); - --try_count; } - - /* Chip id check failed */ - if (!try_count) + else { rslt = BME280_E_DEV_NOT_FOUND; } @@ -455,14 +446,13 @@ int8_t bme280_init(struct bme280_dev *dev) /*! * @brief This API reads the data from the given register address of the sensor. */ -int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme280_dev *dev) +int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme280_dev *dev) { int8_t rslt; - /* Check for null pointer in the device structure*/ + /* Check for null pointer in the device structure */ rslt = null_ptr_check(dev); - /* Proceed if null check is fine */ if ((rslt == BME280_OK) && (reg_data != NULL)) { /* If interface selected is SPI */ @@ -471,7 +461,7 @@ int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct reg_addr = reg_addr | 0x80; } - /* Read the data */ + /* Read the data */ dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr); /* Check for communication error */ @@ -492,20 +482,19 @@ int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct * @brief This API writes the given data to the register address * of the sensor. */ -int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme280_dev *dev) +int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bme280_dev *dev) { int8_t rslt; uint8_t temp_buff[20]; /* Typically not to write more than 10 registers */ + uint32_t temp_len; + uint32_t reg_addr_cnt; - if (len > 10) + if (len > BME280_MAX_LEN) { - len = 10; + len = BME280_MAX_LEN; } - uint16_t temp_len; - uint8_t reg_addr_cnt; - - /* Check for null pointer in the device structure*/ + /* Check for null pointer in the device structure */ rslt = null_ptr_check(dev); /* Check for arguments validity */ @@ -563,20 +552,18 @@ int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, * @brief This API sets the oversampling, filter and standby duration * (normal mode) settings in the sensor. */ -int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *dev) +int8_t bme280_set_sensor_settings(uint8_t desired_settings, + const struct bme280_settings *settings, + struct bme280_dev *dev) { int8_t rslt; uint8_t sensor_mode; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - - /* Proceed if null check is fine */ - if (rslt == BME280_OK) + if (settings != NULL) { rslt = bme280_get_sensor_mode(&sensor_mode, dev); - if ((rslt == BME280_OK) && (sensor_mode != BME280_SLEEP_MODE)) + if ((rslt == BME280_OK) && (sensor_mode != BME280_POWERMODE_SLEEP)) { rslt = put_device_to_sleep(dev); } @@ -588,7 +575,7 @@ int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *d */ if (are_settings_changed(OVERSAMPLING_SETTINGS, desired_settings)) { - rslt = set_osr_settings(desired_settings, &dev->settings, dev); + rslt = set_osr_settings(desired_settings, settings, dev); } /* Check if user wants to change filter and/or @@ -596,10 +583,14 @@ int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *d */ if ((rslt == BME280_OK) && are_settings_changed(FILTER_STANDBY_SETTINGS, desired_settings)) { - rslt = set_filter_standby_settings(desired_settings, &dev->settings, dev); + rslt = set_filter_standby_settings(desired_settings, settings, dev); } } } + else + { + rslt = BME280_E_NULL_PTR; + } return rslt; } @@ -608,24 +599,24 @@ int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *d * @brief This API gets the oversampling, filter and standby duration * (normal mode) settings from the sensor. */ -int8_t bme280_get_sensor_settings(struct bme280_dev *dev) +int8_t bme280_get_sensor_settings(struct bme280_settings *settings, struct bme280_dev *dev) { int8_t rslt; uint8_t reg_data[4]; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - - /* Proceed if null check is fine */ - if (rslt == BME280_OK) + if (settings != NULL) { - rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); + rslt = bme280_get_regs(BME280_REG_CTRL_HUM, reg_data, 4, dev); if (rslt == BME280_OK) { - parse_device_settings(reg_data, &dev->settings); + parse_device_settings(reg_data, settings); } } + else + { + rslt = BME280_E_NULL_PTR; + } return rslt; } @@ -638,26 +629,20 @@ int8_t bme280_set_sensor_mode(uint8_t sensor_mode, struct bme280_dev *dev) int8_t rslt; uint8_t last_set_mode; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); + rslt = bme280_get_sensor_mode(&last_set_mode, dev); + /* If the sensor is not in sleep mode put the device to sleep + * mode + */ + if ((rslt == BME280_OK) && (last_set_mode != BME280_POWERMODE_SLEEP)) + { + rslt = put_device_to_sleep(dev); + } + + /* Set the power mode */ if (rslt == BME280_OK) { - rslt = bme280_get_sensor_mode(&last_set_mode, dev); - - /* If the sensor is not in sleep mode put the device to sleep - * mode - */ - if ((rslt == BME280_OK) && (last_set_mode != BME280_SLEEP_MODE)) - { - rslt = put_device_to_sleep(dev); - } - - /* Set the power mode */ - if (rslt == BME280_OK) - { - rslt = write_power_mode(sensor_mode, dev); - } + rslt = write_power_mode(sensor_mode, dev); } return rslt; @@ -670,15 +655,12 @@ int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, struct bme280_dev *dev) { int8_t rslt; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - - if ((rslt == BME280_OK) && (sensor_mode != NULL)) + if (sensor_mode != NULL) { /* Read the power mode register */ - rslt = bme280_get_regs(BME280_PWR_CTRL_ADDR, sensor_mode, 1, dev); + rslt = bme280_get_regs(BME280_REG_PWR_CTRL, sensor_mode, 1, dev); - /* Assign the power mode in the device structure */ + /* Assign the power mode to variable */ *sensor_mode = BME280_GET_BITS_POS_0(*sensor_mode, BME280_SENSOR_MODE); } else @@ -695,37 +677,30 @@ int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, struct bme280_dev *dev) int8_t bme280_soft_reset(struct bme280_dev *dev) { int8_t rslt; - uint8_t reg_addr = BME280_RESET_ADDR; + uint8_t reg_addr = BME280_REG_RESET; uint8_t status_reg = 0; uint8_t try_run = 5; /* 0xB6 is the soft reset command */ uint8_t soft_rst_cmd = BME280_SOFT_RESET_COMMAND; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); + /* Write the soft reset command in the sensor */ + rslt = bme280_set_regs(®_addr, &soft_rst_cmd, 1, dev); - /* Proceed if null check is fine */ if (rslt == BME280_OK) { - /* Write the soft reset command in the sensor */ - rslt = bme280_set_regs(®_addr, &soft_rst_cmd, 1, dev); - - if (rslt == BME280_OK) + /* If NVM not copied yet, Wait for NVM to copy */ + do { - /* If NVM not copied yet, Wait for NVM to copy */ - do - { - /* As per data sheet - Table 1, startup time is 2 ms. */ - dev->delay_us(2000, dev->intf_ptr); - rslt = bme280_get_regs(BME280_STATUS_REG_ADDR, &status_reg, 1, dev); + /* As per data sheet - Table 1, startup time is 2 ms. */ + dev->delay_us(BME280_STARTUP_DELAY, dev->intf_ptr); + rslt = bme280_get_regs(BME280_REG_STATUS, &status_reg, 1, dev); - } while ((rslt == BME280_OK) && (try_run--) && (status_reg & BME280_STATUS_IM_UPDATE)); + } while ((rslt == BME280_OK) && (try_run--) && (status_reg & BME280_STATUS_IM_UPDATE)); - if (status_reg & BME280_STATUS_IM_UPDATE) - { - rslt = BME280_E_NVM_COPY_FAILED; - } + if (status_reg & BME280_STATUS_IM_UPDATE) + { + rslt = BME280_E_NVM_COPY_FAILED; } } @@ -744,21 +719,18 @@ int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data /* Array to store the pressure, temperature and humidity data read from * the sensor */ - uint8_t reg_data[BME280_P_T_H_DATA_LEN] = { 0 }; + uint8_t reg_data[BME280_LEN_P_T_H_DATA] = { 0 }; struct bme280_uncomp_data uncomp_data = { 0 }; - /* Check for null pointer in the device structure*/ - rslt = null_ptr_check(dev); - - if ((rslt == BME280_OK) && (comp_data != NULL)) + if (comp_data != NULL) { /* Read the pressure and temperature data from the sensor */ - rslt = bme280_get_regs(BME280_DATA_ADDR, reg_data, BME280_P_T_H_DATA_LEN, dev); + rslt = bme280_get_regs(BME280_REG_DATA, reg_data, BME280_LEN_P_T_H_DATA, dev); if (rslt == BME280_OK) { /* Parse the read data from the sensor */ - bme280_parse_sensor_data(reg_data, &uncomp_data); + parse_sensor_data(reg_data, &uncomp_data); /* Compensate the pressure and/or temperature and/or * humidity data from the sensor @@ -774,35 +746,6 @@ int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data return rslt; } -/*! - * @brief This API is used to parse the pressure, temperature and - * humidity data and store it in the bme280_uncomp_data structure instance. - */ -void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data) -{ - /* Variables to store the sensor data */ - uint32_t data_xlsb; - uint32_t data_lsb; - uint32_t data_msb; - - /* Store the parsed register values for pressure data */ - data_msb = (uint32_t)reg_data[0] << 12; - data_lsb = (uint32_t)reg_data[1] << 4; - data_xlsb = (uint32_t)reg_data[2] >> 4; - uncomp_data->pressure = data_msb | data_lsb | data_xlsb; - - /* Store the parsed register values for temperature data */ - data_msb = (uint32_t)reg_data[3] << 12; - data_lsb = (uint32_t)reg_data[4] << 4; - data_xlsb = (uint32_t)reg_data[5] >> 4; - uncomp_data->temperature = data_msb | data_lsb | data_xlsb; - - /* Store the parsed register values for humidity data */ - data_msb = (uint32_t)reg_data[6] << 8; - data_lsb = (uint32_t)reg_data[7]; - uncomp_data->humidity = data_msb | data_lsb; -} - /*! * @brief This API is used to compensate the pressure and/or * temperature and/or humidity data according to the component selected @@ -851,54 +794,64 @@ int8_t bme280_compensate_data(uint8_t sensor_comp, /*! * @brief This API is used to calculate the maximum delay in milliseconds required for the - * temperature/pressure/humidity(which ever at enabled) measurement to complete. + * temperature/pressure/humidity(whichever are enabled) measurement to complete. */ -uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings) +int8_t bme280_cal_meas_delay(uint32_t *max_delay, const struct bme280_settings *settings) { - uint32_t max_delay; + int8_t rslt = BME280_OK; uint8_t temp_osr; uint8_t pres_osr; uint8_t hum_osr; - /*Array to map OSR config register value to actual OSR */ + /* Array to map OSR config register value to actual OSR */ uint8_t osr_sett_to_act_osr[] = { 0, 1, 2, 4, 8, 16 }; - /* Mapping osr settings to the actual osr values e.g. 0b101 -> osr X16 */ - if (settings->osr_t <= 5) + if ((settings != NULL) && (max_delay != NULL)) { - temp_osr = osr_sett_to_act_osr[settings->osr_t]; + /* Mapping osr settings to the actual osr values e.g. 0b101 -> osr X16 */ + if (settings->osr_t <= BME280_OVERSAMPLING_16X) + { + temp_osr = osr_sett_to_act_osr[settings->osr_t]; + } + else + { + temp_osr = BME280_OVERSAMPLING_MAX; + } + + if (settings->osr_p <= BME280_OVERSAMPLING_16X) + { + pres_osr = osr_sett_to_act_osr[settings->osr_p]; + } + else + { + pres_osr = BME280_OVERSAMPLING_MAX; + } + + if (settings->osr_h <= BME280_OVERSAMPLING_16X) + { + hum_osr = osr_sett_to_act_osr[settings->osr_h]; + } + else + { + hum_osr = BME280_OVERSAMPLING_MAX; + } + + (*max_delay) = + (uint32_t)((BME280_MEAS_OFFSET + (BME280_MEAS_DUR * temp_osr) + + ((BME280_MEAS_DUR * pres_osr) + BME280_PRES_HUM_MEAS_OFFSET) + + ((BME280_MEAS_DUR * hum_osr) + BME280_PRES_HUM_MEAS_OFFSET))); } else { - temp_osr = 16; + rslt = BME280_E_NULL_PTR; } - if (settings->osr_p <= 5) - { - pres_osr = osr_sett_to_act_osr[settings->osr_p]; - } - else - { - pres_osr = 16; - } - - if (settings->osr_h <= 5) - { - hum_osr = osr_sett_to_act_osr[settings->osr_h]; - } - else - { - hum_osr = 16; - } - - max_delay = - (uint32_t)((BME280_MEAS_OFFSET + (BME280_MEAS_DUR * temp_osr) + - ((BME280_MEAS_DUR * pres_osr) + BME280_PRES_HUM_MEAS_OFFSET) + - ((BME280_MEAS_DUR * hum_osr) + BME280_PRES_HUM_MEAS_OFFSET)) / BME280_MEAS_SCALING_FACTOR); - - return max_delay; + return rslt; } +/****************************************************************************/ +/**\name INTERNAL APIs */ + /*! * @brief This internal API sets the oversampling settings for pressure, * temperature and humidity in the sensor. @@ -907,12 +860,12 @@ static int8_t set_osr_settings(uint8_t desired_settings, const struct bme280_set { int8_t rslt = BME280_W_INVALID_OSR_MACRO; - if (desired_settings & BME280_OSR_HUM_SEL) + if (desired_settings & BME280_SEL_OSR_HUM) { rslt = set_osr_humidity_settings(settings, dev); } - if (desired_settings & (BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL)) + if (desired_settings & (BME280_SEL_OSR_PRESS | BME280_SEL_OSR_TEMP)) { rslt = set_osr_press_temp_settings(desired_settings, settings, dev); } @@ -928,7 +881,7 @@ static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, int8_t rslt; uint8_t ctrl_hum; uint8_t ctrl_meas; - uint8_t reg_addr = BME280_CTRL_HUM_ADDR; + uint8_t reg_addr = BME280_REG_CTRL_HUM; ctrl_hum = settings->osr_h & BME280_CTRL_HUM_MSK; @@ -940,7 +893,7 @@ static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, */ if (rslt == BME280_OK) { - reg_addr = BME280_CTRL_MEAS_ADDR; + reg_addr = BME280_REG_CTRL_MEAS; rslt = bme280_get_regs(reg_addr, &ctrl_meas, 1, dev); if (rslt == BME280_OK) @@ -961,19 +914,19 @@ static int8_t set_osr_press_temp_settings(uint8_t desired_settings, struct bme280_dev *dev) { int8_t rslt; - uint8_t reg_addr = BME280_CTRL_MEAS_ADDR; + uint8_t reg_addr = BME280_REG_CTRL_MEAS; uint8_t reg_data; rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); if (rslt == BME280_OK) { - if (desired_settings & BME280_OSR_PRESS_SEL) + if (desired_settings & BME280_SEL_OSR_PRESS) { fill_osr_press_settings(®_data, settings); } - if (desired_settings & BME280_OSR_TEMP_SEL) + if (desired_settings & BME280_SEL_OSR_TEMP) { fill_osr_temp_settings(®_data, settings); } @@ -994,19 +947,19 @@ static int8_t set_filter_standby_settings(uint8_t desired_settings, struct bme280_dev *dev) { int8_t rslt; - uint8_t reg_addr = BME280_CONFIG_ADDR; + uint8_t reg_addr = BME280_REG_CONFIG; uint8_t reg_data; rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); if (rslt == BME280_OK) { - if (desired_settings & BME280_FILTER_SEL) + if (desired_settings & BME280_SEL_FILTER) { fill_filter_settings(®_data, settings); } - if (desired_settings & BME280_STANDBY_SEL) + if (desired_settings & BME280_SEL_STANDBY) { fill_standby_settings(®_data, settings); } @@ -1057,7 +1010,7 @@ static void fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settin /*! * @brief This internal API parse the oversampling(pressure, temperature * and humidity), filter and standby duration settings and store in the - * device structure. + * bme280_settings structure. */ static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings) { @@ -1068,13 +1021,42 @@ static void parse_device_settings(const uint8_t *reg_data, struct bme280_setting settings->standby_time = BME280_GET_BITS(reg_data[3], BME280_STANDBY); } +/*! + * @brief This API is used to parse the pressure, temperature and + * humidity data and store it in the bme280_uncomp_data structure instance. + */ +static void parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data) +{ + /* Variables to store the sensor data */ + uint32_t data_xlsb; + uint32_t data_lsb; + uint32_t data_msb; + + /* Store the parsed register values for pressure data */ + data_msb = (uint32_t)reg_data[0] << BME280_12_BIT_SHIFT; + data_lsb = (uint32_t)reg_data[1] << BME280_4_BIT_SHIFT; + data_xlsb = (uint32_t)reg_data[2] >> BME280_4_BIT_SHIFT; + uncomp_data->pressure = data_msb | data_lsb | data_xlsb; + + /* Store the parsed register values for temperature data */ + data_msb = (uint32_t)reg_data[3] << BME280_12_BIT_SHIFT; + data_lsb = (uint32_t)reg_data[4] << BME280_4_BIT_SHIFT; + data_xlsb = (uint32_t)reg_data[5] >> BME280_4_BIT_SHIFT; + uncomp_data->temperature = data_msb | data_lsb | data_xlsb; + + /* Store the parsed register values for humidity data */ + data_msb = (uint32_t)reg_data[6] << BME280_8_BIT_SHIFT; + data_lsb = (uint32_t)reg_data[7]; + uncomp_data->humidity = data_msb | data_lsb; +} + /*! * @brief This internal API writes the power mode in the sensor. */ static int8_t write_power_mode(uint8_t sensor_mode, struct bme280_dev *dev) { int8_t rslt; - uint8_t reg_addr = BME280_PWR_CTRL_ADDR; + uint8_t reg_addr = BME280_REG_PWR_CTRL; /* Variable to store the value read from power mode register */ uint8_t sensor_mode_reg_val; @@ -1103,7 +1085,7 @@ static int8_t put_device_to_sleep(struct bme280_dev *dev) uint8_t reg_data[4]; struct bme280_settings settings; - rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); + rslt = bme280_get_regs(BME280_REG_CTRL_HUM, reg_data, 4, dev); if (rslt == BME280_OK) { @@ -1127,17 +1109,17 @@ static int8_t reload_device_settings(const struct bme280_settings *settings, str { int8_t rslt; - rslt = set_osr_settings(BME280_ALL_SETTINGS_SEL, settings, dev); + rslt = set_osr_settings(BME280_SEL_ALL_SETTINGS, settings, dev); if (rslt == BME280_OK) { - rslt = set_filter_standby_settings(BME280_ALL_SETTINGS_SEL, settings, dev); + rslt = set_filter_standby_settings(BME280_SEL_ALL_SETTINGS, settings, dev); } return rslt; } -#ifdef BME280_FLOAT_ENABLE +#ifdef BME280_DOUBLE_ENABLE /*! * @brief This internal API is used to compensate the raw temperature data and @@ -1151,7 +1133,7 @@ static double compensate_temperature(const struct bme280_uncomp_data *uncomp_dat double temperature_min = -40; double temperature_max = 85; - var1 = ((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_t1) / 1024.0; + var1 = (((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_t1) / 1024.0); var1 = var1 * ((double)calib_data->dig_t2); var2 = (((double)uncomp_data->temperature) / 131072.0 - ((double)calib_data->dig_t1) / 8192.0); var2 = (var2 * var2) * ((double)calib_data->dig_t3); @@ -1192,7 +1174,7 @@ static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data, var1 = (var3 + ((double)calib_data->dig_p2) * var1) / 524288.0; var1 = (1.0 + var1 / 32768.0) * ((double)calib_data->dig_p1); - /* avoid exception caused by division by zero */ + /* Avoid exception caused by division by zero */ if (var1 > (0.0)) { pressure = 1048576.0 - (double) uncomp_data->pressure; @@ -1368,7 +1350,7 @@ static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data var1 = (var3 + var4) / 262144; var1 = (((32768 + var1)) * ((int32_t)calib_data->dig_p1)) / 32768; - /* avoid exception caused by division by zero */ + /* Avoid exception caused by division by zero */ if (var1) { var5 = (uint32_t)((uint32_t)1048576) - uncomp_data->pressure; @@ -1452,13 +1434,13 @@ static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data static int8_t get_calib_data(struct bme280_dev *dev) { int8_t rslt; - uint8_t reg_addr = BME280_TEMP_PRESS_CALIB_DATA_ADDR; + uint8_t reg_addr = BME280_REG_TEMP_PRESS_CALIB_DATA; /* Array to store calibration data */ - uint8_t calib_data[BME280_TEMP_PRESS_CALIB_DATA_LEN] = { 0 }; + uint8_t calib_data[BME280_LEN_TEMP_PRESS_CALIB_DATA] = { 0 }; /* Read the calibration data from the sensor */ - rslt = bme280_get_regs(reg_addr, calib_data, BME280_TEMP_PRESS_CALIB_DATA_LEN, dev); + rslt = bme280_get_regs(reg_addr, calib_data, BME280_LEN_TEMP_PRESS_CALIB_DATA, dev); if (rslt == BME280_OK) { @@ -1466,10 +1448,10 @@ static int8_t get_calib_data(struct bme280_dev *dev) * it in device structure */ parse_temp_press_calib_data(calib_data, dev); - reg_addr = BME280_HUMIDITY_CALIB_DATA_ADDR; + reg_addr = BME280_REG_HUMIDITY_CALIB_DATA; /* Read the humidity calibration data from the sensor */ - rslt = bme280_get_regs(reg_addr, calib_data, BME280_HUMIDITY_CALIB_DATA_LEN, dev); + rslt = bme280_get_regs(reg_addr, calib_data, BME280_LEN_HUMIDITY_CALIB_DATA, dev); if (rslt == BME280_OK) { @@ -1487,9 +1469,9 @@ static int8_t get_calib_data(struct bme280_dev *dev) * @brief This internal API interleaves the register address between the * register data buffer for burst write operation. */ -static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len) +static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint32_t len) { - uint8_t index; + uint32_t index; for (index = 1; index < len; index++) { diff --git a/bme280.h b/bme280.h index fd95990..d0b06f0 100644 --- a/bme280.h +++ b/bme280.h @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme280.h -* @date 2020-03-28 -* @version v3.5.0 +* @date 2020-12-17 +* @version v3.5.1 * */ @@ -46,8 +46,8 @@ * and Sensor API Source Code */ -#ifndef BME280_H_ -#define BME280_H_ +#ifndef _BME280_H +#define _BME280_H /*! CPP guard */ #ifdef __cplusplus @@ -94,7 +94,7 @@ int8_t bme280_init(struct bme280_dev *dev); * \ingroup bme280ApiRegister * \page bme280_api_bme280_set_regs bme280_set_regs * \code - * int8_t bme280_set_regs(const uint8_t reg_addr, const uint8_t *reg_data, uint8_t len, struct bme280_dev *dev); + * int8_t bme280_set_regs(const uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bme280_dev *dev); * \endcode * @details This API writes the given data to the register address of the sensor * @@ -111,13 +111,13 @@ int8_t bme280_init(struct bme280_dev *dev); * @retval < 0 -> Fail. * */ -int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme280_dev *dev); +int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bme280_dev *dev); /*! * \ingroup bme280ApiRegister * \page bme280_api_bme280_get_regs bme280_get_regs * \code - * int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, struct bme280_dev *dev); + * int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme280_dev *dev); * \endcode * @details This API reads the data from the given register address of sensor. * @@ -133,7 +133,7 @@ int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, * @retval < 0 -> Fail. * */ -int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme280_dev *dev); +int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bme280_dev *dev); /** * \ingroup bme280 @@ -145,26 +145,29 @@ int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct * \ingroup bme280ApiSensorSettings * \page bme280_api_bme280_set_sensor_settings bme280_set_sensor_settings * \code - * int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev); + * int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_settings *settings, struct bme280_dev *dev); * \endcode * @details This API sets the oversampling, filter and standby duration * (normal mode) settings in the sensor. * - * @param[in] dev : Structure instance of bme280_dev. - * @param[in] desired_settings : Variable used to select the settings which - * are to be set in the sensor. + * @param[in] desired_settings : Variable used to select the settings which + * are to be set in the sensor. + * @param[in] settings : Structure instance of bme280_settings. + * @param[in] dev : Structure instance of bme280_dev. * * @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. * - * Macros | Functionality + *@verbatim + * Macros | Functionality * -----------------------|---------------------------------------------- - * BME280_OSR_PRESS_SEL | To set pressure oversampling. - * BME280_OSR_TEMP_SEL | To set temperature oversampling. - * BME280_OSR_HUM_SEL | To set humidity oversampling. - * BME280_FILTER_SEL | To set filter setting. - * BME280_STANDBY_SEL | To set standby duration setting. + * BME280_SEL_OSR_PRESS | To set pressure oversampling. + * BME280_SEL_OSR_TEMP | To set temperature oversampling. + * BME280_SEL_OSR_HUM | To set humidity oversampling. + * BME280_SEL_FILTER | To set filter setting. + * BME280_SEL_STANDBY | To set standby duration setting. + *@endverbatim * * @return Result of API execution status * @@ -173,18 +176,21 @@ int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct * @retval < 0 -> Fail. * */ -int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *dev); +int8_t bme280_set_sensor_settings(uint8_t desired_settings, + const struct bme280_settings *settings, + struct bme280_dev *dev); /*! * \ingroup bme280ApiSensorSettings * \page bme280_api_bme280_get_sensor_settings bme280_get_sensor_settings * \code - * int8_t bme280_get_sensor_settings(struct bme280_dev *dev); + * int8_t bme280_get_sensor_settings(struct bme280_settings *settings, struct bme280_dev *dev); * \endcode * @details This API gets the oversampling, filter and standby duration * (normal mode) settings from the sensor. * - * @param[in,out] dev : Structure instance of bme280_dev. + * @param[in] settings : Structure instance of bme280_settings. + * @param[in,out] dev : Structure instance of bme280_dev. * * @return Result of API execution status * @@ -193,7 +199,7 @@ int8_t bme280_set_sensor_settings(uint8_t desired_settings, struct bme280_dev *d * @retval < 0 -> Fail. * */ -int8_t bme280_get_sensor_settings(struct bme280_dev *dev); +int8_t bme280_get_sensor_settings(struct bme280_settings *settings, struct bme280_dev *dev); /** * \ingroup bme280 @@ -209,14 +215,16 @@ int8_t bme280_get_sensor_settings(struct bme280_dev *dev); * \endcode * @details This API sets the power mode of the sensor. * - * @param[in] dev : Structure instance of bme280_dev. * @param[in] sensor_mode : Variable which contains the power mode to be set. + * @param[in] dev : Structure instance of bme280_dev. * - * sensor_mode | Macros - * ---------------------|------------------- - * 0 | BME280_SLEEP_MODE - * 1 | BME280_FORCED_MODE - * 3 | BME280_NORMAL_MODE + *@verbatim + * sensor_mode | Macros + * ---------------------|------------------------- + * 0 | BME280_POWERMODE_SLEEP + * 1 | BME280_POWERMODE_FORCED + * 3 | BME280_POWERMODE_NORMAL + *@endverbatim * * @return Result of API execution status * @@ -231,18 +239,20 @@ int8_t bme280_set_sensor_mode(uint8_t sensor_mode, struct bme280_dev *dev); * \ingroup bme280ApiSensorMode * \page bme280_api_bme280_get_sensor_mode bme280_get_sensor_mode * \code - * int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev); + * int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, struct bme280_dev *dev); * \endcode * @details This API gets the power mode of the sensor. * - * @param[in] dev : Structure instance of bme280_dev. * @param[out] sensor_mode : Pointer variable to store the power mode. + * @param[in] dev : Structure instance of bme280_dev. * - * sensor_mode | Macros - * ---------------------|------------------- - * 0 | BME280_SLEEP_MODE - * 1 | BME280_FORCED_MODE - * 3 | BME280_NORMAL_MODE + *@verbatim + * sensor_mode | Macros + * ---------------------|------------------------- + * 0 | BME280_POWERMODE_SLEEP + * 1 | BME280_POWERMODE_FORCED + * 3 | BME280_POWERMODE_NORMAL + *@endverbatim * * @return Result of API execution status * @@ -297,15 +307,17 @@ int8_t bme280_soft_reset(struct bme280_dev *dev); * @param[in] sensor_comp : Variable which selects which data to be read from * the sensor. * + *@verbatim * sensor_comp | Macros * ------------|------------------- * 1 | BME280_PRESS * 2 | BME280_TEMP * 4 | BME280_HUM * 7 | BME280_ALL + *@endverbatim * * @param[out] comp_data : Structure instance of bme280_data. - * @param[in] dev : Structure instance of bme280_dev. + * @param[in] dev : Structure instance of bme280_dev. * * @return Result of API execution status * @@ -316,22 +328,6 @@ int8_t bme280_soft_reset(struct bme280_dev *dev); */ int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev); -/*! - * \ingroup bme280ApiSensorData - * \page bme280_api_bme280_parse_sensor_data bme280_parse_sensor_data - * \code - * void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data); - * \endcode - * @details This API is used to parse the pressure, temperature and - * humidity data and store it in the bme280_uncomp_data structure instance. - * - * @param[in] reg_data : Contains register data which needs to be parsed - * @param[out] uncomp_data : Contains the uncompensated pressure, temperature - * and humidity data. - * - */ -void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data); - /*! * \ingroup bme280ApiSensorData * \page bme280_api_bme280_compensate_data bme280_compensate_data @@ -346,12 +342,12 @@ void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data * user. * * @param[in] sensor_comp : Used to select pressure and/or temperature and/or - * humidity. + * humidity. * @param[in] uncomp_data : Contains the uncompensated pressure, temperature and - * humidity data. - * @param[out] comp_data : Contains the compensated pressure and/or temperature - * and/or humidity data. - * @param[in] calib_data : Pointer to the calibration data structure. + * humidity data. + * @param[out] comp_data : Contains the compensated pressure and/or temperature + * and/or humidity data. + * @param[in] calib_data : Pointer to bme280_calib_data * * @return Result of API execution status. * @@ -375,21 +371,27 @@ int8_t bme280_compensate_data(uint8_t sensor_comp, * \ingroup bme280ApiSensorDelay * \page bme280_api_bme280_cal_meas_delay bme280_cal_meas_delay * \code - * uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings); + * uint32_t bme280_cal_meas_delay(uint32_t *max_delay, const struct bme280_settings *settings); * \endcode - * @brief This API is used to calculate the maximum delay in milliseconds required for the - * temperature/pressure/humidity(which ever are enabled) measurement to complete. + * + * @details This API is used to calculate the maximum delay in microseconds required for the + * temperature/pressure/humidity(whichever are enabled) measurement to complete. * The delay depends upon the number of sensors enabled and their oversampling configuration. * - * @param[in] settings : contains the oversampling configurations. + * @param[out] max_delay : Delay required in microseconds. + * @param[in] settings : Contains the oversampling configurations. * - * @return delay required in milliseconds. + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval > 0 -> Warning. + * @retval < 0 -> Fail. * */ -uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings); +int8_t bme280_cal_meas_delay(uint32_t *max_delay, const struct bme280_settings *settings); #ifdef __cplusplus } #endif /* End of CPP guard */ -#endif /* BME280_H_ */ +#endif /* _BME280_H */ /** @}*/ diff --git a/bme280_defs.h b/bme280_defs.h index 686ba6a..43d86d1 100644 --- a/bme280_defs.h +++ b/bme280_defs.h @@ -31,13 +31,13 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme280_defs.h -* @date 2020-03-28 -* @version v3.5.0 +* @date 2020-12-17 +* @version v3.5.1 * */ -#ifndef BME280_DEFS_H_ -#define BME280_DEFS_H_ +#ifndef _BME280_DEFS_H +#define _BME280_DEFS_H /********************************************************/ /* header includes */ @@ -83,16 +83,20 @@ #endif #endif -/********************************************************/ - +/******************************************************************************/ +/*! @name Compiler switch macros Definitions */ +/******************************************************************************/ #ifndef BME280_64BIT_ENABLE /*< Check if 64-bit integer (using BME280_64BIT_ENABLE) is enabled */ #ifndef BME280_32BIT_ENABLE /*< Check if 32-bit integer (using BME280_32BIT_ENABLE) is enabled */ -#ifndef BME280_FLOAT_ENABLE /*< If any of the integer data types not enabled then enable BME280_FLOAT_ENABLE */ -#define BME280_FLOAT_ENABLE +#ifndef BME280_DOUBLE_ENABLE /*< If any of the integer data types not enabled then enable BME280_DOUBLE_ENABLE */ +#define BME280_DOUBLE_ENABLE #endif #endif #endif +/******************************************************************************/ +/*! @name General Macro Definitions */ +/******************************************************************************/ #ifndef TRUE #define TRUE UINT8_C(1) #endif @@ -100,96 +104,73 @@ #define FALSE UINT8_C(0) #endif -/** +/*! * BME280_INTF_RET_TYPE is the read/write interface return type which can be overwritten by the build system. */ #ifndef BME280_INTF_RET_TYPE #define BME280_INTF_RET_TYPE int8_t #endif -/** +/*! * The last error code from read/write interface is stored in the device structure as intf_rslt. */ #ifndef BME280_INTF_RET_SUCCESS #define BME280_INTF_RET_SUCCESS INT8_C(0) #endif -/**\name I2C addresses */ -#define BME280_I2C_ADDR_PRIM UINT8_C(0x76) -#define BME280_I2C_ADDR_SEC UINT8_C(0x77) - -/**\name BME280 chip identifier */ -#define BME280_CHIP_ID UINT8_C(0x60) - -/**\name Register Address */ -#define BME280_CHIP_ID_ADDR UINT8_C(0xD0) -#define BME280_RESET_ADDR UINT8_C(0xE0) -#define BME280_TEMP_PRESS_CALIB_DATA_ADDR UINT8_C(0x88) -#define BME280_HUMIDITY_CALIB_DATA_ADDR UINT8_C(0xE1) -#define BME280_PWR_CTRL_ADDR UINT8_C(0xF4) -#define BME280_CTRL_HUM_ADDR UINT8_C(0xF2) -#define BME280_CTRL_MEAS_ADDR UINT8_C(0xF4) -#define BME280_CONFIG_ADDR UINT8_C(0xF5) -#define BME280_DATA_ADDR UINT8_C(0xF7) - -/**\name API success code */ +/*! @name API success code */ #define BME280_OK INT8_C(0) -/**\name API error codes */ +/*! @name API error codes */ #define BME280_E_NULL_PTR INT8_C(-1) -#define BME280_E_DEV_NOT_FOUND INT8_C(-2) +#define BME280_E_COMM_FAIL INT8_C(-2) #define BME280_E_INVALID_LEN INT8_C(-3) -#define BME280_E_COMM_FAIL INT8_C(-4) +#define BME280_E_DEV_NOT_FOUND INT8_C(-4) #define BME280_E_SLEEP_MODE_FAIL INT8_C(-5) #define BME280_E_NVM_COPY_FAILED INT8_C(-6) -/**\name API warning codes */ +/*! @name API warning codes */ #define BME280_W_INVALID_OSR_MACRO INT8_C(1) -/**\name Macros related to size */ -#define BME280_TEMP_PRESS_CALIB_DATA_LEN UINT8_C(26) -#define BME280_HUMIDITY_CALIB_DATA_LEN UINT8_C(7) -#define BME280_P_T_H_DATA_LEN UINT8_C(8) +/*! @name BME280 chip identifier */ +#define BME280_CHIP_ID UINT8_C(0x60) -/**\name Sensor power modes */ -#define BME280_SLEEP_MODE UINT8_C(0x00) -#define BME280_FORCED_MODE UINT8_C(0x01) -#define BME280_NORMAL_MODE UINT8_C(0x03) +/*! @name I2C addresses */ +#define BME280_I2C_ADDR_PRIM UINT8_C(0x76) +#define BME280_I2C_ADDR_SEC UINT8_C(0x77) -/**\name Macro to combine two 8 bit data's to form a 16 bit data */ -#define BME280_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) +/*! @name Register Address */ +#define BME280_REG_CHIP_ID UINT8_C(0xD0) +#define BME280_REG_RESET UINT8_C(0xE0) +#define BME280_REG_TEMP_PRESS_CALIB_DATA UINT8_C(0x88) +#define BME280_REG_HUMIDITY_CALIB_DATA UINT8_C(0xE1) +#define BME280_REG_CTRL_HUM UINT8_C(0xF2) +#define BME280_REG_STATUS UINT8_C(0xF3) +#define BME280_REG_PWR_CTRL UINT8_C(0xF4) +#define BME280_REG_CTRL_MEAS UINT8_C(0xF4) +#define BME280_REG_CONFIG UINT8_C(0xF5) +#define BME280_REG_DATA UINT8_C(0xF7) -#define BME280_SET_BITS(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | \ - ((data << bitname##_POS) & bitname##_MSK)) -#define BME280_SET_BITS_POS_0(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | \ - (data & bitname##_MSK)) +/*! @name Macros related to size */ +#define BME280_LEN_TEMP_PRESS_CALIB_DATA UINT8_C(26) +#define BME280_LEN_HUMIDITY_CALIB_DATA UINT8_C(7) +#define BME280_LEN_P_T_H_DATA UINT8_C(8) -#define BME280_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ - (bitname##_POS)) -#define BME280_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) +/*! @name Sensor power modes */ +#define BME280_POWERMODE_SLEEP UINT8_C(0x00) +#define BME280_POWERMODE_FORCED UINT8_C(0x01) +#define BME280_POWERMODE_NORMAL UINT8_C(0x03) -/**\name Macros for bit masking */ #define BME280_SENSOR_MODE_MSK UINT8_C(0x03) #define BME280_SENSOR_MODE_POS UINT8_C(0x00) -#define BME280_CTRL_HUM_MSK UINT8_C(0x07) -#define BME280_CTRL_HUM_POS UINT8_C(0x00) +/*! @name Soft reset command */ +#define BME280_SOFT_RESET_COMMAND UINT8_C(0xB6) -#define BME280_CTRL_PRESS_MSK UINT8_C(0x1C) -#define BME280_CTRL_PRESS_POS UINT8_C(0x02) +#define BME280_STATUS_IM_UPDATE UINT8_C(0x01) +#define BME280_STATUS_MEAS_DONE UINT8_C(0x08) -#define BME280_CTRL_TEMP_MSK UINT8_C(0xE0) -#define BME280_CTRL_TEMP_POS UINT8_C(0x05) - -#define BME280_FILTER_MSK UINT8_C(0x1C) -#define BME280_FILTER_POS UINT8_C(0x02) - -#define BME280_STANDBY_MSK UINT8_C(0xE0) -#define BME280_STANDBY_POS UINT8_C(0x05) - -/**\name Sensor component selection macros +/*! @name Sensor component selection macros * These values are internal for API implementation. Don't relate this to * data sheet. */ @@ -198,29 +179,41 @@ #define BME280_HUM UINT8_C(1 << 2) #define BME280_ALL UINT8_C(0x07) -/**\name Settings selection macros */ -#define BME280_OSR_PRESS_SEL UINT8_C(1) -#define BME280_OSR_TEMP_SEL UINT8_C(1 << 1) -#define BME280_OSR_HUM_SEL UINT8_C(1 << 2) -#define BME280_FILTER_SEL UINT8_C(1 << 3) -#define BME280_STANDBY_SEL UINT8_C(1 << 4) -#define BME280_ALL_SETTINGS_SEL UINT8_C(0x1F) +/*! @name Settings selection macros */ +#define BME280_SEL_OSR_PRESS UINT8_C(1) +#define BME280_SEL_OSR_TEMP UINT8_C(1 << 1) +#define BME280_SEL_OSR_HUM UINT8_C(1 << 2) +#define BME280_SEL_FILTER UINT8_C(1 << 3) +#define BME280_SEL_STANDBY UINT8_C(1 << 4) +#define BME280_SEL_ALL_SETTINGS UINT8_C(0x1F) -/**\name Oversampling macros */ +/*! @name Oversampling macros */ #define BME280_NO_OVERSAMPLING UINT8_C(0x00) #define BME280_OVERSAMPLING_1X UINT8_C(0x01) #define BME280_OVERSAMPLING_2X UINT8_C(0x02) #define BME280_OVERSAMPLING_4X UINT8_C(0x03) #define BME280_OVERSAMPLING_8X UINT8_C(0x04) #define BME280_OVERSAMPLING_16X UINT8_C(0x05) +#define BME280_OVERSAMPLING_MAX UINT8_C(16) -/**\name Measurement delay calculation macros */ +#define BME280_CTRL_HUM_MSK UINT8_C(0x07) +#define BME280_CTRL_HUM_POS UINT8_C(0x00) +#define BME280_CTRL_PRESS_MSK UINT8_C(0x1C) +#define BME280_CTRL_PRESS_POS UINT8_C(0x02) +#define BME280_CTRL_TEMP_MSK UINT8_C(0xE0) +#define BME280_CTRL_TEMP_POS UINT8_C(0x05) + +/*! @name Measurement delay calculation macros */ #define BME280_MEAS_OFFSET UINT16_C(1250) #define BME280_MEAS_DUR UINT16_C(2300) #define BME280_PRES_HUM_MEAS_OFFSET UINT16_C(575) #define BME280_MEAS_SCALING_FACTOR UINT16_C(1000) +#define BME280_STARTUP_DELAY UINT16_C(2000) -/**\name Standby duration selection macros */ +/*! @name Length macros */ +#define BME280_MAX_LEN UINT8_C(10) + +/*! @name Standby duration selection macros */ #define BME280_STANDBY_TIME_0_5_MS (0x00) #define BME280_STANDBY_TIME_62_5_MS (0x01) #define BME280_STANDBY_TIME_125_MS (0x02) @@ -230,40 +223,65 @@ #define BME280_STANDBY_TIME_10_MS (0x06) #define BME280_STANDBY_TIME_20_MS (0x07) -/**\name Filter coefficient selection macros */ +#define BME280_STANDBY_MSK UINT8_C(0xE0) +#define BME280_STANDBY_POS UINT8_C(0x05) + +/*! @name Bit shift macros */ +#define BME280_12_BIT_SHIFT UINT8_C(12) +#define BME280_8_BIT_SHIFT UINT8_C(8) +#define BME280_4_BIT_SHIFT UINT8_C(4) + +/*! @name Filter coefficient selection macros */ #define BME280_FILTER_COEFF_OFF (0x00) #define BME280_FILTER_COEFF_2 (0x01) #define BME280_FILTER_COEFF_4 (0x02) #define BME280_FILTER_COEFF_8 (0x03) #define BME280_FILTER_COEFF_16 (0x04) -#define BME280_STATUS_REG_ADDR (0xF3) -#define BME280_SOFT_RESET_COMMAND (0xB6) -#define BME280_STATUS_IM_UPDATE (0x01) +#define BME280_FILTER_MSK UINT8_C(0x1C) +#define BME280_FILTER_POS UINT8_C(0x02) + +/*! @name Macro to combine two 8 bit data's to form a 16 bit data */ +#define BME280_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) + +/*! @name Macro to SET and GET BITS of a register */ +#define BME280_SET_BITS(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + ((data << bitname##_POS) & bitname##_MSK)) + +#define BME280_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +#define BME280_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ + (bitname##_POS)) +#define BME280_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/********************************************************/ /*! * @brief Interface selection Enums */ enum bme280_intf { - /*< SPI interface */ + /*! SPI interface */ BME280_SPI_INTF, - /*< I2C interface */ + /*! I2C interface */ BME280_I2C_INTF }; -/*! - * @brief Type definitions - */ +/******************************************************************************/ +/*! @name Function Pointers */ +/******************************************************************************/ /*! * @brief Bus communication function pointer which should be mapped to * the platform specific read functions of the user * * @param[in] reg_addr : Register address from which data is read. - * @param[out] reg_data : Pointer to data buffer where read data is stored. + * @param[out] reg_data : Pointer to data buffer where read data is stored. * @param[in] len : Number of bytes of data to be read. * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs. + * for interface related call backs. * * @retval 0 -> Success. * @retval Non zero value -> Fail. @@ -276,7 +294,7 @@ typedef BME280_INTF_RET_TYPE (*bme280_read_fptr_t)(uint8_t reg_addr, uint8_t *re * the platform specific write functions of the user * * @param[in] reg_addr : Register address to which the data is written. - * @param[in] reg_data : Pointer to data buffer in which data to be written + * @param[in] reg_data : Pointer to data buffer in which data to be written * is stored. * @param[in] len : Number of bytes of data to be written. * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors @@ -300,66 +318,70 @@ typedef BME280_INTF_RET_TYPE (*bme280_write_fptr_t)(uint8_t reg_addr, const uint */ typedef void (*bme280_delay_us_fptr_t)(uint32_t period, void *intf_ptr); +/******************************************************************************/ +/*! @name Structure Declarations */ +/******************************************************************************/ + /*! * @brief Calibration data */ struct bme280_calib_data { - /*< Calibration coefficient for the temperature sensor */ + /*! Calibration coefficient for the temperature sensor */ uint16_t dig_t1; - /*< Calibration coefficient for the temperature sensor */ + /*! Calibration coefficient for the temperature sensor */ int16_t dig_t2; - /*< Calibration coefficient for the temperature sensor */ + /*! Calibration coefficient for the temperature sensor */ int16_t dig_t3; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ uint16_t dig_p1; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p2; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p3; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p4; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p5; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p6; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p7; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p8; - /*< Calibration coefficient for the pressure sensor */ + /*! Calibration coefficient for the pressure sensor */ int16_t dig_p9; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ uint8_t dig_h1; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ int16_t dig_h2; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ uint8_t dig_h3; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ int16_t dig_h4; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ int16_t dig_h5; - /*< Calibration coefficient for the humidity sensor */ + /*! Calibration coefficient for the humidity sensor */ int8_t dig_h6; - /*< Variable to store the intermediate temperature coefficient */ + /*! Variable to store the intermediate temperature coefficient */ int32_t t_fine; }; @@ -367,28 +389,28 @@ struct bme280_calib_data * @brief bme280 sensor structure which comprises of temperature, pressure and * humidity data */ -#ifdef BME280_FLOAT_ENABLE +#ifdef BME280_DOUBLE_ENABLE struct bme280_data { - /*< Compensated pressure */ + /*! Compensated pressure */ double pressure; - /*< Compensated temperature */ + /*! Compensated temperature */ double temperature; - /*< Compensated humidity */ + /*! Compensated humidity */ double humidity; }; #else struct bme280_data { - /*< Compensated pressure */ + /*! Compensated pressure */ uint32_t pressure; - /*< Compensated temperature */ + /*! Compensated temperature */ int32_t temperature; - /*< Compensated humidity */ + /*! Compensated humidity */ uint32_t humidity; }; #endif /*! BME280_USE_FLOATING_POINT */ @@ -399,13 +421,13 @@ struct bme280_data */ struct bme280_uncomp_data { - /*< un-compensated pressure */ + /*! Un-compensated pressure */ uint32_t pressure; - /*< un-compensated temperature */ + /*! Un-compensated temperature */ uint32_t temperature; - /*< un-compensated humidity */ + /*! Un-compensated humidity */ uint32_t humidity; }; @@ -415,19 +437,19 @@ struct bme280_uncomp_data */ struct bme280_settings { - /*< pressure oversampling */ + /*! Pressure oversampling */ uint8_t osr_p; - /*< temperature oversampling */ + /*! Temperature oversampling */ uint8_t osr_t; - /*< humidity oversampling */ + /*! Humidity oversampling */ uint8_t osr_h; - /*< filter coefficient */ + /*! Filter coefficient */ uint8_t filter; - /*< standby time */ + /*! Standby time */ uint8_t standby_time; }; @@ -436,35 +458,37 @@ struct bme280_settings */ struct bme280_dev { - /*< Chip Id */ + /*! Chip Id */ uint8_t chip_id; - /*< Interface function pointer used to enable the device address for I2C and chip selection for SPI */ - void *intf_ptr; - - /*< Interface Selection + /*! Interface Selection * For SPI, intf = BME280_SPI_INTF * For I2C, intf = BME280_I2C_INTF - * */ + */ enum bme280_intf intf; - /*< Read function pointer */ + /*! + * The interface pointer is used to enable the user + * to link their interface descriptors for reference during the + * implementation of the read and write interfaces to the + * hardware. + */ + void *intf_ptr; + + /*! Variable to store result of read/write function */ + BME280_INTF_RET_TYPE intf_rslt; + + /*! Read function pointer */ bme280_read_fptr_t read; - /*< Write function pointer */ + /*! Write function pointer */ bme280_write_fptr_t write; - /*< Delay function pointer */ + /*! Delay function pointer */ bme280_delay_us_fptr_t delay_us; - /*< Trim data */ + /*! Trim data */ struct bme280_calib_data calib_data; - - /*< Sensor settings */ - struct bme280_settings settings; - - /*< Variable to store result of read/write function */ - BME280_INTF_RET_TYPE intf_rslt; }; -#endif /* BME280_DEFS_H_ */ +#endif /* _BME280_DEFS_H */ diff --git a/examples/Makefile b/examples/Makefile deleted file mode 100644 index a32ac6f..0000000 --- a/examples/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -raspbian: - gcc linux_userspace.c ../bme280.c -I ../ -lwiringPi -o bme280 - -bsd: - cc bsd_userspace.c ../bme280.c -I ../ -o bme280 - -clean: - rm -v bme280 diff --git a/examples/common/common.c b/examples/common/common.c new file mode 100644 index 0000000..36c5834 --- /dev/null +++ b/examples/common/common.c @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "coines.h" +#include "bme280.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +#define BME280_SHUTTLE_ID UINT8_C(0x33) + +/******************************************************************************/ +/*! Static variable definition */ + +/*! Variable that holds the I2C device address or SPI chip selection */ +static uint8_t dev_addr; + +/******************************************************************************/ +/*! User interface functions */ + +/*! + * I2C read function map to COINES platform + */ +BME280_INTF_RET_TYPE bme280_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_i2c(COINES_I2C_BUS_0, dev_addr, reg_addr, reg_data, (uint16_t)length); +} + +/*! + * I2C write function map to COINES platform + */ +BME280_INTF_RET_TYPE bme280_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_i2c(COINES_I2C_BUS_0, dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)length); +} + +/*! + * SPI read function map to COINES platform + */ +BME280_INTF_RET_TYPE bme280_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_spi(COINES_SPI_BUS_0, dev_addr, reg_addr, reg_data, (uint16_t)length); +} + +/*! + * SPI write function map to COINES platform + */ +BME280_INTF_RET_TYPE bme280_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_spi(COINES_SPI_BUS_0, dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)length); +} + +/*! + * Delay function map to COINES platform + */ +void bme280_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +void bme280_error_codes_print_result(const char api_name[], int8_t rslt) +{ + if (rslt != BME280_OK) + { + printf("%s\t", api_name); + + switch (rslt) + { + case BME280_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BME280_E_COMM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BME280_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BME280_E_INVALID_LEN: + printf("Error [%d] : Invalid length error. It occurs when write is done with invalid length\r\n", rslt); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} + +/*! + * @brief Function to select the interface between SPI and I2C. + */ +int8_t bme280_interface_selection(struct bme280_dev *dev, uint8_t intf) +{ + int8_t rslt = BME280_OK; + struct coines_board_info board_info; + + if (dev != NULL) + { + int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB, NULL); + + if (result < COINES_SUCCESS) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(result); + } + + result = coines_get_board_info(&board_info); + +#if defined(PC) + setbuf(stdout, NULL); +#endif + + if (COINES_SUCCESS != result) + { + printf("\n Unable to retrieve board information ! \n"); + exit(COINES_E_FAILURE); + } + + if ((board_info.shuttle_id != BME280_SHUTTLE_ID)) + { + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Bus configuration : I2C */ + if (intf == BME280_I2C_INTF) + { + printf("I2C Interface\n"); + + dev_addr = BME280_I2C_ADDR_PRIM; + dev->read = bme280_i2c_read; + dev->write = bme280_i2c_write; + dev->intf = BME280_I2C_INTF; + /* SDO pin is made low*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_SDO, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* set the sensor interface as I2C with 100kHz speed */ + result = coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); + } + /* Bus configuration : SPI */ + else if (intf == BME280_SPI_INTF) + { + printf("SPI Interface\n"); + + dev_addr = COINES_SHUTTLE_PIN_7; + dev->read = bme280_spi_read; + dev->write = bme280_spi_write; + dev->intf = BME280_SPI_INTF; + + result = coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); + } + + if(result != COINES_SUCCESS) + { + rslt = COINES_E_COMM_INIT_FAILED; + } + + /* Holds the I2C device addr or SPI chip selection */ + dev->intf_ptr = &dev_addr; + + /* Configure delay in microseconds */ + dev->delay_us = bme280_delay_us; + + coines_delay_msec(100); + + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + + coines_delay_msec(100); + } + else + { + rslt = BME280_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief Function deinitializes coines platform. + */ +void bme280_coines_deinit(void) +{ + coines_close_comm_intf(COINES_COMM_INTF_USB, NULL); +} diff --git a/examples/common/common.h b/examples/common/common.h new file mode 100644 index 0000000..f2a3910 --- /dev/null +++ b/examples/common/common.h @@ -0,0 +1,140 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +#ifndef _COMMON_H +#define _COMMON_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "bme280.h" + +/***************************************************************************/ + +/*! User function prototypes + ****************************************************************************/ + +/*! + * @brief Function for reading the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address from which data is read. + * @param[out] reg_data : Pointer to data buffer where read data is stored. + * @param[in] length : Number of bytes of data to be read. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs. + * + * @return Status of execution + * + * @retval BME280_INTF_RET_SUCCESS -> Success. + * @retval != BME280_INTF_RET_SUCCESS -> Failure. + * + */ +BME280_INTF_RET_TYPE bme280_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address from which data is read. + * @param[out] reg_data : Pointer to data buffer where read data is stored. + * @param[in] length : Number of bytes of data to be read. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs. + * + * @return Status of execution + * + * @retval BME280_INTF_RET_SUCCESS -> Success. + * @retval != BME280_INTF_RET_SUCCESS -> Failure. + * + */ +BME280_INTF_RET_TYPE bme280_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address to which the data is written. + * @param[in] reg_data : Pointer to data buffer in which data to be written + * is stored. + * @param[in] length : Number of bytes of data to be written. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * + * @return Status of execution + * + * @retval BME280_INTF_RET_SUCCESS -> Success. + * @retval != BME280_INTF_RET_SUCCESS -> Failure. + * + */ +BME280_INTF_RET_TYPE bme280_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address to which the data is written. + * @param[in] reg_data : Pointer to data buffer in which data to be written + * is stored. + * @param[in] length : Number of bytes of data to be written. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * + * @return Status of execution + * + * @retval BME280_INTF_RET_SUCCESS -> Success. + * @retval != BME280_INTF_RET_SUCCESS -> Failure. + * + */ +BME280_INTF_RET_TYPE bme280_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period_us : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +void bme280_delay_us(uint32_t period_us, void *intf_ptr); + +/*! + * @brief This function is to select the interface between SPI and I2C. + * + * @param[in] dev : Structure instance of bme280_dev + * @param[in] intf : Interface selection parameter + * For I2C : BME280_I2C_INTF + * For SPI : BME280_SPI_INTF + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure + */ +int8_t bme280_interface_selection(struct bme280_dev *dev, uint8_t intf); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] api_name : Name of the API whose execution status has to be printed. + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +void bme280_error_codes_print_result(const char api_name[], int8_t rslt); + +/*! + * @brief This function deinitializes coines platform + * + * @return void. + * + */ +void bme280_coines_deinit(void); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _COMMON_H */ diff --git a/examples/contributed/Makefile b/examples/contributed/Makefile new file mode 100644 index 0000000..1cfc7d4 --- /dev/null +++ b/examples/contributed/Makefile @@ -0,0 +1,8 @@ +raspbian: + gcc linux_userspace.c ../../bme280.c -I ../.. -lwiringPi -o bme280 + +bsd: + gcc bsd_userspace.c ../../bme280.c -I ../.. -o bme280 + +clean: + rm -v bme280 diff --git a/examples/bsd_userspace.c b/examples/contributed/bsd_userspace.c similarity index 91% rename from examples/bsd_userspace.c rename to examples/contributed/bsd_userspace.c index 411a459..ef99e5a 100644 --- a/examples/bsd_userspace.c +++ b/examples/contributed/bsd_userspace.c @@ -1,329 +1,337 @@ -/* - * BSD userspace test code, simple and mose code directy from the doco. - * compile like this: cc bsd_userspace.c ../bme280.c -I ../ -o bme280 - * tested: NanoPi NEO. - * Use like: ./bme280 /dev/iic0 - */ - -#ifdef __KERNEL__ -#include -#include -#endif - -/******************************************************************************/ -/*! System header files */ - -#include -#include -#include -#include -#include -#include - -/******************************************************************************/ -/*! Own header files */ -#include -#include "bme280.h" - -/******************************************************************************/ -/*! Structures */ - -/* Structure that contains identifier details used in example */ -struct identifier -{ - /* Variable to hold device address */ - uint8_t dev_addr; - - /* Variable that contains file descriptor */ - int8_t fd; -}; - -/******************************************************************************/ -/*! Functions */ - -/*! - * @brief Function for reading the sensor's registers through I2C bus. - * - * @param[in] reg_addr : Register address. - * @param[out] data : Pointer to the data buffer to store the read data. - * @param[in] len : No of bytes to read. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs. - * - * @return Status of execution - * - * @retval 0 -> Success - * @retval > 0 -> Failure Info - * - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr); - -/*! - * @brief Function that creates a mandatory delay required in some of the APIs. - * - * @param[in] period : Delay in microseconds. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs - * @return void. - * - */ -void user_delay_us(uint32_t period, void *intf_ptr); - -/*! - * @brief Function for writing the sensor's registers through I2C bus. - * - * @param[in] reg_addr : Register address. - * @param[in] data : Pointer to the data buffer whose value is to be written. - * @param[in] len : No of bytes to write. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs - * - * @return Status of execution - * - * @retval BME280_OK -> Success - * @retval BME280_E_COMM_FAIL -> Communication failure. - * - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr); - -/*! - * @brief Function for print the temperature, humidity and pressure data. - * - * @param[out] comp_data : Structure instance of bme280_data - * - * @note Sensor data whose can be read - * - * sens_list - * -------------- - * Pressure - * Temperature - * Humidity - * - */ -static void print_sensor_data(struct bme280_data *comp_data); - -/*! - * @brief Function reads temperature, humidity and pressure data in forced mode. - * - * @param[in] dev : Structure instance of bme280_dev. - * - * @return Result of API execution status - * - * @retval BME280_OK - Success. - * @retval BME280_E_NULL_PTR - Error: Null pointer error - * @retval BME280_E_COMM_FAIL - Error: Communication fail error - * @retval BME280_E_NVM_COPY_FAILED - Error: NVM copy failed - * - */ -static int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev); - -/*! - * @brief This function reading the sensor's registers through I2C bus. - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr) -{ - struct identifier id; - - id = *((struct identifier *)intf_ptr); - - struct iic_msg msgs[2] = { - { id.dev_addr << 1 | IIC_M_WR, IIC_M_WR, 1, ®_addr }, { id.dev_addr << 1 | IIC_M_RD, IIC_M_RD, len, data }, - }; - - struct iic_rdwr_data rdwr_data = { msgs, 2 }; - - int error = ioctl(id.fd, I2CRDWR, &rdwr_data); - - if (error) - { - return BME280_E_COMM_FAIL; - } - - return BME280_OK; -} - -/*! - * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the - * APIs - */ -void user_delay_us(uint32_t period, void *intf_ptr) -{ - usleep(period); -} - -/*! - * @brief This function for writing the sensor's registers through I2C bus. - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr) -{ - struct identifier id; - - id = *((struct identifier *)intf_ptr); - - uint8_t *buf = malloc((1 + len) * sizeof(uint8_t)); - - if (buf == NULL) - { - return BME280_E_COMM_FAIL; - } - - buf[0] = reg_addr; - - for (uint8_t i = 0; i < len; i++) - { - buf[i + 1] = data[i]; - } - - struct iic_msg msg; - - msg.slave = id.dev_addr << 1 | !IIC_M_RD; - msg.flags = !IIC_M_RD; - msg.len = (1 + len) * sizeof(uint8_t); - msg.buf = buf; - - struct iic_rdwr_data rdwr_data = { &msg, 1 }; - - int error = ioctl(id.fd, I2CRDWR, &rdwr_data); - - if (error) - { - free(buf); - - return BME280_E_COMM_FAIL; - } - - free(buf); - - return BME280_OK; -} - -/*! - * @brief This API used to print the sensor temperature, pressure and humidity data. - */ -void print_sensor_data(struct bme280_data *comp_data) -{ - float temp, press, hum; - -#ifdef BME280_FLOAT_ENABLE - temp = comp_data->temperature; - press = 0.01 * comp_data->pressure; - hum = comp_data->humidity; -#else -#ifdef BME280_64BIT_ENABLE - temp = 0.01f * comp_data->temperature; - press = 0.0001f * comp_data->pressure; - hum = 1.0f / 1024.0f * comp_data->humidity; -#else - temp = 0.01f * comp_data->temperature; - press = 0.01f * comp_data->pressure; - hum = 1.0f / 1024.0f * comp_data->humidity; -#endif -#endif - printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum); -} - -/*! - * @brief This API reads the sensor temperature, pressure and humidity data in forced mode. - */ -int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) -{ - int8_t rslt; - uint8_t settings_sel; - struct bme280_data comp_data; - - /* Recommended mode of operation: Indoor navigation */ - dev->settings.osr_h = BME280_OVERSAMPLING_1X; - dev->settings.osr_p = BME280_OVERSAMPLING_16X; - dev->settings.osr_t = BME280_OVERSAMPLING_2X; - dev->settings.filter = BME280_FILTER_COEFF_16; - - settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL; - - rslt = bme280_set_sensor_settings(settings_sel, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt); - - return rslt; - } - - printf("Temperature, Pressure, Humidity\n"); - - /* Continuously stream sensor data */ - while (1) - { - rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt); - break; - } - - /* Wait for the measurement to complete and print data @25Hz */ - dev->delay_us(40000, dev->intf_ptr); - rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to get sensor data (code %+d).", rslt); - break; - } - - print_sensor_data(&comp_data); - dev->delay_us(1000000, dev->intf_ptr); - } - - return rslt; -} - -/*! - * @brief This function starts execution of the program. - */ -int main(int argc, char* argv[]) -{ - struct bme280_dev dev; - int8_t rslt = BME280_OK; - - struct identifier id; - - if (argc < 2) - { - fprintf(stderr, "Missing argument for i2c bus.\n"); - exit(1); - } - - if ((id.fd = open(argv[1], O_RDWR)) < 0) - { - fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]); - exit(1); - } - - /* - * make sure to select BME280_I2C_ADDR_PRIM - * or BME280_I2C_ADDR_SEC as needed - */ - id.dev_addr = BME280_I2C_ADDR_PRIM; - - dev.intf = BME280_I2C_INTF; - dev.read = user_i2c_read; - dev.write = user_i2c_write; - dev.delay_us = user_delay_us; - - /* Update interface pointer with the structure that contains both device address and file descriptor */ - dev.intf_ptr = &id; - - rslt = bme280_init(&dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt); - exit(1); - } - - rslt = stream_sensor_data_forced_mode(&dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt); - exit(1); - } - - return 0; -} +/* + * BSD userspace test code, simple and mose code directy from the doco. + * compile like this: cc bsd_userspace.c ../bme280.c -I ../ -o bme280 + * tested: NanoPi NEO. + * Use like: ./bme280 /dev/iic0 + */ + +#ifdef __KERNEL__ +#include +#include +#endif + +/******************************************************************************/ +/*! System header files */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************/ +/*! Own header files */ +#include +#include "bme280.h" + +/******************************************************************************/ +/*! Structures */ + +/* Structure that contains identifier details used in example */ +struct identifier +{ + /* Variable to hold device address */ + uint8_t dev_addr; + + /* Variable that contains file descriptor */ + int8_t fd; +}; + +/******************************************************************************/ +/*! Functions */ + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[out] data : Pointer to the data buffer to store the read data. + * @param[in] len : No of bytes to read. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs. + * + * @return Status of execution + * + * @retval 0 -> Success + * @retval > 0 -> Failure Info + * + */ +int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function that creates a mandatory delay required in some of the APIs. + * + * @param[in] period : Delay in microseconds. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * @return void. + * + */ +void user_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[in] data : Pointer to the data buffer whose value is to be written. + * @param[in] len : No of bytes to write. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * + * @return Status of execution + * + * @retval BME280_OK -> Success + * @retval BME280_E_COMM_FAIL -> Communication failure. + * + */ +int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for print the temperature, humidity and pressure data. + * + * @param[out] comp_data : Structure instance of bme280_data + * + * @note Sensor data whose can be read + * + * sens_list + * -------------- + * Pressure + * Temperature + * Humidity + * + */ +static void print_sensor_data(struct bme280_data *comp_data); + +/*! + * @brief Function reads temperature, humidity and pressure data in forced mode. + * + * @param[in] dev : Structure instance of bme280_dev. + * + * @return Result of API execution status + * + * @retval BME280_OK - Success. + * @retval BME280_E_NULL_PTR - Error: Null pointer error + * @retval BME280_E_COMM_FAIL - Error: Communication fail error + * @retval BME280_E_NVM_COPY_FAILED - Error: NVM copy failed + * + */ +static int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev); + +/*! + * @brief This function reading the sensor's registers through I2C bus. + */ +int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr) +{ + struct identifier id; + + id = *((struct identifier *)intf_ptr); + + struct iic_msg msgs[2] = { + { id.dev_addr << 1 | IIC_M_WR, IIC_M_WR, 1, ®_addr }, { id.dev_addr << 1 | IIC_M_RD, IIC_M_RD, len, data }, + }; + + struct iic_rdwr_data rdwr_data = { msgs, 2 }; + + int error = ioctl(id.fd, I2CRDWR, &rdwr_data); + + if (error) + { + return BME280_E_COMM_FAIL; + } + + return BME280_OK; +} + +/*! + * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the + * APIs + */ +void user_delay_us(uint32_t period, void *intf_ptr) +{ + usleep(period); +} + +/*! + * @brief This function for writing the sensor's registers through I2C bus. + */ +int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr) +{ + struct identifier id; + + id = *((struct identifier *)intf_ptr); + + uint8_t *buf = malloc((1 + len) * sizeof(uint8_t)); + + if (buf == NULL) + { + return BME280_E_COMM_FAIL; + } + + buf[0] = reg_addr; + + for (uint8_t i = 0; i < len; i++) + { + buf[i + 1] = data[i]; + } + + struct iic_msg msg; + + msg.slave = id.dev_addr << 1 | !IIC_M_RD; + msg.flags = !IIC_M_RD; + msg.len = (1 + len) * sizeof(uint8_t); + msg.buf = buf; + + struct iic_rdwr_data rdwr_data = { &msg, 1 }; + + int error = ioctl(id.fd, I2CRDWR, &rdwr_data); + + if (error) + { + free(buf); + + return BME280_E_COMM_FAIL; + } + + free(buf); + + return BME280_OK; +} + +/*! + * @brief This API used to print the sensor temperature, pressure and humidity data. + */ +void print_sensor_data(struct bme280_data *comp_data) +{ + float temp, press, hum; + +#ifdef BME280_FLOAT_ENABLE + temp = comp_data->temperature; + press = 0.01 * comp_data->pressure; + hum = comp_data->humidity; +#else +#ifdef BME280_64BIT_ENABLE + temp = 0.01f * comp_data->temperature; + press = 0.0001f * comp_data->pressure; + hum = 1.0f / 1024.0f * comp_data->humidity; +#else + temp = 0.01f * comp_data->temperature; + press = 0.01f * comp_data->pressure; + hum = 1.0f / 1024.0f * comp_data->humidity; +#endif +#endif + printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum); +} + +/*! + * @brief This API reads the sensor temperature, pressure and humidity data in forced mode. + */ +int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) +{ + int8_t rslt; + struct bme280_data comp_data; + struct bme280_settings settings = {0}; + + /* Get the current sensor settings */ + rslt = bme280_get_sensor_settings(&settings, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to get sensor settings (code %+d).", rslt); + + return rslt; + } + + /* Recommended mode of operation: Indoor navigation */ + settings.filter = BME280_FILTER_COEFF_16; + settings.osr_h = BME280_OVERSAMPLING_1X; + settings.osr_p = BME280_OVERSAMPLING_16X; + settings.osr_t = BME280_OVERSAMPLING_2X; + + /* Set the sensor settings */ + rslt = bme280_set_sensor_settings(BME280_SEL_ALL_SETTINGS, &settings, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt); + + return rslt; + } + + printf("Temperature, Pressure, Humidity\n"); + + /* Continuously stream sensor data */ + while (1) + { + rslt = bme280_set_sensor_mode(BME280_POWERMODE_FORCED, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt); + break; + } + + /* Wait for the measurement to complete and print data @25Hz */ + dev->delay_us(40000, dev->intf_ptr); + rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to get sensor data (code %+d).", rslt); + break; + } + + print_sensor_data(&comp_data); + dev->delay_us(1000000, dev->intf_ptr); + } + + return rslt; +} + +/*! + * @brief This function starts execution of the program. + */ +int main(int argc, char* argv[]) +{ + struct bme280_dev dev; + int8_t rslt = BME280_OK; + + struct identifier id; + + if (argc < 2) + { + fprintf(stderr, "Missing argument for i2c bus.\n"); + exit(1); + } + + if ((id.fd = open(argv[1], O_RDWR)) < 0) + { + fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]); + exit(1); + } + + /* + * make sure to select BME280_I2C_ADDR_PRIM + * or BME280_I2C_ADDR_SEC as needed + */ + id.dev_addr = BME280_I2C_ADDR_PRIM; + + dev.intf = BME280_I2C_INTF; + dev.read = user_i2c_read; + dev.write = user_i2c_write; + dev.delay_us = user_delay_us; + + /* Update interface pointer with the structure that contains both device address and file descriptor */ + dev.intf_ptr = &id; + + rslt = bme280_init(&dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt); + exit(1); + } + + rslt = stream_sensor_data_forced_mode(&dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt); + exit(1); + } + + return 0; +} diff --git a/examples/linux_userspace.c b/examples/contributed/linux_userspace.c similarity index 90% rename from examples/linux_userspace.c rename to examples/contributed/linux_userspace.c index 0b8fc9a..71dc2b8 100644 --- a/examples/linux_userspace.c +++ b/examples/contributed/linux_userspace.c @@ -1,331 +1,338 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -/** - * \ingroup bme280 - * \defgroup bme280Examples Examples - * @brief Reference Examples - */ - -/*! - * @ingroup bme280Examples - * @defgroup bme280GroupExampleLU linux_userspace - * @brief Linux userspace test code, simple and mose code directly from the doco. - * compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280 - * tested: Raspberry Pi. - * Use like: ./bme280 /dev/i2c-0 - * \include linux_userspace.c - */ - -#ifdef __KERNEL__ -#include -#include -#endif - -/******************************************************************************/ -/*! System header files */ -#include -#include -#include -#include -#include -#include - -/******************************************************************************/ -/*! Own header files */ -#include "bme280.h" - -/******************************************************************************/ -/*! Structures */ - -/* Structure that contains identifier details used in example */ -struct identifier -{ - /* Variable to hold device address */ - uint8_t dev_addr; - - /* Variable that contains file descriptor */ - int8_t fd; -}; - -/****************************************************************************/ -/*! Functions */ - -/*! - * @brief Function that creates a mandatory delay required in some of the APIs. - * - * @param[in] period : Delay in microseconds. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs - * @return void. - * - */ -void user_delay_us(uint32_t period, void *intf_ptr); - -/*! - * @brief Function for print the temperature, humidity and pressure data. - * - * @param[out] comp_data : Structure instance of bme280_data - * - * @note Sensor data whose can be read - * - * sens_list - * -------------- - * Pressure - * Temperature - * Humidity - * - */ -void print_sensor_data(struct bme280_data *comp_data); - -/*! - * @brief Function for reading the sensor's registers through I2C bus. - * - * @param[in] reg_addr : Register address. - * @param[out] data : Pointer to the data buffer to store the read data. - * @param[in] len : No of bytes to read. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs. - * - * @return Status of execution - * - * @retval 0 -> Success - * @retval > 0 -> Failure Info - * - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr); - -/*! - * @brief Function for writing the sensor's registers through I2C bus. - * - * @param[in] reg_addr : Register address. - * @param[in] data : Pointer to the data buffer whose value is to be written. - * @param[in] len : No of bytes to write. - * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors - * for interface related call backs - * - * @return Status of execution - * - * @retval BME280_OK -> Success - * @retval BME280_E_COMM_FAIL -> Communication failure. - * - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr); - -/*! - * @brief Function reads temperature, humidity and pressure data in forced mode. - * - * @param[in] dev : Structure instance of bme280_dev. - * - * @return Result of API execution status - * - * @retval BME280_OK - Success. - * @retval BME280_E_NULL_PTR - Error: Null pointer error - * @retval BME280_E_COMM_FAIL - Error: Communication fail error - * @retval BME280_E_NVM_COPY_FAILED - Error: NVM copy failed - * - */ -int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev); - -/*! - * @brief This function starts execution of the program. - */ -int main(int argc, char* argv[]) -{ - struct bme280_dev dev; - - struct identifier id; - - /* Variable to define the result */ - int8_t rslt = BME280_OK; - - if (argc < 2) - { - fprintf(stderr, "Missing argument for i2c bus.\n"); - exit(1); - } - - if ((id.fd = open(argv[1], O_RDWR)) < 0) - { - fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]); - exit(1); - } - -#ifdef __KERNEL__ - if (ioctl(id.fd, I2C_SLAVE, id.dev_addr) < 0) - { - fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n"); - exit(1); - } - -#endif - - /* Make sure to select BME280_I2C_ADDR_PRIM or BME280_I2C_ADDR_SEC as needed */ - id.dev_addr = BME280_I2C_ADDR_PRIM; - - dev.intf = BME280_I2C_INTF; - dev.read = user_i2c_read; - dev.write = user_i2c_write; - dev.delay_us = user_delay_us; - - /* Update interface pointer with the structure that contains both device address and file descriptor */ - dev.intf_ptr = &id; - - /* Initialize the bme280 */ - rslt = bme280_init(&dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt); - exit(1); - } - - rslt = stream_sensor_data_forced_mode(&dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt); - exit(1); - } - - return 0; -} - -/*! - * @brief This function reading the sensor's registers through I2C bus. - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr) -{ - struct identifier id; - - id = *((struct identifier *)intf_ptr); - - write(id.fd, ®_addr, 1); - read(id.fd, data, len); - - return 0; -} - -/*! - * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the - * APIs - */ -void user_delay_us(uint32_t period, void *intf_ptr) -{ - usleep(period); -} - -/*! - * @brief This function for writing the sensor's registers through I2C bus. - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr) -{ - uint8_t *buf; - struct identifier id; - - id = *((struct identifier *)intf_ptr); - - buf = malloc(len + 1); - buf[0] = reg_addr; - memcpy(buf + 1, data, len); - if (write(id.fd, buf, len + 1) < (uint16_t)len) - { - return BME280_E_COMM_FAIL; - } - - free(buf); - - return BME280_OK; -} - -/*! - * @brief This API used to print the sensor temperature, pressure and humidity data. - */ -void print_sensor_data(struct bme280_data *comp_data) -{ - float temp, press, hum; - -#ifdef BME280_FLOAT_ENABLE - temp = comp_data->temperature; - press = 0.01 * comp_data->pressure; - hum = comp_data->humidity; -#else -#ifdef BME280_64BIT_ENABLE - temp = 0.01f * comp_data->temperature; - press = 0.0001f * comp_data->pressure; - hum = 1.0f / 1024.0f * comp_data->humidity; -#else - temp = 0.01f * comp_data->temperature; - press = 0.01f * comp_data->pressure; - hum = 1.0f / 1024.0f * comp_data->humidity; -#endif -#endif - printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum); -} - -/*! - * @brief This API reads the sensor temperature, pressure and humidity data in forced mode. - */ -int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) -{ - /* Variable to define the result */ - int8_t rslt = BME280_OK; - - /* Variable to define the selecting sensors */ - uint8_t settings_sel = 0; - - /* Variable to store minimum wait time between consecutive measurement in force mode */ - uint32_t req_delay; - - /* Structure to get the pressure, temperature and humidity values */ - struct bme280_data comp_data; - - /* Recommended mode of operation: Indoor navigation */ - dev->settings.osr_h = BME280_OVERSAMPLING_1X; - dev->settings.osr_p = BME280_OVERSAMPLING_16X; - dev->settings.osr_t = BME280_OVERSAMPLING_2X; - dev->settings.filter = BME280_FILTER_COEFF_16; - - settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL; - - /* Set the sensor settings */ - rslt = bme280_set_sensor_settings(settings_sel, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt); - - return rslt; - } - - printf("Temperature, Pressure, Humidity\n"); - - /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled - * and the oversampling configuration. */ - req_delay = bme280_cal_meas_delay(&dev->settings); - - /* Continuously stream sensor data */ - while (1) - { - /* Set the sensor to forced mode */ - rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt); - break; - } - - /* Wait for the measurement to complete and print data */ - dev->delay_us(req_delay, dev->intf_ptr); - rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); - if (rslt != BME280_OK) - { - fprintf(stderr, "Failed to get sensor data (code %+d).", rslt); - break; - } - - print_sensor_data(&comp_data); - } - - return rslt; -} +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/** + * \ingroup bme280 + * \defgroup bme280Examples Examples + * @brief Reference Examples + */ + +/*! + * @ingroup bme280Examples + * @defgroup bme280GroupExampleLU linux_userspace + * @brief Linux userspace test code, simple and mose code directly from the doco. + * compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280 + * tested: Raspberry Pi. + * Use like: ./bme280 /dev/i2c-0 + * \include linux_userspace.c + */ + +#ifdef __KERNEL__ +#include +#include +#endif + +/******************************************************************************/ +/*! System header files */ +#include +#include +#include +#include +#include +#include + +/******************************************************************************/ +/*! Own header files */ +#include "bme280.h" + +/******************************************************************************/ +/*! Structures */ + +/* Structure that contains identifier details used in example */ +struct identifier +{ + /* Variable to hold device address */ + uint8_t dev_addr; + + /* Variable that contains file descriptor */ + int8_t fd; +}; + +/****************************************************************************/ +/*! Functions */ + +/*! + * @brief Function that creates a mandatory delay required in some of the APIs. + * + * @param[in] period : Delay in microseconds. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * @return void. + * + */ +void user_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief Function for print the temperature, humidity and pressure data. + * + * @param[out] comp_data : Structure instance of bme280_data + * + * @note Sensor data whose can be read + * + * sens_list + * -------------- + * Pressure + * Temperature + * Humidity + * + */ +void print_sensor_data(struct bme280_data *comp_data); + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[out] data : Pointer to the data buffer to store the read data. + * @param[in] len : No of bytes to read. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs. + * + * @return Status of execution + * + * @retval 0 -> Success + * @retval > 0 -> Failure Info + * + */ +int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[in] data : Pointer to the data buffer whose value is to be written. + * @param[in] len : No of bytes to write. + * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related call backs + * + * @return Status of execution + * + * @retval BME280_OK -> Success + * @retval BME280_E_COMM_FAIL -> Communication failure. + * + */ +int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function reads temperature, humidity and pressure data in forced mode. + * + * @param[in] dev : Structure instance of bme280_dev. + * + * @return Result of API execution status + * + * @retval BME280_OK - Success. + * @retval BME280_E_NULL_PTR - Error: Null pointer error + * @retval BME280_E_COMM_FAIL - Error: Communication fail error + * @retval BME280_E_NVM_COPY_FAILED - Error: NVM copy failed + * + */ +int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev); + +/*! + * @brief This function starts execution of the program. + */ +int main(int argc, char* argv[]) +{ + struct bme280_dev dev; + + struct identifier id; + + /* Variable to define the result */ + int8_t rslt = BME280_OK; + + if (argc < 2) + { + fprintf(stderr, "Missing argument for i2c bus.\n"); + exit(1); + } + + if ((id.fd = open(argv[1], O_RDWR)) < 0) + { + fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]); + exit(1); + } + +#ifdef __KERNEL__ + if (ioctl(id.fd, I2C_SLAVE, id.dev_addr) < 0) + { + fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n"); + exit(1); + } + +#endif + + /* Make sure to select BME280_I2C_ADDR_PRIM or BME280_I2C_ADDR_SEC as needed */ + id.dev_addr = BME280_I2C_ADDR_PRIM; + + dev.intf = BME280_I2C_INTF; + dev.read = user_i2c_read; + dev.write = user_i2c_write; + dev.delay_us = user_delay_us; + + /* Update interface pointer with the structure that contains both device address and file descriptor */ + dev.intf_ptr = &id; + + /* Initialize the bme280 */ + rslt = bme280_init(&dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt); + exit(1); + } + + rslt = stream_sensor_data_forced_mode(&dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt); + exit(1); + } + + return 0; +} + +/*! + * @brief This function reading the sensor's registers through I2C bus. + */ +int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr) +{ + struct identifier id; + + id = *((struct identifier *)intf_ptr); + + write(id.fd, ®_addr, 1); + read(id.fd, data, len); + + return 0; +} + +/*! + * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the + * APIs + */ +void user_delay_us(uint32_t period, void *intf_ptr) +{ + usleep(period); +} + +/*! + * @brief This function for writing the sensor's registers through I2C bus. + */ +int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void *intf_ptr) +{ + uint8_t *buf; + struct identifier id; + + id = *((struct identifier *)intf_ptr); + + buf = malloc(len + 1); + buf[0] = reg_addr; + memcpy(buf + 1, data, len); + if (write(id.fd, buf, len + 1) < (uint16_t)len) + { + return BME280_E_COMM_FAIL; + } + + free(buf); + + return BME280_OK; +} + +/*! + * @brief This API used to print the sensor temperature, pressure and humidity data. + */ +void print_sensor_data(struct bme280_data *comp_data) +{ + float temp, press, hum; + +#ifdef BME280_FLOAT_ENABLE + temp = comp_data->temperature; + press = 0.01 * comp_data->pressure; + hum = comp_data->humidity; +#else +#ifdef BME280_64BIT_ENABLE + temp = 0.01f * comp_data->temperature; + press = 0.0001f * comp_data->pressure; + hum = 1.0f / 1024.0f * comp_data->humidity; +#else + temp = 0.01f * comp_data->temperature; + press = 0.01f * comp_data->pressure; + hum = 1.0f / 1024.0f * comp_data->humidity; +#endif +#endif + printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum); +} + +/*! + * @brief This API reads the sensor temperature, pressure and humidity data in forced mode. + */ +int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) +{ + /* Variable to define the result */ + int8_t rslt = BME280_OK; + + /* Structure to store the settings */ + struct bme280_settings settings = {0}; + + /* Variable to store minimum wait time between consecutive measurement in force mode */ + uint32_t req_delay; + + /* Structure to get the pressure, temperature and humidity values */ + struct bme280_data comp_data; + + /* Get the current sensor settings */ + rslt = bme280_get_sensor_settings(&settings, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to get sensor settings (code %+d).", rslt); + + return rslt; + } + + /* Recommended mode of operation: Indoor navigation */ + settings.filter = BME280_FILTER_COEFF_16; + settings.osr_h = BME280_OVERSAMPLING_1X; + settings.osr_p = BME280_OVERSAMPLING_16X; + settings.osr_t = BME280_OVERSAMPLING_2X; + + /* Set the sensor settings */ + rslt = bme280_set_sensor_settings(BME280_SEL_ALL_SETTINGS, &settings, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt); + + return rslt; + } + + printf("Temperature, Pressure, Humidity\n"); + + /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled + * and the oversampling configuration. */ + bme280_cal_meas_delay(&req_delay, &settings); + + /* Continuously stream sensor data */ + while (1) + { + /* Set the sensor to forced mode */ + rslt = bme280_set_sensor_mode(BME280_POWERMODE_FORCED, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt); + break; + } + + /* Wait for the measurement to complete and print data */ + dev->delay_us(req_delay, dev->intf_ptr); + rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); + if (rslt != BME280_OK) + { + fprintf(stderr, "Failed to get sensor data (code %+d).", rslt); + break; + } + + print_sensor_data(&comp_data); + } + + return rslt; +} diff --git a/examples/humidity/Makefile b/examples/humidity/Makefile new file mode 100644 index 0000000..cd9fe9f --- /dev/null +++ b/examples/humidity/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= humidity.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme280.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/humidity/humidity.c b/examples/humidity/humidity.c new file mode 100644 index 0000000..ba05003 --- /dev/null +++ b/examples/humidity/humidity.c @@ -0,0 +1,129 @@ +/**\ + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * The license is available at root folder + * + **/ + +/******************************************************************************/ +/*! Header Files */ +#include "stdio.h" +#include "bme280.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +#define SAMPLE_COUNT UINT8_C(50) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to get compensated humidity data. + * + * @param[in] period : Contains the delay in microseconds. + * @param[in] dev : Structure instance of bme280_dev. + * + * @return Status of execution. + */ +static int8_t get_humidity(uint32_t period, struct bme280_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + int8_t rslt; + uint32_t period; + struct bme280_dev dev; + struct bme280_settings settings; + + /* Interface selection is to be updated as parameter + * For I2C : BME280_I2C_INTF + * For SPI : BME280_SPI_INTF + */ + rslt = bme280_interface_selection(&dev, BME280_I2C_INTF); + bme280_error_codes_print_result("bme280_interface_selection", rslt); + + rslt = bme280_init(&dev); + bme280_error_codes_print_result("bme280_init", rslt); + + /* Always read the current settings before writing, especially when all the configuration is not modified */ + rslt = bme280_get_sensor_settings(&settings, &dev); + bme280_error_codes_print_result("bme280_get_sensor_settings", rslt); + + /* Configuring the over-sampling rate, filter coefficient and standby time */ + /* Overwrite the desired settings */ + settings.filter = BME280_FILTER_COEFF_2; + + /* Over-sampling rate for humidity, temperature and pressure */ + settings.osr_h = BME280_OVERSAMPLING_1X; + settings.osr_p = BME280_OVERSAMPLING_1X; + settings.osr_t = BME280_OVERSAMPLING_1X; + + /* Setting the standby time */ + settings.standby_time = BME280_STANDBY_TIME_0_5_MS; + + rslt = bme280_set_sensor_settings(BME280_SEL_ALL_SETTINGS, &settings, &dev); + bme280_error_codes_print_result("bme280_set_sensor_settings", rslt); + + /* Always set the power mode after setting the configuration */ + rslt = bme280_set_sensor_mode(BME280_POWERMODE_NORMAL, &dev); + bme280_error_codes_print_result("bme280_set_power_mode", rslt); + + /* Calculate measurement time in microseconds */ + rslt = bme280_cal_meas_delay(&period, &settings); + bme280_error_codes_print_result("bme280_cal_meas_delay", rslt); + + printf("\nHumidity calculation (Data displayed are compensated values)\n"); + printf("Measurement time : %lu us\n\n", (long unsigned int)period); + + rslt = get_humidity(period, &dev); + bme280_error_codes_print_result("get_humidity", rslt); + + bme280_coines_deinit(); + + return 0; +} + +/*! + * @brief This internal API is used to get compensated humidity data. + */ +static int8_t get_humidity(uint32_t period, struct bme280_dev *dev) +{ + int8_t rslt = BME280_E_NULL_PTR; + int8_t idx = 0; + uint8_t status_reg; + struct bme280_data comp_data; + + while (idx < SAMPLE_COUNT) + { + rslt = bme280_get_regs(BME280_REG_STATUS, &status_reg, 1, dev); + bme280_error_codes_print_result("bme280_get_regs", rslt); + + if (status_reg & BME280_STATUS_MEAS_DONE) + { + /* Measurement time delay given to read sample */ + dev->delay_us(period, dev->intf_ptr); + + /* Read compensated data */ + rslt = bme280_get_sensor_data(BME280_HUM, &comp_data, dev); + bme280_error_codes_print_result("bme280_get_sensor_data", rslt); + +#ifndef BME280_DOUBLE_ENABLE + comp_data.humidity = comp_data.humidity / 1000; +#endif + +#ifdef BME280_DOUBLE_ENABLE + printf("Humidity[%d]: %lf %%RH\n", idx, comp_data.humidity); +#else + printf("Humidity[%d]: %lu %%RH\n", idx, (long unsigned int)comp_data.humidity); +#endif + idx++; + } + } + + return rslt; +} diff --git a/examples/pressure/Makefile b/examples/pressure/Makefile new file mode 100644 index 0000000..e5e51f0 --- /dev/null +++ b/examples/pressure/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= pressure.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme280.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/pressure/pressure.c b/examples/pressure/pressure.c new file mode 100644 index 0000000..8b75111 --- /dev/null +++ b/examples/pressure/pressure.c @@ -0,0 +1,129 @@ +/**\ + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * The license is available at root folder + * + **/ + +/******************************************************************************/ +/*! Header Files */ +#include "stdio.h" +#include "bme280.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +#define SAMPLE_COUNT UINT8_C(50) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to get compensated pressure data. + * + * @param[in] period : Contains the delay in microseconds. + * @param[in] dev : Structure instance of bme280_dev. + * + * @return Status of execution. + */ +static int8_t get_pressure(uint32_t period, struct bme280_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + int8_t rslt; + uint32_t period; + struct bme280_dev dev; + struct bme280_settings settings; + + /* Interface selection is to be updated as parameter + * For I2C : BME280_I2C_INTF + * For SPI : BME280_SPI_INTF + */ + rslt = bme280_interface_selection(&dev, BME280_I2C_INTF); + bme280_error_codes_print_result("bme280_interface_selection", rslt); + + rslt = bme280_init(&dev); + bme280_error_codes_print_result("bme280_init", rslt); + + /* Always read the current settings before writing, especially when all the configuration is not modified */ + rslt = bme280_get_sensor_settings(&settings, &dev); + bme280_error_codes_print_result("bme280_get_sensor_settings", rslt); + + /* Configuring the over-sampling rate, filter coefficient and standby time */ + /* Overwrite the desired settings */ + settings.filter = BME280_FILTER_COEFF_2; + + /* Over-sampling rate for humidity, temperature and pressure */ + settings.osr_h = BME280_OVERSAMPLING_1X; + settings.osr_p = BME280_OVERSAMPLING_1X; + settings.osr_t = BME280_OVERSAMPLING_1X; + + /* Setting the standby time */ + settings.standby_time = BME280_STANDBY_TIME_0_5_MS; + + rslt = bme280_set_sensor_settings(BME280_SEL_ALL_SETTINGS, &settings, &dev); + bme280_error_codes_print_result("bme280_set_sensor_settings", rslt); + + /* Always set the power mode after setting the configuration */ + rslt = bme280_set_sensor_mode(BME280_POWERMODE_NORMAL, &dev); + bme280_error_codes_print_result("bme280_set_power_mode", rslt); + + /* Calculate measurement time in microseconds */ + rslt = bme280_cal_meas_delay(&period, &settings); + bme280_error_codes_print_result("bme280_cal_meas_delay", rslt); + + printf("\nPressure calculation (Data displayed are compensated values)\n"); + printf("Measurement time : %lu us\n\n", (long unsigned int)period); + + rslt = get_pressure(period, &dev); + bme280_error_codes_print_result("get_pressure", rslt); + + bme280_coines_deinit(); + + return 0; +} + +/*! + * @brief This internal API is used to get compensated pressure data. + */ +static int8_t get_pressure(uint32_t period, struct bme280_dev *dev) +{ + int8_t rslt = BME280_E_NULL_PTR; + int8_t idx = 0; + uint8_t status_reg; + struct bme280_data comp_data; + + while (idx < SAMPLE_COUNT) + { + rslt = bme280_get_regs(BME280_REG_STATUS, &status_reg, 1, dev); + bme280_error_codes_print_result("bme280_get_regs", rslt); + + if (status_reg & BME280_STATUS_MEAS_DONE) + { + /* Measurement time delay given to read sample */ + dev->delay_us(period, dev->intf_ptr); + + /* Read compensated data */ + rslt = bme280_get_sensor_data(BME280_PRESS, &comp_data, dev); + bme280_error_codes_print_result("bme280_get_sensor_data", rslt); + +#ifdef BME280_64BIT_ENABLE + comp_data.pressure = comp_data.pressure / 100; +#endif + +#ifdef BME280_DOUBLE_ENABLE + printf("Pressure[%d]: %lf Pa\n", idx, comp_data.pressure); +#else + printf("Pressure[%d]: %lu Pa\n", idx, (long unsigned int)comp_data.pressure); +#endif + idx++; + } + } + + return rslt; +} diff --git a/examples/temperature/Makefile b/examples/temperature/Makefile new file mode 100644 index 0000000..46e21af --- /dev/null +++ b/examples/temperature/Makefile @@ -0,0 +1,15 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= temperature.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bme280.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/temperature/temperature.c b/examples/temperature/temperature.c new file mode 100644 index 0000000..d0c088a --- /dev/null +++ b/examples/temperature/temperature.c @@ -0,0 +1,129 @@ +/**\ + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * The license is available at root folder + * + **/ + +/******************************************************************************/ +/*! Header Files */ +#include "stdio.h" +#include "bme280.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +#define SAMPLE_COUNT UINT8_C(50) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to get compensated temperature data. + * + * @param[in] period : Contains the delay in microseconds. + * @param[in] dev : Structure instance of bme280_dev. + * + * @return Status of execution. + */ +static int8_t get_temperature(uint32_t period, struct bme280_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + int8_t rslt; + uint32_t period; + struct bme280_dev dev; + struct bme280_settings settings; + + /* Interface selection is to be updated as parameter + * For I2C : BME280_I2C_INTF + * For SPI : BME280_SPI_INTF + */ + rslt = bme280_interface_selection(&dev, BME280_I2C_INTF); + bme280_error_codes_print_result("bme280_interface_selection", rslt); + + rslt = bme280_init(&dev); + bme280_error_codes_print_result("bme280_init", rslt); + + /* Always read the current settings before writing, especially when all the configuration is not modified */ + rslt = bme280_get_sensor_settings(&settings, &dev); + bme280_error_codes_print_result("bme280_get_sensor_settings", rslt); + + /* Configuring the over-sampling rate, filter coefficient and standby time */ + /* Overwrite the desired settings */ + settings.filter = BME280_FILTER_COEFF_2; + + /* Over-sampling rate for humidity, temperature and pressure */ + settings.osr_h = BME280_OVERSAMPLING_1X; + settings.osr_p = BME280_OVERSAMPLING_1X; + settings.osr_t = BME280_OVERSAMPLING_1X; + + /* Setting the standby time */ + settings.standby_time = BME280_STANDBY_TIME_0_5_MS; + + rslt = bme280_set_sensor_settings(BME280_SEL_ALL_SETTINGS, &settings, &dev); + bme280_error_codes_print_result("bme280_set_sensor_settings", rslt); + + /* Always set the power mode after setting the configuration */ + rslt = bme280_set_sensor_mode(BME280_POWERMODE_NORMAL, &dev); + bme280_error_codes_print_result("bme280_set_power_mode", rslt); + + /* Calculate measurement time in microseconds */ + rslt = bme280_cal_meas_delay(&period, &settings); + bme280_error_codes_print_result("bme280_cal_meas_delay", rslt); + + printf("\nTemperature calculation (Data displayed are compensated values)\n"); + printf("Measurement time : %lu us\n\n", (long unsigned int)period); + + rslt = get_temperature(period, &dev); + bme280_error_codes_print_result("get_temperature", rslt); + + bme280_coines_deinit(); + + return 0; +} + +/*! + * @brief This internal API is used to get compensated temperature data. + */ +static int8_t get_temperature(uint32_t period, struct bme280_dev *dev) +{ + int8_t rslt = BME280_E_NULL_PTR; + int8_t idx = 0; + uint8_t status_reg; + struct bme280_data comp_data; + + while (idx < SAMPLE_COUNT) + { + rslt = bme280_get_regs(BME280_REG_STATUS, &status_reg, 1, dev); + bme280_error_codes_print_result("bme280_get_regs", rslt); + + if (status_reg & BME280_STATUS_MEAS_DONE) + { + /* Measurement time delay given to read sample */ + dev->delay_us(period, dev->intf_ptr); + + /* Read compensated data */ + rslt = bme280_get_sensor_data(BME280_TEMP, &comp_data, dev); + bme280_error_codes_print_result("bme280_get_sensor_data", rslt); + +#ifndef BME280_DOUBLE_ENABLE + comp_data.temperature = comp_data.temperature / 100; +#endif + +#ifdef BME280_DOUBLE_ENABLE + printf("Temperature[%d]: %lf deg C\n", idx, comp_data.temperature); +#else + printf("Temperature[%d]: %ld deg C\n", idx, (long int)comp_data.temperature); +#endif + idx++; + } + } + + return rslt; +}