Smablo Air Quality Shield is based on the BME680 sensor which can measure gas, humidity, pressure and temperature.
Air quality module allows you to monitor indoor air quality and present it in form of Air-quality EPA Index. In simple words, it shows if air quality conditions are good, unhealthy or hazardous:
To get started with Smablo Air Quality Shield you will need:
TFrom Smablo Development Kit take Smablo CPU Shield and place it on Smablo Development board and do the same with Smablo Air Quality Shield just as you can see on the pictures and video below:
{.force-inline}
{.force-inline}
{.force-inline}
{.force-inline}
When you’ve done connecting Shields you can connect Smablo Development board to your computer with USB cable.
To show you how to interact with Smablo Air Quality Shield open Visual Studio Code and from your Smablo SDK example directory and open bme680_bsec like it was shown at the video below:
If you will scroll down to the bottom of the bsec_manager_main_demo.c
file you will see main configuration function called bsec_manager_demo_main
.
To compile and run the example press F5 button and then press run button on the top screen menu. The example will measure IAQ, humidity, pressure and temperature and print it on screen with use of RTT Viewer.
Minimal example code will show you how to program with Smablo Shields an app_bsec_manager.h
driver.
//1
#include <stdio.h>
#include "app_bsec_manager.h"
#include "sm_timestamp.h"
#include "nrf_log.h"
#include "app_error.h"
//4
static void bsec_data_handler(const app_bsec_data_t* const p_bsec_data)
{
char buff[100];
snprintf(buff, sizeof(buff), "%llu:\t\tstatus: %d", p_bsec_data->timestamp/1000000000, p_bsec_data->bsec_status);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
if(p_bsec_data->temp_present)
{
snprintf(buff, sizeof(buff), "\tTemp:\t\t%.2f oC", p_bsec_data->temp);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
}
if(p_bsec_data->hum_present)
{
snprintf(buff, sizeof(buff), "\tHum:\t\t%.2f %%Rh", p_bsec_data->hum);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
}
if(p_bsec_data->press_present)
{
snprintf(buff, sizeof(buff), "\tPress:\t%.0f Pa", p_bsec_data->press);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
}
if(p_bsec_data->iaq_present)
{
snprintf(buff, sizeof(buff), "\tIAQ:\t\t%.3f\tacc:%u", p_bsec_data->iaq, p_bsec_data->iaq_accuracy);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
}
if(p_bsec_data->iaq_runin_present)
{
snprintf(buff, sizeof(buff), "\tIAQ runin:\t%.0f", p_bsec_data->iaq_runin);
NRF_LOG_RAW_DEBUG("%s\r\n", nrf_log_push(buff));
}
}
void bsec_manager_demo_main(void)
{
//2
//initialize app_bsec
bsec_library_return_t ret=app_bsec_init(APP_BSEC_SAMPLE_RATE_LP, bsec_data_handler, NULL);
//3 if(ret!=BSEC_OK)
{
NRF_LOG_ERROR("app_bsec_manager failed to initialize\r\n");
APP_ERROR_CHECK(NRF_ERROR_INTERNAL);
}
}
Minimal code example show how to use Air Quality Shield. Example is measuring temperature, humidity, pressure and IAQ (indoor air quality) and print them on screen.
In point 1 we need to include libraries and driver we will use in project.
#include "app_bsec_manager.h"
#include "sm_timestamp.h"
#include "nrf_log.h"
#include "app_error.h"
app_bsec_manager.h
is a driver that we wil use to interact with Air Quality Shield sm_timestamp.h
is a library that will let us to measure timestampsnrf_log.h
is library that we will use to print log on screen log marcosapp_error.h
is libary that will help us to check for errorsIn point 2 we are initializing the Smablo Air Quality Shield with app_bsec_init
function. Function is type bsec_library_return_t
/*!
* @brief Enumeration for function return codes
*/
typedef enum
{
BSEC_OK = 0, /*!< Function execution successful */
BSEC_E_DOSTEPS_INVALIDINPUT = -1, /*!< Input (physical) sensor id passed to bsec_do_steps() is not in the valid range or not valid for requested virtual sensor */
BSEC_E_DOSTEPS_VALUELIMITS = -2, /*!< Value of input (physical) sensor signal passed to bsec_do_steps() is not in the valid range */
BSEC_E_DOSTEPS_DUPLICATEINPUT = -6, /*!< Duplicate input (physical) sensor ids passed as input to bsec_do_steps() */
BSEC_I_DOSTEPS_NOOUTPUTSRETURNABLE = 2, /*!< No memory allocated to hold return values from bsec_do_steps(), i.e., n_outputs == 0 */
BSEC_W_DOSTEPS_EXCESSOUTPUTS = 3, /*!< Not enough memory allocated to hold return values from bsec_do_steps(), i.e., n_outputs < maximum number of requested output (virtual) sensors */
BSEC_W_DOSTEPS_TSINTRADIFFOUTOFRANGE = 4, /*!< Duplicate timestamps passed to bsec_do_steps() */
BSEC_E_SU_WRONGDATARATE = -10, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() is zero */
BSEC_E_SU_SAMPLERATELIMITS = -12, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() does not match with the sampling rate allowed for that sensor */
BSEC_E_SU_DUPLICATEGATE = -13, /*!< Duplicate output (virtual) sensor ids requested through bsec_update_subscription() */
BSEC_E_SU_INVALIDSAMPLERATE = -14, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() does not fall within the global minimum and maximum sampling rates */
BSEC_E_SU_GATECOUNTEXCEEDSARRAY = -15, /*!< Not enough memory allocated to hold returned input (physical) sensor data from bsec_update_subscription(), i.e., n_required_sensor_settings < #BSEC_MAX_PHYSICAL_SENSOR */
BSEC_E_SU_SAMPLINTVLINTEGERMULT = -16, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() is not correct */
BSEC_E_SU_MULTGASSAMPLINTVL = -17, /*!< The sample_rate of the requested output (virtual), which requires the gas sensor, is not equal to the sample_rate that the gas sensor is being operated */
BSEC_E_SU_HIGHHEATERONDURATION = -18, /*!< The duration of one measurement is longer than the requested sampling interval */
BSEC_W_SU_UNKNOWNOUTPUTGATE = 10, /*!< Output (virtual) sensor id passed to bsec_update_subscription() is not in the valid range; e.g., n_requested_virtual_sensors > actual number of output (virtual) sensors requested */
BSEC_I_SU_SUBSCRIBEDOUTPUTGATES = 12, /*!< No output (virtual) sensor data were requested via bsec_update_subscription() */
BSEC_E_PARSE_SECTIONEXCEEDSWORKBUFFER = -32, /*!< n_work_buffer_size passed to bsec_set_[configuration/state]() not sufficient */
BSEC_E_CONFIG_FAIL = -33, /*!< Configuration failed */
BSEC_E_CONFIG_VERSIONMISMATCH = -34, /*!< Version encoded in serialized_[settings/state] passed to bsec_set_[configuration/state]() does not match with current version */
BSEC_E_CONFIG_FEATUREMISMATCH = -35, /*!< Enabled features encoded in serialized_[settings/state] passed to bsec_set_[configuration/state]() does not match with current library implementation */
BSEC_E_CONFIG_CRCMISMATCH = -36, /*!< serialized_[settings/state] passed to bsec_set_[configuration/state]() is corrupted */
BSEC_E_CONFIG_EMPTY = -37, /*!< n_serialized_[settings/state] passed to bsec_set_[configuration/state]() is to short to be valid */
BSEC_E_CONFIG_INSUFFICIENTWORKBUFFER = -38, /*!< Provided work_buffer is not large enough to hold the desired string */
BSEC_E_CONFIG_INVALIDSTRINGSIZE = -40, /*!< String size encoded in configuration/state strings passed to bsec_set_[configuration/state]() does not match with the actual string size n_serialized_[settings/state] passed to these functions */
BSEC_E_CONFIG_INSUFFICIENTBUFFER = -41, /*!< String buffer nsufficient to hold serialized data from BSEC library */
BSEC_E_SET_INVALIDCHANNELIDENTIFIER = -100, /*!< Internal error code */
BSEC_E_SET_INVALIDLENGTH = -104, /*!< Internal error code */
BSEC_W_SC_CALL_TIMING_VIOLATION = 100, /*!< Difference between actual and defined sampling intervals of bsec_sensor_control() greater than allowed */
} bsec_library_return_t;
Which holds possible states of the shield. app_bsec_init
function takes 3 parameters.
sample_rate
type app_bsec_sample_rate_t
///Sample rate setting enum
typedef enum
{
APP_BSEC_SAMPLE_RATE_LP=0, ///< 'Low power mode' - 1 sample every 3 seconds, high current usage, recommended only for development
APP_BSEC_SAMPLE_RATE_ULP ///< 'Ultra low power mode' - 1 sample every 300 seconds, low current usage, recommended mode
} app_bsec_sample_rate_t;
parameter which determnes the sample rate of measurements. W can choose between APP_BSEC_SAMPLE_RATE_LP
which will return measurements every 3 second and is desined for development debug and testing and APP_BSEC_SAMPLE_RATE_ULP
which is ultra low power mode designed for end usage, this mode will sample measurment every 300 seconds.
drdy_handler
type app_bsec_drdy_handler_t
which is pointer to user defined handler which will execute with rate confugured in sample_rate
parameter. The hanler will also give you access to app_bsec_data_t
structure which will hold the most recent measurements. The app_bsec_data_t
holds following components :
///Data container returned by BSEC to data ready handler
typedef struct
{
int64_t timestamp; ///< Measurement timestamp in nanoseconds
bsec_library_return_t bsec_status; ///< BSEC status, non zero indicates error
float iaq; ///< Indoor Air Quality index value
uint8_t iaq_accuracy; ///< iaq measurement accuracy:
///< 0 - The sensor is not yet stablized or in a run-in status
///< 1 - Calibration required but not enough data to perform it at this time
///< 2 - Calibration on-going
///< 3 - Calibration is done, now IAQ estimate achieves best perfomance
bool iaq_present; ///< if true iaq measurement is present in this structure
float iaq_runin; ///< iaq sensor run-in status 1= run in complete
bool iaq_runin_present; ///< if true run in signal is present
float temp; ///< temperature in Centigrade
bool temp_present; ///< if true temperature signal is present
float hum; ///< relative humidity in % Rh
bool hum_present; ///< if true humidity signal is present
float press; ///< pressure in Pa
bool press_present; ///< if true pressure signal is present
} app_bsec_data_t;
timestamp
type int64_t
is a measurement timestamp of the measurementbsec_status
type bsec_library_return_t
/*!
* @brief Enumeration for function return codes
*/
typedef enum
{
BSEC_OK = 0, /*!< Function execution successful */
BSEC_E_DOSTEPS_INVALIDINPUT = -1, /*!< Input (physical) sensor id passed to bsec_do_steps() is not in the valid range or not valid for requested virtual sensor */
BSEC_E_DOSTEPS_VALUELIMITS = -2, /*!< Value of input (physical) sensor signal passed to bsec_do_steps() is not in the valid range */
BSEC_E_DOSTEPS_DUPLICATEINPUT = -6, /*!< Duplicate input (physical) sensor ids passed as input to bsec_do_steps() */
BSEC_I_DOSTEPS_NOOUTPUTSRETURNABLE = 2, /*!< No memory allocated to hold return values from bsec_do_steps(), i.e., n_outputs == 0 */
BSEC_W_DOSTEPS_EXCESSOUTPUTS = 3, /*!< Not enough memory allocated to hold return values from bsec_do_steps(), i.e., n_outputs < maximum number of requested output (virtual) sensors */
BSEC_W_DOSTEPS_TSINTRADIFFOUTOFRANGE = 4, /*!< Duplicate timestamps passed to bsec_do_steps() */
BSEC_E_SU_WRONGDATARATE = -10, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() is zero */
BSEC_E_SU_SAMPLERATELIMITS = -12, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() does not match with the sampling rate allowed for that sensor */
BSEC_E_SU_DUPLICATEGATE = -13, /*!< Duplicate output (virtual) sensor ids requested through bsec_update_subscription() */
BSEC_E_SU_INVALIDSAMPLERATE = -14, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() does not fall within the global minimum and maximum sampling rates */
BSEC_E_SU_GATECOUNTEXCEEDSARRAY = -15, /*!< Not enough memory allocated to hold returned input (physical) sensor data from bsec_update_subscription(), i.e., n_required_sensor_settings < #BSEC_MAX_PHYSICAL_SENSOR */
BSEC_E_SU_SAMPLINTVLINTEGERMULT = -16, /*!< The sample_rate of the requested output (virtual) sensor passed to bsec_update_subscription() is not correct */
BSEC_E_SU_MULTGASSAMPLINTVL = -17, /*!< The sample_rate of the requested output (virtual), which requires the gas sensor, is not equal to the sample_rate that the gas sensor is being operated */
BSEC_E_SU_HIGHHEATERONDURATION = -18, /*!< The duration of one measurement is longer than the requested sampling interval */
BSEC_W_SU_UNKNOWNOUTPUTGATE = 10, /*!< Output (virtual) sensor id passed to bsec_update_subscription() is not in the valid range; e.g., n_requested_virtual_sensors > actual number of output (virtual) sensors requested */
BSEC_I_SU_SUBSCRIBEDOUTPUTGATES = 12, /*!< No output (virtual) sensor data were requested via bsec_update_subscription() */
BSEC_E_PARSE_SECTIONEXCEEDSWORKBUFFER = -32, /*!< n_work_buffer_size passed to bsec_set_[configuration/state]() not sufficient */
BSEC_E_CONFIG_FAIL = -33, /*!< Configuration failed */
BSEC_E_CONFIG_VERSIONMISMATCH = -34, /*!< Version encoded in serialized_[settings/state] passed to bsec_set_[configuration/state]() does not match with current version */
BSEC_E_CONFIG_FEATUREMISMATCH = -35, /*!< Enabled features encoded in serialized_[settings/state] passed to bsec_set_[configuration/state]() does not match with current library implementation */
BSEC_E_CONFIG_CRCMISMATCH = -36, /*!< serialized_[settings/state] passed to bsec_set_[configuration/state]() is corrupted */
BSEC_E_CONFIG_EMPTY = -37, /*!< n_serialized_[settings/state] passed to bsec_set_[configuration/state]() is to short to be valid */
BSEC_E_CONFIG_INSUFFICIENTWORKBUFFER = -38, /*!< Provided work_buffer is not large enough to hold the desired string */
BSEC_E_CONFIG_INVALIDSTRINGSIZE = -40, /*!< String size encoded in configuration/state strings passed to bsec_set_[configuration/state]() does not match with the actual string size n_serialized_[settings/state] passed to these functions */
BSEC_E_CONFIG_INSUFFICIENTBUFFER = -41, /*!< String buffer nsufficient to hold serialized data from BSEC library */
BSEC_E_SET_INVALIDCHANNELIDENTIFIER = -100, /*!< Internal error code */
BSEC_E_SET_INVALIDLENGTH = -104, /*!< Internal error code */
BSEC_W_SC_CALL_TIMING_VIOLATION = 100, /*!< Difference between actual and defined sampling intervals of bsec_sensor_control() greater than allowed */
} bsec_library_return_t;
Which are are function error codes that descibe the state of the shield.
iaq
type float
which is Indoor Air Quality index value. This index can have values from 0 to 500 with resolution of 1 to indicate or quantify the quality of the surrinding air.iaq_accuracy
type uint8_t
is an IAQ measurement accuracy:
iaq_present
type bool
when value of parameter is True IAQ new measurement is present in this structureiaq_runin
type float
iaq sensor run-in status 1 = run in complete. Indicates when sensor oos ready after switch-oniaq_runin_present
type bool
if true run in signal is presenttemp
type float
temperature value in Centigrade ( -40…85°C) with ±1.0°C accuracytemp_present
type bool
when value of parameter is True new temperature measurement is present in this structurehum
type float
relative humidity in % Rh (0…100%) with ±3% accuracyhum_present
type bool
when value of parameter is True new humidity measurement is present in this structurepress
type float
pressure in Pa (300...1100 hPa) with ±1 hPa absolute accuracypress_present
type bool
when value of parameter is True new pressure measurement is present in this structureerror_handler
type app_bsec_error_handler_t
which is pointer to user defined error handler function that will execute when error occurs In point 3 we check if initialization went ok if not the error code is printed on screen.
In point 4 bsec_data_handler
handler taht will be called every 3 seconds in this example will print all measurement on screen with use of log marcos.
app_bsec_manager
library referenceapp_bsec_init
Prototype:
bsec_library_return_t app_bsec_init(app_bsec_sample_rate_t sample_rate, app_bsec_drdy_handler_t drdy_handler, app_bsec_error_handler_t error_handler);
Function is used to initialize the Air Quality Shield configure sampling data rate configure user defined handler and user defined error handler. This is the only function in app_bsec_manager
driver and its usage was described in Minimal code chapter