An open API service indexing awesome lists of open source software.

https://github.com/ebrezadev/bme280-barometric-pressure-temperature-humidity-sensor-c-driver

Bosch Sensortec BME280 High Level MCU Independent C Driver
https://github.com/ebrezadev/bme280-barometric-pressure-temperature-humidity-sensor-c-driver

api arduino bme280 bosch c driver embedded humidity library microcontroller pressure sensor temperature

Last synced: 3 months ago
JSON representation

Bosch Sensortec BME280 High Level MCU Independent C Driver

Awesome Lists containing this project

README

          

# BME280 Barometric Pressure, Temperature and Humidity Sensor C Device Driver (Platform Independent, Thread-safe, Reentrant)
## Introduction
* Version 2.0
* Reza G. Ebrahimi

The BME280 is a combined digital humidity, pressure and temperature sensor made by Bosch Sensortec. This is a platform independent, re-entrant and thread-safe C device driver with safety, error handling and optional features.

___
## Quick Start Guide
**Please refer to "BME280 Driver Description" section for full details**.
1. Turn features ON or OFF in the "bme280_config.h" file. In a simple example:
```c
#define BME280_INCLUDE_NULL_CHECK 0
#define BME280_INCLUDE_NULL_CHECK_ONLY_INIT 1
#define BME280_INCLUDE_CONNECTION_CHECK 1
/*etc...*/
```
2. Fill in the needed interface prototypes inside 'bme280_interface.c' file. This could be I2C interface, SPI or software mock. As an example of I2C interface:
```c
int bme280_write_array(uint8_t deviceAddress, uint8_t startRegisterAddress, uint8_t *data, uint8_t dataLength)
{
/*...*/
return 0;
}
/*etc...*/
```
4. In your application file, declare a handle for BME280 instance:
```c
bme280_type_handle_t handle;
```
4. Provide function pointers for `handle.dependency_interface`. As an example of I2C interface:
```c
handle.dependency_interface.bme280_interface_init = bme280_i2c_init;
handle.dependency_interface.bme280_interface_deinit = bme280_i2c_deinit;
handle.dependency_interface.bme280_read_array = bme280_read_array;
/*etc...*/
```
5. The init function must be called before any other API. Here we can set the interface as I2C with `BME280_TYPEVAL_HARDWARE_INTERFACE_I2C`, SPI with `BME280_TYPEVAL_HARDWARE_INTERFACE_SPI` or software mock with `BME280_TYPEVAL_HARDWARE_INTERFACE_OTHER`. In case of I2C, correct I2C address must be chosen between `BME280_TYPEVAL_I2C_ADDRESS_1` (0x76) or `BME280_TYPEVAL_I2C_ADDRESS_2` (0x77). In case of SPI or software mock, this address is ignored. As an example for I2C:
```c
bme280_type_error_code_t error;

error = bme280_api_init(&handle, BME280_TYPEVAL_HARDWARE_INTERFACE_I2C, BME280_TYPEVAL_I2C_ADDRESS_2);
```
6. Now mode of operation, oversampling values, IIR filter and standby time (in normal mode of operation) can be set. Alternatively, a Bosch recommended preset can be used. As an example:
```c
/*Example for custom settings*/
error = bme280_api_set_mode(&handle, BME280_TYPEVAL_MODE_NORMAL);
/*handle error...*/
error = bme280_api_set_pressure_oversampling(&handle, BME280_TYPEVAL_OVERSAMPLING_4X);
/*handle error...*/
error = bme280_api_set_temperature_oversampling(&handle, BME280_TYPEVAL_OVERSAMPLING_8X);
/*etc...*/

/*Example for Bosch recommended settings*/
error = bme280_preset_weather_monitoring(&handle);
```
7. If set to NORMAL mode, the sensor values can be read periodically. As an example of setting `BME280_INCLUDE_SENSOR_ALL` in config file for all-in-one reading:
```c
bme280_type_sensors_data_t data;

error = bme280_api_get_all(&handle, &data);
/*handle error...*/
/*Do stuff with data.temperature, data.pressure, data.humidity*/

float temperature = (float)data.temperature / 100;
float humidity = (float)data.humidity / 1024;
```
8. If set to FORCED mode, the sensor values can be read right after calling the 'set mode' API function. As an example of setting `BME280_INCLUDE_SENSOR_ALL` in config file for all-in-one reading:
```c
bme280_type_sensors_data_t data;

error = bme280_api_set_mode(&handle, BME280_TYPEVAL_MODE_FORCED);
/*handle error...*/
error = bme280_api_get_all(&handle, &data);
/*handle error...*/
/*Do stuff with data.temperature, data.pressure, data.humidity*/

float temperature = (float)data.temperature / 100;
float humidity = (float)data.humidity / 1024;
```

---
## BME280 Hardware Overview
### Introduction to BME280
The BME280 is a combined digital humidity, pressure and temperature sensor based on proven sensing principles. The sensor module is housed in an extremely compact metal-lid LGA package with a footprint of only 2.5 × 2.5 mm² with a height of 0.93 mm. Its small dimensions and its low power consumption allow the implementation in battery driven devices such as handsets, GPS modules or watches. The BME280 is register and performance compatible to the Bosch Sensortec BMP280 digital pressure sensor.

### BME280 Features
- Combined digital humidity, pressure and temperature sensor.
- The sensor provides both SPI and I²C interfaces.
- Can be supplied using 1.71 to 3.6 V for the sensor supply VDD and 1.2 to 3.6 V for the interface supply VDDIO.
- Measurements can be triggered by the host (forced mode) or performed in regular intervals (normal mode).
- BME280 has 3 modes of operation:
- SLEEP: No new measurements take place.
- FORCED: Updates measurements for once and changes to SLEEP state afterwards.
- NORMAL: Periodically (based on standby time) updates measurements.
- In order to tailor data rate, noise, response time and current consumption to the needs of the user, a variety of oversampling modes, filter modes and data rates can be selected.
- The BME280 measurement period consists of a temperature, pressure and humidity measurement with selectable oversampling. After the measurement period, the pressure and temperature data can be passed through an optional IIR filter, which removes short-term fluctuations in pressure (e.g. caused by slamming a door). For humidity, such a filter is not needed and has not been implemented.

### Humidity Measurement
The humidity measurement can be enabled or skipped. When enabled, several oversampling options exist. For the humidity measurement, oversampling is possible to reduce the noise. The resolution of the humidity measurement is fixed at 16 bit ADC output.

### Pressure Measurement
Pressure measurement can be enabled or skipped. When enabled, several oversampling options exist. For the pressure measurement, oversampling is possible to reduce the noise. The resolution of the pressure data depends on the IIR filter and the oversampling setting:
- When the IIR filter is enabled, the pressure resolution is 20 bit.
- When the IIR filter is disabled, the pressure resolution is 16 + (osrs_p – 1) bit, e.g. 18 bit when osrs_p is set to ‘3’.

### Temperature Measurement
Temperature measurement can be enabled or skipped. Skipping the measurement could be useful to measure pressure extremely rapidly. When enabled, several oversampling options exist. For the temperature measurement, oversampling is possible to reduce the noise. The resolution of the temperature data depends on the IIR filter and the oversampling setting:
- When the IIR filter is enabled, the temperature resolution is 20 bit.
- When the IIR filter is disabled, the temperature resolution is 16 + (osrs_t – 1) bit, e.g. 18 bit when osrs_t is set to ‘3’.

___
## BME280 Driver Description
### Driver Features
- Written from a standpoint of providing mechanism, not policy
- Type safety is provided and limits are checked
- NULL pointer checker (optional)
- Write verification (optional)
- BME280 connection check (optional)
- Error log message string (optional)
- Device driver handle design pattern for unlimited instances of sensors
- Dependency injection pattern for interface (allows for even remote or software mocked module)
- Can be used with SPI, I2C or software test mock
- Stateless and re-entrant
- Thread-safety with lock and unlock hooks for interface read/write (optional)
- Possible to be used with baremetal, RTOS or under any general purpose OS like Linux
- Error handling baked into the driver
- Doxygen style comments
- Config file for configurations and turning features on/off
- Altitude calculation (optional)
- Production ready

### Driver Structure
In order to compile, all .c files in the 'src' directory must be compiled and all the .h header files inside 'inc' directory must be added to include path. Application writer only edits the 'bme280_config.h' file inside 'inc' directory to turn features ON or OFF, and provides the interface function prototypes for their target platform in the 'bme280_interface.c' file in the 'src' directory. No other files need to be touched.

### Driver Use Flow
The steps of using the driver are as follows:
1. Turn optional features ON or OFF in the 'bme280_config.c' file.
2. Implement the needed interface functions either inside the 'bme280_interface.c' file or in any other custom file.
3. Inside your application, declare and define an instance of `bme280_type_handle_t`.
4. Provide the handle structure with the implemented interface functions.
5. Call the `bme280_api_init()` function.

### Config File
In the 'bme280_config.h' file, there are a list of macros that turn ON/OFF features:
1. `BME280_INCLUDE_NULL_CHECK`: Checks for NULL interface pointers inside the handle structure in every API function/macro call. If the application writer is confident in implementing and and providing the prototype function pointers there is no need for this.
2. `BME280_INCLUDE_NULL_CHECK_ONLY_INIT`: Lighter version of NULL checker that only works inside `bme280_api_init()` function. If a lighter overhead is desired and a NULL checker is still needed, this is recommended.
3. `BME280_INCLUDE_CONNECTION_CHECK`: Checks for the presence and connection of a BME280 in every API call. Recommended if the physical connection is uncertain and may drop mid-use. If defined as `1`, the `int bme280_interface_ack_test(uint8_t deviceAddress)` prototype must be implemented by the application writer.
4. `BME280_INCLUDE_WRITE_VERIFICATION`: Verifies the write operation in API functions that change settings in BME280 registers. Recommended if the connection is noisy.
5. `BME280_INCLUDE_ALTITUDE`: Defines a pair of altitude calculation API functions. These functions contain floating point operations and should be avoided in most cases unless altitude calculations are really needed.
6. `BME280_INCLUDE_SENSOR_TEMPERATURE`: Enables the `bme280_api_get_temperature` function which gets temperature individualy.
7. `BME280_INCLUDE_SENSOR_PRESSURE`: Enables the `bme280_api_get_pressure` function which gets pressure individualy.
8. `BME280_INCLUDE_SENSOR_HUMIDITY`: Enables the `bme280_api_get_humidity` function which gets humidity individualy.
9. `BME280_INCLUDE_SENSOR_ALL`: Enables the `bme280_api_get_all` function which gets all three sensors in one reading. **Please do not turn on the individual API function in the config file in case of `BME280_INCLUDE_SENSOR_ALL`, since they will be redundant.**
10. `BME280_INCLUDE_EXCLUSION_HOOK`: Enables mutual exclusion lock and unlock hooks for protection of interface bus in mutithreading. Needs a lock hook, an unlock hook and a mutex handle inside 'bme280_interface.c' in case of turning on.
11. `BME280_INCLUDE_ERROR_LOG_STRING`: Enables the `bme280_api_error_log()` function which gives an error log message in case of turning on.
12. `BME280_INCLUDE_BOSCH_RECOMMENDED_SETTINGS`: Enables the `bme280_preset_...()` macros that sets the BME280 in one of Bosch recommended settings for different applications.

### Interface Implementation
The 'bme280_interface.c' is not strictly needed in the way that is presented here. The application writer can remove 'bme280_interface.c' and 'bme280_interface.h' files and provide their own version in any form; The important thing is to implement all the needed prototypes based on the optional features and later provide the function pointers for the BME280 handle structure. **These functions must return 0 in case of success and any other integer in case of an error**. List of prototypes:
```c
int bme280_i2c_init(uint8_t deviceAddress);
int bme280_i2c_deinit(uint8_t deviceAddress);
int bme280_read_array(uint8_t deviceAddress, uint8_t startRegisterAddress, uint8_t *data, uint8_t dataLength);
int bme280_write_array(uint8_t deviceAddress, uint8_t startRegisterAddress, uint8_t *data, uint8_t dataLength);
int bme280_delay_function(uint32_t delayMS);

#if BME280_INCLUDE_ALTITUDE
int bme280_power_function(float x, float y, float *result);
#endif

#if BME280_INCLUDE_CONNECTION_CHECK
int bme280_interface_ack_test(uint8_t deviceAddress);
#endif

#if BME280_INCLUDE_EXCLUSION_HOOK
int bme280_interface_mutex_lock(void *mutex);
int bme280_interface_mutex_unlock(void *mutex);
#endif
```
As it can be seen, based on optional features set inside 'bme280_config.h' file the prototype list changes. Please note that if the config macros are to be used in custom versions, 'bme280_config.h' must be included.

### Naming Conventions
All data types are started with `bme280_type_...` and end with `_t` (function pointers ending with `_fp`. As an example:
```c
bme280_type_register_address_t
bme280_type_handle_t
bme280_type_error_code_t
/*...*/
```
All possible values of a particular data type are started with `BME280_TYPEVAL_...`. As examples:
```c
BME280_TYPEVAL_BOOL_FALSE
BME280_TYPEVAL_REGISTER_ADDRESS_P1
BME280_TYPEVAL_OVERSAMPLING_8X
```
All application usable API functions and macros are started with `bme280_api_...`. These functions/macros return an error code of type `bme280_type_error_code_t`. As examples:
```c
bme280_api_init()
bme280_api_check_chip_id()
bme280_api_set_pressure_oversampling()
```
All config macros are started with `BME280_INCLUDE_...` and are defined inside 'bme280_config.h'. As examples:
```c
BME280_INCLUDE_NULL_CHECK
BME280_INCLUDE_CONNECTION_CHECK
BME280_INCLUDE_WRITE_VERIFICATION
```
All constants are started with `BME280_CONST_...`. As example:
```c
BME280_CONST_STARTUP_DELAY_IN_MS
BME280_CONST_DEFAULT_CHIP_ID
BME280_CONST_TEMPERATURE_OVERSAMPLING_DEFAULT
```
All driver utilities are started with `__bme280_util_...`. **Application writer does not need to use these functions**. These are used by API functions indirectly. As examples:
```c
__bme280_util_null_check()
__bme280_util_raw_pressure_data()
__bme280_util_get_bits_in_register()
```
All Bosch recommended presets are presented with API macros starting with `bme280_preset_...`. These are optional. As examples:
```c
bme280_preset_humidity_sensing()
bme280_preset_indoor_navigation()
bme280_preset_gaming()
```

### Error Handling
All API functions and macros return with an error code of type `bme280_type_error_code_t`:
```c
typedef enum
{
/*no error*/
BME280_TYPEVAL_ERROR_OK = 0,
/*error in interface initialization*/
BME280_TYPEVAL_ERROR_INTERFACE_INIT,
/*error in interface de-initialization*/
BME280_TYPEVAL_ERROR_INTERFACE_DEINIT,
/*error in interface read function*/
BME280_TYPEVAL_ERROR_INTERFACE_READ,
/*error in interface write function*/
BME280_TYPEVAL_ERROR_INTERFACE_WRITE,
/*error in interface delay function*/
BME280_TYPEVAL_ERROR_INTERFACE_DELAY,
/*error in sensor ID*/
BME280_TYPEVAL_ERROR_SENSOR_ID,
/*error in polling timeout. please select a higher timeout*/
BME280_TYPEVAL_ERROR_SENSOR_POLL_TIMEOUT,
/*Invalid input in set APIs*/
BME280_TYPEVAL_ERROR_INPUT_INVALID,
/*error in null handle pointer*/
BME280_TYPEVAL_ERROR_NULL_HANDLE,
/*error in dependency function pointers*/
BME280_TYPEVAL_ERROR_NULL_INTERFACE,
/*error in interface math power function*/
BME280_TYPEVAL_ERROR_INTERFACE_MATH_POW,
/*handle to mutex does not exist*/
BME280_TYPEVAL_ERROR_NULL_MUTEX_HANDLE,
/*error in exclusion lock function*/
BME280_TYPEVAL_ERROR_EXCLUSION_LOCK,
/*error in exclusion unlock function*/
BME280_TYPEVAL_ERROR_EXCLUSION_UNLOCK,
/*error in verifying the write operation to BME280*/
BME280_TYPEVAL_ERROR_VERIFICATION_FAIL,
/*error in sensor connection*/
BME280_TYPEVAL_ERROR_BME280_NOT_CONNECTED
} bme280_type_error_code_t;
```
In which `0` or `BME280_TYPEVAL_ERROR_OK` means no error. Error log message strings are enabled with `BME280_INCLUDE_ERROR_LOG_STRING` in config file and using `bme280_api_error_log()` function API. As an example:
```c
bme280_type_handle_t handle;
bme280_type_error_code_t error;
char *error_message;

/*...*/
error = bme280_api_init(&handle);
bme280_api_error_log(error, &error_message);

/*perror() is application specific*/
perror(error_message);
```

### Mutual Exclusion
In order to avoid race conditions, shared resources must be protected using mutual exclusion. I2C or SPI bus are shared resources and accessing them must be protected. Mutual exclusion is made possible with lock and unlock hooks (optional). In order to turn mutual exclusion on, set the corresponding macro in the 'bme280_config.h' file:
```c
/*Inside bme280_config.h*/
#define BME280_INCLUDE_EXCLUSION_HOOK 1
```
This will open up the function prototypes for mutex lock and unlock hooks in 'bme280_interface.c' and 'bme280_interface.h' files. The next step will be filling these two function prototypes inside 'bme280_interface.c' file:
```c
/*Inside bme280_interface.c*/
int bme280_interface_mutex_lock(void *mutex)
{
/*cast the mutex handle pointer provided by operating system*/
/*mutex lock operation based on your operating system API*/
/*return 0 in case of no error, any other number in case of errors*/
return 0;
}

int bme280_interface_mutex_unlock(void *mutex)
{
/*cast the mutex handle pointer provided by operating system*/
/*mutex unlock operation based on your operating system API*/
/*return 0 in case of no error, any other number in case of errors*/
return 0;
}
```
The next step is to provide the BME280 interface handle with these prototypes in the application:
```c
/*Inside your application file*/
#include "bme280_interface.h"

bme280_type_handle_t handle;

void application_main()
{
handle.dependency_interface.bme280_interface_exclusion.bme280_interface_lock = bme280_interface_mutex_lock;

handle.dependency_interface.bme280_interface_exclusion.bme280_interface_unlock = bme280_interface_mutex_unlock;

handle.dependency_interface.bme280_interface_exclusion.mutex_handle = (void *)mutex_handle_pointer;

/*...*/
}
```
As an example in FreeRTOS, the mutex can be created and used like this:
```c
/*Inside your main function*/
SemaphoreHandle_t I2C_mutex = xSemaphoreCreateMutex();

if(I2C_mutex == NULL)
{
error();
}

/*Inside your bme280 gatekeeper task*/
handle.dependency_interface.bme280_interface_exclusion.mutex_handle = (void *)&I2C_mutex;

/*Inside your bme280_interface.c*/
int bme280_interface_mutex_lock(void *mutex)
{
if(xSemaphoreTake(*((SemaphoreHandle_t *)mutex), portMAX_DELAY) == pdFALSE)
{
return 1;
}

return 0;
}

int bme280_interface_mutex_unlock(void *mutex)
{
if(xSemaphoreGive(*((SemaphoreHandle_t *)mutex)) == pdFALSE)
{
return 1;
}

return 0;
}
```
>**ATTENTION**: The mutex lock and unlock feature in the driver only protects the interface access (I2C or SPI bus) in a gatekeeper task with a BME280 handle instance exclusive to one task/thread. If the application shares the same BME280 handle instance among multiple tasks, such a situation must be protected by the application using an additional lock on all API accesses.

### NULL Check
To avoid passing NULL pointers to BME280 handle, NULL pointer checks are added "optionally" to all API functions, which can be turned on in config file using `BME280_INCLUDE_NULL_CHECK`. If code size and latency are issues but NULL checking is still needed, application writer can use `BME280_INCLUDE_NULL_CHECK_ONLY_INIT` which only turns on NULL checking for `bme280_api_init()` function. The second method is recommended.

### Connection Check
If the connection to a BME280 module is uncertain, application writer can add optional connection checking which tests the connection inside every API function using `BME280_INCLUDE_CONNECTION_CHECK` in the config file. If turned on, the `int bme280_interface_ack_test(uint8_t deviceAddress)` must be provided by the application writer, that sends a dummy byte to the BME280 module in order to test the connection and returns `0` in case of success.

### Write Verification
In a noisy and uncertain environment, write verification operation is possible using `BME280_INCLUDE_WRITE_VERIFICATION` in the config file. If turned on, the driver verifies the write operations on the BME280 registers.

### Modes of Operation
Mode of operation can be changed with:
```c
bme280_api_set_mode();
```
BME280 has 3 modes of operation:
1. NORMAL mode (`BME280_TYPEVAL_MODE_NORMAL`)
2. FORCED mode (`BME280_TYPEVAL_MODE_FORCED`)
3. SLEEP mode (`BME280_TYPEVAL_MODE_SLEEP)

In SLEEP mode, sensor values are not updated. In NORMAL mode, sensor values are updated in a period of standby time, which can be set with:
```c
bme280_api_set_standby_time();
```
Which accepts a standby time value of type `bme280_type_standby_time_t`. In FORCED mode, the sensor reading values are updated only once and the mode of operation changes automatically back to SLEEP mode. **In order to use this mode of operation, the application writer must pay attention to set mode to FORCED each time a sensor reading is desired.**

### Sensors Reading API
Generally, reading sensors values is possible in two ways:
1. Individual sensor reading
2. All-in-one sensors reading

In case of individual readings, One, two or three (better to use all-in-one reading in this case) sensors are enabled using macros `BME280_INCLUDE_SENSOR_TEMPERATURE`, `BME280_INCLUDE_SENSOR_PRESSURE` and `BME280_INCLUDE_SENSOR_HUMIDITY` inside config file:
```c
bme280_api_get_temperature();
bme280_api_get_pressure();
bme280_api_get_humidity();
```
In case of All-in-one reading, one API is enabled using:
`BME280_INCLUDE_SENSOR_ALL` inside config file:
```c
bme280_api_get_all();
```
**Please do not mix individual APIs with all-in-one API because the individual APIs would be redundant.**

### Sensors Oversampling
BME280 consists of 3 sensors: temperature, pressure and humidity. BME280 provides oversampling for these three sensors including an option of `BME280_TYPEVAL_OVERSAMPLING_0X` oversampling that means turning that sensor OFF:
```c
bme280_api_set_temperature_oversampling(...);
bme280_api_set_pressure_oversampling(...);
bme280_api_set_humidity_oversampling(...);
```
**Turning temperature sensor OFF is not recommended, since the other two sensor readings compensation need temperature value.**

### IIR Filter
The IIR filter (Infinite Impulse Response filter) in the BME280 is a built-in digital low pass filter. Its purpose is to reduce short term fluctuations in the sensor output that come from environmental changes or sensor noise. Without IIR filter (set to `BME280_TYPEVAL_FILTER_OFF`), each measurement is reported exactly as ADC converts it; So if there's a sudden pressure spike from moving the sensor or wind gusts it will be seen directly on the output. With IIR filter enabled, the BME280 applies a smoothing function to each new measurement. Use the filter enabled for applications like altimeter, weather stations or room monitoring, and filter disabled for fast reaction applications.
```c
bme280_api_set_iir_filter_coefficient();
```

### Temperature Calculation
In order to avoid floating point operations, the driver API returns a signed 32 bit integer value for temperature **multiplied in 100**. In order to read the floating point value:
```c
int32_t read_temp;
float float_temp;

if(bme280_api_get_temperature(&handle, &read_temp) != BME280_TYPEVAL_ERROR_OK)
{
/*handle error*/
}

float_temp = (float)read_temp / 100;
```
In order to avoid floating point:
```c
int32_t read_temp;
int32_t integer_temp;

if(bme280_api_get_temperature(&handle, &read_temp) != BME280_TYPEVAL_ERROR_OK)
{
/*handle error*/
}

integer_temp = read_temp / 100;
```
Please note that in this example the decimal value of temperature is omitted.

### Humidity Calculation
In order to avoid floating point operations, the driver API returns an unsigned 32 bit integer value for humidity **multiplied in 1024**. In order to read the floating point value:
```c
uint32_t read_humidity;
float float_humidity;

if(bme280_api_get_humidity(&handle, &read_humidity) != BME280_TYPEVAL_ERROR_OK)
{
/*handle error*/
}

float_humidity = (float)read_temp / 1024;
```
In order to avoid floating point:
```c
uint32_t read_humidity;
uint32_t integer_humidity;

if(bme280_api_get_humidity(&handle, &read_humidity) != BME280_TYPEVAL_ERROR_OK)
{
/*handle error*/
}

integer_humidity = read_temp / 1024;
```
Please note that in this example the decimal value of humidity is omitted.

### Altitude Calculation
Altitude calculation is optionally enabled with `BME280_INCLUDE_ALTITUDE` inside the config file. If enabled, two similar API functions are added: One requiring barometric pressure, the other requiring both barometric pressure and ambient temperature:
```c
bme280_api_calculate_altitude_quick(...);
bme280_api_calculate_altitude_hypsometric(...);
```
Enabling these functions will need a math power function in interface file:
```c
int bme280_power_function(float x, float y, float *result);
```
>**Please note that these functions use floating point math and are therefore heavy on code size and latency.**

### Bosch Recommended Settings
Bosch has recommended oversampling, IIR filter, mode of operation and standbyt time settings for *weather monitoring*, *humidity sensing*, *indoor navigation* and *gaming* in the BME280 datasheet. These presets can be turned on and used with `BME280_INCLUDE_BOSCH_RECOMMENDED_SETTINGS` in the config file which adds these macros to the API:
```c
bme280_preset_weather_monitoring();
bme280_preset_humidity_sensing();
bme280_preset_indoor_navigation();
bme280_preset_gaming();
```

---
## API List
```c
bme280_type_error_code_t bme280_api_init(bme280_type_handle_t *handle, bme280_type_hardware_interface_t hw_interface, bme280_type_i2c_address_t i2c_address);

bme280_type_error_code_t bme280_api_deinit(bme280_type_handle_t *handle);

bme280_type_error_code_t bme280_api_check_chip_id(const bme280_type_handle_t *bme280_handle);

bme280_type_error_code_t bme280_api_reset(bme280_type_handle_t *handle);

bme280_type_error_code_t bme280_api_set_mode(bme280_type_handle_t *handle, bme280_type_operation_mode_t operation_mode);

bme280_api_set_pressure_oversampling(handle_pointer, os_value);

bme280_api_set_temperature_oversampling(handle_pointer, os_value);

bme280_api_set_humidity_oversampling(handle_pointer, os_value);

bme280_api_set_standby_time(handle_pointer, standby_time);

bme280_api_set_iir_filter_coefficient(handle_pointer, filter_coefficient);

bme280_type_error_code_t bme280_api_get_mode(bme280_type_handle_t *handle, bme280_type_operation_mode_t *mode);

bme280_api_get_temperature_oversampling(handle_pointer, temperature_oversampling_pointer);

bme280_api_get_pressure_oversampling(handle_pointer, pressure_oversampling_pointer);

bme280_api_get_humidity_oversampling(handle_pointer, humidity_oversampling_pointer);

bme280_api_get_standby_time(handle_pointer, standby_time_pointer);

bme280_api_get_iir_filter_coefficient(handle_pointer, filter_coefficient_pointer);

bme280_type_error_code_t bme280_api_get_temperature(bme280_type_handle_t *handle, int32_t *temperature);

bme280_type_error_code_t bme280_api_get_pressure(bme280_type_handle_t *handle, uint32_t *pressure);

bme280_type_error_code_t bme280_api_get_humidity(bme280_type_handle_t *handle, uint32_t *humidity);

bme280_type_error_code_t bme280_api_get_all(bme280_type_handle_t *handle, bme280_type_sensors_data_t *sensor_data);

bme280_type_error_code_t bme280_api_calculate_altitude_quick(bme280_type_handle_t *handle, uint32_t barometric_pressure, float *alt);

bme280_type_error_code_t bme280_api_calculate_altitude_hypsometric(bme280_type_handle_t *handle, uint32_t barometric_pressure, float ambient_temperature_in_C, float *alt);

bme280_type_error_code_t bme280_api_spi_3wire(const bme280_type_handle_t *handle, bme280_type_bool_t enable);

bme280_type_error_code_t bme280_api_error_log(bme280_type_error_code_t error, char **message);

bme280_preset_weather_monitoring(handle_pointer);

bme280_preset_humidity_sensing(handle_pointer);

bme280_preset_indoor_navigation(handle_pointer);

bme280_preset_gaming(handle_pointer);
```