Introduction

Smablo Smoke Sensor is optical particle detection sensor based on MAX30105 sensor that allows you to detect fire in the surrounding area.

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Applications

Smoke module can be used indoors or outdoors, depending on business needs. It’s typical applications:

  • Fire Alarms
  • Smoke Detectors for Building Automation
  • Smoke Detectors for Mobile Devices
  • Smoke Detectors for Wearable Devices

Getting started

To get started with Smablo weather sensor you will need :

From Smablo development kit take Smablo CPU Shield and place it on Smablo Development board and do the same with Smablo Smoke Shield just as you can see on the video below.

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

{.force-inline} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {.force-inline} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {.force-inline} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

When you’ve done connecting Shields you can connect Smablo Development board to your computer with USB cable.

Example programs

Smablo prepared demo project to show you how to use Smablo Smoke Sensor. To see how to use it open Visual Studio Code and Click file->Open folder and from your libsmablo/examples directory choose smoke example just like it was shown on the videos below.

smoke

To see how to use Smablo Smoke Sensor let’s open Visual Studio Code and Click file->Open folder and from your libsmablo/examples directory choose smoke demo code. Example will show the quantity of particles from IR and RED color LED.

Open smoke demo code just like it was shown on the video below:

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

To see how the smoke works compile and run the project by pressing F5 button just like on the video below:

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

And in the RTT Viewer window you should see all the measurements.

Minimal code

Basic example code will show you how to program with Smablo Shields and driver. You should always program you projects in this sequence.

#ifdef NRF_LOG_MODULE_NAME
#undef NRF_LOG_MODULE_NAME
#endif

#define NRF_LOG_MODULE_NAME "test_max30105.c"

//1
#include "nrf_log.h"
#include "drv_max30105.h"

//2
static max30105_instance_t max30105_instance=SM_MAX30105_INSTANCE;

//'FIFO almost full' interrupt handler
static inline void fifo_data_handler(max30105_instance_t* const p_instance)
{
    //trigger temperature measurement
    max30105_trigger_temp_blocking(p_instance);

    //decode fifo data
    max30105_fifo_data_t fifo_data;
    max30105_decode_fifo(p_instance, &fifo_data);

    for(uint8_t i=0; i<fifo_data.sample_count;i++)
    {
        NRF_LOG_RAW_DEBUG("Sample %u: RED: %u, IR: %u\r\n", i, fifo_data.RED[i], fifo_data.IR[i]);
    }

}

//10
//main interrupt handler
static void max30105_int_handler(max30105_instance_t* const p_instance)
{
    //get bitfield with active interrupt flags
    uint8_t int_flags=max30105_decode_int_flags(p_instance);

    //check which interrupts are active
    for(uint8_t i=0; i<7; i++)
    {
        uint8_t flag=(1<<i);
        if(!(int_flags & flag)) continue;

        switch((max30105_int_t)flag)
        {
            case MAX30105_INT_A_FULL: ///< FIFO Almost Full Flag
                NRF_LOG_RAW_DEBUG("MAX30105_INT_A_FULL\r\n");
                fifo_data_handler(p_instance);
                break;
            case MAX30105_INT_DIE_TEMP_RDY: ///< Internal Temperature Ready Flag
                NRF_LOG_RAW_DEBUG("MAX30105_INT_DIE_TEMP_RDY: "NRF_LOG_FLOAT_MARKER" degC\r\n", NRF_LOG_FLOAT(max30105_decode_temp(p_instance)));
                break;

            default:
                break;
        }
    }
}

void test_max30105_main(void)
{
    //3
    //initialize driver
    max30105_init(&max30105_instance, max30105_int_handler);

    //4
    //set particle sensing mode with 2 leds
    max30105_configure_mode(&max30105_instance, MAX30105_MODE_PARTICLE_2_LED);

    //5
    //enable 'FIFO almost full' and 'temperature ready' interrupts
    max30105_reg_int_enable_t int_enable={
        .regs.A_FULL_EN=1, 
        .regs.DIE_TEMP_RDY_EN=1
    };
    max30105_configure_int(&max30105_instance, &int_enable);

    //6
    //set sampliog parameters
    max30105_adc_cfg_t adc_cfg={
        .sample_rate=MAX30105_SR_100SPS,
        .resolution=MAX30105_RES_16BIT
    };
    max30105_configure_adc(&max30105_instance, &adc_cfg);

    //7
    //set fifo parameters
    max30105_fifo_cfg_t fifo_cfg={
        .fifo_a_full=2,
        .sample_avg=MAX30105_SMP_AVE_2
    };
    max30105_configure_fifo(&max30105_instance, &fifo_cfg);

    //8
    //turn on IR and RED leds used by selected mode
    max30105_led_cfg_t led_cfg={
        .led1_current_ma=4,
        .led2_current_ma=4,
    };
    max30105_configure_leds(&max30105_instance, &led_cfg);

    //9
    //write settings to the device
    max30105_commit_blocking(&max30105_instance);
}

In point 1 we need to include all the libraries that we will need to work with:

  • drv_max30105.h driver is the main Smoke Shield driver holding all the functions to configure and use the shield.
  • #include "nrf_log.h" that help us debug the programs and let us show sentencies and data on screen with use of RTT Viewer.

In point 2 we are creating the instance of the Smablo Smoke Shield with static max30105_instance_t max30105_instance. Instance will hold all of the current registers values and configuration of the module. SM_MAX30105_INSTANCE macro holds all the default values of the shield and it is recomended to use it.

In point 3 we are initializing the Smoke Shield with the max30105_instance instance using max30105_init(). We need to do it only once at the begining of the program. In max30105_init() as a second parameter we are also giving the max30105_int_handler handler function that will be executed every time the sensor will send an interrupt.

In point 4 we configure instance with data acquisition mode using max30105_configure_mode(). In this example we configure the shield to get the measurements on red color and IR LED with MAX30105_MODE_PARTICLE_2_LED.

In point 5 we configure the FIFO almost full' and 'temperature ready' interrupts. To configure these interrupts we need to create max30105_reg_int_enable_t type structure in this case called int_enable, configure the interrupts we want and then use it in max30105_configure_int() function that will configure the instance with the structure. Every time these interrupts occur the max30105_int_handler() will be executed.

In point 6 we configure the sampling rate with max30105_configure_adc(). To do this we need to create max30105_adc_cfg_t type structure in which we configure particle sensing ADC Range Control, particle sensing Sample Rate Control (Using 2 LEDs) and LED Pulse Width Control and ADC Resolution. In our example we are setting our sampling rate to MAX30105_SR_100SPS 100 samples per second and resolution to MAX30105_RES_16BIT 16 bit.

In point 7 to use FIFO we need to configure it first with max30105_configure_fifo() function. Firstly we need to create and configure max30105_fifo_cfg_t type structure. In this case we are setting fifo_a_full parameter to 2, this sets how many samples ahead of FIFO full event will trigger interrupt and sample_avg sample averaging to 2 to average 2 samples.

In point 8 we need to turn on IR and RED LEDs used by selected mode using max30105_configure_leds() . Firstly we need to crate and configure max30105_led_cfg_t structure. In our case we are setting the current t first and second LED to 4 mA.

In point 9 we are sending our configurated instance to the shield with max30105_commit_blocking() function. All the confuguration will take place after this function is executed.

In point 10 in our handler function we are checking which event generated an interrupt with max30105_decode_int_flags() and depending whcich flag is turned on execute correct user defined action for it.

drv_max30105 driver reference

To use this driver you need to include it to your project with #include statement. It is also important that before using any of the driver functions create instance of the module:

///max30105 driver instance
static max30105_instance_t max30105_instance=SM_MAX30105_INSTANCE;

The example of usage if instance was showan in Minimal code snippet.

max30105_init

Prototype:

void max30105_init(max30105_instance_t* const p_instance, max30105_int_handler_t int_handler);

Function is used for initialize the shield. Use it once at the beginning of our program. Function takes two parameters. The first is pointer to max30105_instance_t type instance which you need to create earlier and the second one is int_handler handler function that will be executed every time an interrupy occurs. For your coinvenience the SM_MAX30105_INSTANCE macro was created and it is recommended for use this macro to set the default values to all instance registers so they match the values of the real registers on the shield. The example use of the function was shown in Minimal code snippet.

max30105_reset

Prototype:

void max30105_reset(max30105_instance_t* const p_instance);

Function is used for performing reset thus all configuration, threshold, and data registers are reset to their power-on-state througha power-on reset. Function takes one parameter which is pointer to max30105_instance_t type instance. The example use of the function was shown below:

#include "drv_max30105.h"

//create instance of smoke shield 
static max30105_instance_t max30105_instance=SM_MAX30105_INSTANCE;

void test_max30105_main(void)
{
    //initialize driver
    max30105_init(&max30105_instance, max30105_int_handler);

    //perform reset
    max30105_reset(&max30105_instance, max30105_int_handler);
}

max30105_configure_power

Prototype:

void max30105_configure_power(max30105_instance_t* const p_instance, const max30105_shdn_state_t power_cfg);

Function is used for configuration of power state of the shield. Function takes 2 parameters:

  • p_instance type max30105_instance_t which is Smoke Shield instance address.
  • sampling_cfg type max30105_shdn_state_t which is the shield power state. The power state of the shield can be chosen from max30105_shdn_state_t enum:
///possible values of max30105_reg_mode_cfg_t::SGDN
typedef enum
{
    MAX30105_POWER_ON=0,    ///< power on, data acquisition active
    MAX30105_POWER_OFF      ///< power saving mode 

} max30105_shdn_state_t;

By default the power state of the shield is turned on. While in power-save mode, all registers retain their values, and we can still configure and read the data from the shield. All interrupts are cleared to zero in this mode. The code snippet below shows how to turn the shield in to power saving mode.

#include "drv_max30105.h"

//create instance of smoke shield 
static max30105_instance_t max30105_instance=SM_MAX30105_INSTANCE;

void test_max30105_main(void)
{
    //initialize driver
    max30105_init(&max30105_instance, max30105_int_handler);

    //configure shield into power saving mode
    max30105_configure_power(&max30105_instance, MAX30105_POWER_OFF);

    //write settings to the device
    max30105_commit_blocking(&max30105_instance);

}

max30105_configure_int

Prototype:

void max30105_configure_int(max30105_instance_t* const p_instance, const max30105_reg_int_enable_t* const p_int_enable);

Function is used for configurating power mode and oversampling rate. Function takes 3 parameters :

  • p_instance type max30105_instance_t which is Smoke Shield instance.
  • p_int_enable type max30105_reg_int_enable_t that configures interrupts of the shield. To use this function we need to create max30105_reg_int_enable_t and populate it with interrupts we want:
/**
    \brief Interrupt Enable (0x02–0x03)

    Each source of hardware interrupt, with the exception of power ready, 
    can be disabled in a software register within the MAX30105 IC. 
    The power-ready interrupt cannot be disabled because the digital state of 
    the module is reset upon a brownout condition (low power supply voltage), 
    and the default condition is that all the interrupts are disabled. 
    Also, it is important for the system to know that a brownout condition has occurred, 
    and the data within the module is reset as a result.
    The unused bits should always be set to zero for normal operation.
*/
typedef union 
{
    struct
    {
        const uint8_t   res1:4;             ///< reserved, write as 0
        uint8_t         PROX_INT_EN:1;      ///< Set this bit to enable proximity threshold interrupt
        uint8_t         ALC_OVF_EN:1;       ///< Set this bit to enable Ambient Light Cancellation Overflow interrupt
        uint8_t         DATA_RDY_EN:1;      ///< Set this bit to enable data ready interrupt
        uint8_t         A_FULL_EN:1;        ///< Set this bit to enable FIFO almost full interrupt
        const uint8_t   res2:1;             ///< reserved, write as 0
        uint8_t         DIE_TEMP_RDY_EN:1;  ///< Set this bit to enable die temp ready interrupt
        const uint8_t   res3:6;             ///< reserved, write as 0

    } regs;

    uint8_t raw[2];

} max30105_reg_int_enable_t;

The usage of the the function was shown in the Minimal code snippet.

max30105_configure_adc

Prototype:

void max30105_configure_adc(max30105_instance_t* const p_instance, const max30105_adc_cfg_t* const p_adc_cfg);

Function is used for configuring ADC settings. Function takes two parameter:

  • p_instance type max30105_instance_t which is Smoke Shield instance.
  • p_adc_cfg type max30105_adc_cfg_t that control ADC. To use the function we need to create and populate the structure with wanted configuration:
///ADC configuration struct
typedef struct
{
    max30105_adc_rge_state_t    adc_range;      ///< Particle-Sensing ADC Range Control
    max30105_sr_state_t         sample_rate;    ///< Particle-Sensing Sample Rate Control (Using 2 LEDs)
    max30105_res_state_t        resolution;     ///< LED Pulse Width Control and ADC Resolution

} max30105_adc_cfg_t;
  • adc_range is controling the Particle-Sensing ADC range which we can choose from max30105_adc_rge_state_t structure

    ///Possible values for max30105_reg_particle_cfg_t::ADC_RGE
    typedef enum
    {
        MAX30105_ADC_RGE_2048nA=0,  ///< 7.81 nA per LSB,   2048 nA range (18bit mode)
        MAX30105_ADC_RGE_4096nA,    ///< 15.63 nA per LSB,  4096 nA range (18bit mode)
        MAX30105_ADC_RGE_8192nA,    ///< 31.25 nA per LSB,  8192 nA range (18bit mode)
        MAX30105_ADC_RGE_16384nA    ///< 62.5 nA per LSB,   16384 nA range (18bit mode)
    
    } max30105_adc_rge_state_t;
  • sample_rate is a Particle-Sensing Sample Rate Control the effective sampling rate with one sample consisting of one IR pulse/conversion and one RED pulse/conversion. The sample rate and pulse width are related in that the sample rate sets an upper bound on the pulse width time. If the user selects a sample rate that is too high for the selected LED Pulse Width Control setting, the highest possible sample rate is programmed instead into the register. Sample rate can be configure with max30105_sr_state_t structure:

    ///possible values for max30105_reg_particle_cfg_t::SR
    typedef enum
    {
        MAX30105_SR_50SPS=0,    ///< 50 samples per second
        MAX30105_SR_100SPS,     ///< 100 samples per second
        MAX30105_SR_200SPS,     ///< 200 samples per second
        MAX30105_SR_400SPS,     ///< 400 samples per second
        MAX30105_SR_800SPS,     ///< 800 samples per second
        MAX30105_SR_1000SPS,    ///< 1000 samples per second
        MAX30105_SR_1600SPS,    ///< 1600 samples per second
        MAX30105_SR_3200SPS     ///< 3200 samples per second
    
    } max30105_sr_state_t;
  • resolution is a LED Pulse Width Control and ADC Resolution. LED pulse width (the IR, Red, and Green have the same pulse width), and therefore, indirectly sets the integration time of the ADC in each sample. The ADC resolution is directly related to the integration time. We can choose it from max30105_res_state_t:

    ///possible values for max30105_reg_particle_cfg_t::LED_PW
    typedef enum
    {
        MAX30105_RES_15BIT=0,   ///< 69us pulse,    15 bits ADC resolution
        MAX30105_RES_16BIT,     ///< 118us pulse,   16 bits ADC resolution
        MAX30105_RES_17BIT,     ///< 215us pulse,   17 bits ADC resolution
        MAX30105_RES_18BIT      ///< 411us pulse,   18 bits ADC resolution
    
    } max30105_res_state_t;

    The usage of the the function was shown in the Minimal code snippet.

max30105_configure_fifo

Prototype:

void max30105_configure_fifo(max30105_instance_t* const p_instance, const max30105_fifo_cfg_t* const p_fifo_cfg);

Function is used for FIFO configuration. Function takes 2 parameters:

  • p_instance type max30105_instance_t which is Smoke Shield instance.
  • p_fifo_cfg type max30105_fifo_cfg_t structure that we need to populate.

    ///FIFO configuration struct
    typedef struct
    {
        uint8_t                                 fifo_a_full;    ///< how many samples ahead of FIFO full event will trigger interrupt. See max30105_reg_fifo_cfg_t::FIFO_A_FULL
        bool                                    fifo_rollover;  ///< FIFO rollover enable.
        max30105_reg_fifo_cfg_smp_ave_state_t   sample_avg;     ///< sample averaging and decimation setting.
    
    } max30105_fifo_cfg_t;
    • fifo_a_full This register sets the trigger for the FIFO_A_FULL interrupt. For example, if set to 0x0F, the interrupt triggers when there are 15 empty space left (17 data samples), and so on trigger at 32-FIFO_A_FULL samples in the FIFO. If there are specified number of free spaces in FIFO left the interrupt will be set.
    • fifo_rollover setting this bit enables FIFO rollover feature
    • sample_avg

bme280_trigger_sampling

Prototype:

void bme280_trigger_sampling(bme280_instance_t* const p_instance, bme280_async_handler_t handler, bme280_async_ctx_t* const p_ctx)

Function is used for triggering single measurement when Weather Shield is in forced(default) mode in asynchronous manner which means that other actions can take place during execution of this function. Function takes parameters:

  • p_instance type bme280_instance_t which is Weather shield instance address.
  • handler type bme280_async_handler_t which is pointer to user handler function that will be called after bme280_trigger_sampling function executes
  • p_ctx type bme280_async_ctx_t
///BME280 async context
typedef struct
{
    bme280_instance_t* p_instance;      ///< Pointer to driver instance
    bme280_async_handler_t handler;     ///< Pointer to event handler
} bme280_async_ctx_t;

which is asynchronous context data structure which is needed in asynchronous functions. If you want to use this function you need to create this type of structure earlier. The example use of this function was shown below:

#include "nrf_log.h"
#include "sm_delay.h"
#include "drv_bme280.h"

//create instance of weather shield 
static bme280_instance_t bme280_instance=SM_BME280_INSTANCE;
1.
//asynchronous contex structure
static bme280_async_ctx_t async_contex;

2.
//trigger handler
static void trigger_async_handler(bme280_instance_t* const instance)
{
    SM_DELAY_MS(10);
    //get the measurements 
    bme280_get_measurement_data_blocking(&bme280_instance);

     //decode raw measurments to floats data  
    bme280_measurement_data_t data;
    bme280_decode_measurement_data(instance, &data);

    //print data on screen
    NRF_LOG_RAW_DEBUG("  P:"NRF_LOG_FLOAT_MARKER"Pa\r\n", NRF_LOG_FLOAT(data.pressure));
}

void example_func(void)
{

    //Initialize Weather Shield
    bme280_init(&bme280_instance);

    //select which data we want to measure 
    bme280_sampling_cfg_t measurements = 
    {
        .press_sampling=BME280_OVS_1X,
    };

    //configure Weather Shield with measurements structure
    bme280_configure_sampling(&bme280_instance,&measurements);

    //Send our configurations to the Smablo Weather Shield
    bme280_commit_blocking(&bme280_instance); 
3.
    //trigger single measurement 
    bme280_trigger_sampling(&bme280_instance, trigger_async_handler, &async_contex);

}

In point 1 we are creating the asynchronous contex structure.

In point 2 we are creating the user defined handler that will be executed after bme280_trigger_sampling function executes .

In point 3 we are triggering one time measurement. After triggering the measurement trigger_async_handler will be executed.

bme280_get_measurement_data_blocking

Prototype:

void bme280_get_measurement_data_blocking(bme280_instance_t* const p_instance)

Function is used for reading humidity, temperature and pressure data from the Shield if they were set in the bme280_configure_sampling() function in blocking manner which means that no other action can take place during the transaction. . Function takes one parameter : p_instance type bme280_instance_t which is Weather shield instance address.

Be aware that this function will read all the data(humidity, temperature, pressure ) from the shield and if the sample this data was not set in the bme280_configure_sampling function the reading of that data will be false. More info in bme280_configure_sampling

bme280_get_measurement_data

Prototype:

void bme280_get_measurement_data(bme280_instance_t* const p_instance, bme280_async_handler_t handler, bme280_async_ctx_t* const p_ctx);

Function is used for reading humidity, temperature and pressure data from the Shield if they were set in the bme280_configure_sampling() function in asynchronous manner. Function takes 3 parameters :

  • p_instance type bme280_instance_t which is Weather shield instance address.
  • handler type bme280_async_handler_t which is pointer to user handler function that will be executed all data is read
  • p_ctx type bme280_async_ctx_t
  • ///BME280 async context
    typedef struct
    {
    bme280_instance_t* p_instance;      ///< Pointer to driver instance
    bme280_async_handler_t handler;     ///< Pointer to event handler
    } bme280_async_ctx_t;

    which is asynchronous context data structure which is needed in asynchronous functions. If you want to use this function you need to create this type of structure earlier. The example use of this function was shown below:

#include "nrf_log.h"
#include "sm_delay.h"
#include "drv_bme280.h"

//create instance of weather shield 
static bme280_instance_t bme280_instance=SM_BME280_INSTANCE;
1.
//asynchronous contex helper structure
static bme280_async_ctx_t async_contex;
2.
//asynchronous contex handler
static void async_handler(bme280_instance_t* const instance)
{
  //decode raw measurments to floats data  
    bme280_measurement_data_t data;
    bme280_decode_measurement_data(instance, &data);

    //print data on screen
    NRF_LOG_RAW_DEBUG("  P:"NRF_LOG_FLOAT_MARKER"Pa\r\n", NRF_LOG_FLOAT(data.pressure));
}

void example_func(void)
{

    //Initialize Weather Shield
    bme280_init(&bme280_instance);

    //select which data we want to measure 
    bme280_sampling_cfg_t measurements = 
    {
        .press_sampling=BME280_OVS_1X,
    };

    //configure Weather Shield with measurements structure
    bme280_configure_sampling(&bme280_instance,&measurements);

    //Send our configurations to the Smablo Weather Shield
    bme280_commit_blocking(&bme280_instance); 

    //trigger single measurement 
    bme280_trigger_sampling_blocking(&bme280_instance);

     //wait for measurement to complete
    SM_DELAY_MS(10);
3.
    //get the measurements 
    bme280_get_measurement_data(&bme280_instance, async_handler, &async_contex);

}

In point 1 we are creating the asynchronous contex structure.

In point 2 we are  creating the user defined handler that will be executed after `bme280_get_measurement_data` function executes . 

In point 3 we are getting the data from the shield. After reading the measurments fromthe shield `async_handler` will be executed. 

Be aware that this function will read all the data(humidity, temperature, pressure ) from the shield and if the sampling of this data was not set in the bme280_configure_sampling function the reading of that data will be false. More info in bme280_configure_sampling

bme280_decode_measurement_data

Prototype:

void bme280_decode_measurement_data(bme280_instance_t* const p_instance, bme280_measurement_data_t* const p_data)

Function is used for decoding the that was read from shield with bme280_get_measurement_data_blocking() or bme280_get_measurement_data() functions. Function takes 2 parameters:

  • p_instance type bme280_instance_t which is Weather shield instance address.
  • p_data type bme280_measurement_data_t

    
    ///Struct for storing result of sensor data conversion
    typedef struct
    {
    float temperature;      ///< Temperature in Centigrade
    float humidity;         ///< Humidity in %Rh
    float pressure;         ///< Pressure in Pa
    } bme280_measurement_data_t;
    

    which is pointer to structure data you need to create earlier. Structure holds decoded measurements of temperature, humidity and pressure saved as floats. The example use of this function was shown in Measure using autosampling and Minimal code

Advanced

Measurement time

The active measurement time depends on the selected values for humidity, temperature and pressure oversampling and can be calculated in milliseconds using the formulas below.

You can find the oversampling values in bme280 datasheet in page 27 or in the tables below:

For example, using temperature oversampling ×1, pressure oversampling ×4 and no humidity measurement, the measurement time is:

Response time using IIR filter

When using the IIR filter, the response time of the sensor depends on the selected filter coefficient and the data rate used. It can be calculated using the following formula:

You can find the oversampling values in bme280 datasheet in page 16 or in the tables below:

For the example above with a data rate of 13.51 Hz, the user could select a filter coefficient of 8. According to Table 6, the number of samples needed to reach 75% of a step response using this filter setting is 11. The response time with filter is therefore:

Measurement rate in forced mode

In forced mode, the measurement rate depends on the rate at which it is forced by the master. The highest possible frequency in Hz can be calculated as:

If measurements are forced faster than they can be executed, the data rate saturates at the attainable data rate. For the example from Measurement time with 11.5 ms measurement time, the typically achievable output data rate would be:

Measurement rate in normal mode

The measurement rate in normal mode depends on the measurement time and the standby time and can be calculated in Hz using the following formula:

The accuracy of tstandby is described in the specification parameter Δtstandby. For the example from Measurement time with 11.5 ms measurement time, setting normal mode with a standby time of 62.5 ms from table below would result in a data rate of:

Current consumption

The current consumption depends on the selected oversampling settings, the measurement rate and the sensor mode, but not on the IIR filter setting. It can be calculated as:

Note that the only difference between forced and normal mode current consumption is that the current for the inactive time is either IDDSL or IDDSB.

For the example above, the current would be

Parameters for most common use cases

For most common uses at page 17 in bme280 datasheet there recommended modes of operation for weather, humidity sensing, indoor navigation and gaming. For example for Weather monitoring there is table that describes what to measure and what parameters to set :

You can use these paramters in your projects or model your own that suiuts your needs.