Updated to new architecture. Added examples. Updated contributed examples.

This commit is contained in:
Bosch Sensortec 2023-04-17 10:50:33 +02:00 committed by Kevin Goveas
parent c47f06eb44
commit 3ba9abb813
16 changed files with 1987 additions and 1446 deletions

316
README.md
View File

@ -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;
}
```
- [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)

544
bme280.c
View File

@ -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(&reg_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(&reg_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, &reg_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(&reg_data, settings);
}
if (desired_settings & BME280_OSR_TEMP_SEL)
if (desired_settings & BME280_SEL_OSR_TEMP)
{
fill_osr_temp_settings(&reg_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, &reg_data, 1, dev);
if (rslt == BME280_OK)
{
if (desired_settings & BME280_FILTER_SEL)
if (desired_settings & BME280_SEL_FILTER)
{
fill_filter_settings(&reg_data, settings);
}
if (desired_settings & BME280_STANDBY_SEL)
if (desired_settings & BME280_SEL_STANDBY)
{
fill_standby_settings(&reg_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++)
{

130
bme280.h
View File

@ -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 <a href="https://github.com/BoschSensortec/BME280_driver">Sensor API Source Code</a>
*/
#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 */
/** @}*/

View File

@ -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 */

View File

@ -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

216
examples/common/common.c Normal file
View File

@ -0,0 +1,216 @@
/**
* Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#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);
}

140
examples/common/common.h Normal file
View File

@ -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 <stdio.h>
#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 */

View File

@ -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

View File

@ -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 <sys/ioctl.h>
#include <dev/iicbus/iic.h>
#endif
/******************************************************************************/
/*! System header files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
/******************************************************************************/
/*! Own header files */
#include <iic.h>
#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, &reg_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 <sys/ioctl.h>
#include <dev/iicbus/iic.h>
#endif
/******************************************************************************/
/*! System header files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
/******************************************************************************/
/*! Own header files */
#include <iic.h>
#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, &reg_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;
}

View File

@ -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 <linux/i2c-dev.h>
#include <sys/ioctl.h>
#endif
/******************************************************************************/
/*! System header files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
/******************************************************************************/
/*! 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, &reg_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 <linux/i2c-dev.h>
#include <sys/ioctl.h>
#endif
/******************************************************************************/
/*! System header files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
/******************************************************************************/
/*! 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, &reg_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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}