Environmental

This chapter introduces how to configure and use the environmental sensor BME280 on the XDK via the environmental interface. It provides not only an example on how to initialize and read the sensor data, but also an explanation of some specific presettings.

For more specific information about the BME280, please take a look at the corresponding datasheet.

  1. Environmental API Overview
  2. Initializing the Environmental Sensor
  3. Configuring the Presettings
  4. Reading Sensor Data
    1. Temperature Reading
    2. Pressure Reading
    3. Humidity Reading
    4. Full Data Reading
    5. Compensating Temperature Data
  5. Full Code Example
  6. Appendix
    1. XDK Console Output example

Environmental API Overview

It is generally recommended to develop an application based on the highest API level the XDK framework supports, although it is possible to access deeper API levels if this isn’t enough for the distinct purpose.

fig1

Initializing the Environmental Sensor

Before we start with the implementation of the environmental sensor, the sensor handling header file has to be included, which is XdkSensorHandle.h. This header file provides the interfaces for every sensor type, in this case, BCDS_Environmental.h. Afterwards the function Environmental_init() is used to initialize the sensor with the correct sensor specific handler.

/* Interface for the sensors on the XDK */

#include "XdkSensorHandle.h"

Environmental_init(xdkEnvironmental_BME280_Handle);

The particular sensor specific handler can be found within XdkSensorHandle.h. It contains the sensor specific handler for every sensor type on the XDK.

/************************************************************
*   XdkSensorHandle.h
************************************************************/

/* Sensor Handler for the BME280 Sensor */
extern Environmental_HandlePtr_T xdkEnvironmental_BME280_Handle;

Configuring the Presettings

This short overview gives an example about how to configure the environmental sensor with presettings. It is of course possible to use the environmental sensor without modifying the settings, too.

The functions Environmental_setOverSamplingPressure() and Environmental_setFilterCoefficient() set a specific oversampling rate and filter coefficient for the pressure measurements of the environmental sensor. Please keep in mind that before any presettings can be configured, the light sensor needs to be initialized first.

Environmental_setOverSamplingPressure(xdkEnvironmental_BME280_Handle,ENVIRONMENTAL_BME280_OVERSAMP_2X);

Environmental_setFilterCoefficient(xdkEnvironmental_BME280_Handle,ENVIRONMENTAL_BME280_FILTER_COEFF_2);

The table below contains some of the configuration functions which are available in the interface BCDS_Environmental.h.

FunctionEffect
`Environmental_setOverSamplingTemperature()`Configures the temperature oversampling rate with the given oversampling enumeration.
`Environmental_setOverSamplingPressure()`Configures the pressure oversampling rate with the given oversampling enumeration.
`Environmental_setOverSamplingHumidity()`Configures the humidity oversampling rate with the given oversampling enumeration.
`Environmental_setFilterCoefficient()`Configures the temperature and pressure filtering of the environmental sensor with a given filter coefficient enumeration.
`Environmental_setStandbyDuration()`Configures the environmental sensor with the given sleep duration enumeration.
`Environmental_getStandbyDuration()`Returns the configured sleep duration of the environmental sensor in a passed reference variable.
`Environmental_setPowerMode()`Configures the environmental sensor with the given power mode enumeration.
`Environmental_getPowerMode()`Returns the configured power mode of the enviromental sensor in a passed reference variable.

A more detailed explanation can be found in the mentioned interface BCDS_Environmental.h.

Reading Sensor Data

This section describes how to read measured data from the environmental sensor.

First a storage struct for the environmental data is declared. The data is then read by the Environmental_readData() function and then stored in a passed reference of the storage struct.

Environmental_Data_T bme280 = { INT32_C(0), INT32_C(0), INT32_C(0) };

Environmental_readData(xdkEnvironmental_BME280_Handle,&bme280);

The temperature, humidity and pressure measurements can also be read from the environmental sensor separately, if the only one or two of them are needed. The following code snippets will show how to read all of them separately. In addition, the code snippets will show how to receive the measurements in their physical values as well as in bytes.

Temperature Reading

First the single reading for the temperature is shown. For this, only a storage variable has to be declared. Afterwards the function Environmental_readTemperature() is called, which stores the measured temperature in the storage variable.

As such, the temperature can be received as mentioned in analog values or as raw digital values. Analog values would be calculated from the digital measurements back into the correct physical values and therefore the function Environmental_readTemperature() is used. On the other hand, the digital values can be received by using the function Environmental_readTemperatureLSB() and are represented in bytes.

int32_t getTemperature = INT32_C(0);

Environmental_readTemperature(xdkEnvironmental_BME280_Handle,&getTemperature);

Environmental_readTemperatureLSB(xdkEnvironmental_BME280_Handle,&getTemperature);

Pressure Reading

The pressure data can be read from the environmental sensor in a similar approach as the temperature data. First a storage variable is declared to hold the read pressure data from the environmental data. Following the data from the environmental sensor is passed in the declared storage variable similar to the temperature reading with Environmental_readPressure().

As such, the pressure measurements can be represented in either in physical values by using the function via Environmental_readPressure() to receive the pressure measurements or in bytes by using the function Environmental_readPressureLSB().

uint32_t getPressure = INT32_C(0);

Environmental_readPressure(xdkEnvironmental_BME280_Handle,&getPressure);

Environmental_readPressureLSB(xdkEnvironmental_BME280_Handle,&getPressure);

Humidity Reading

The humidity data can be received similar to the pressure and temperature measurements. As before, a storage variable needs to be declared which will hold the measured humidity data. Afterwards the function Environmental_readHumidity() takes a reference to the storage variable and stores the measured humidity data into it.

The humidity data can be represented similar to temperature and pressure by its physical value or as byte. If the function Environmental_readHumidity() is used to store the data, it will be its physical value. With the function Environmental_readHumidity() it will store the digital representation in bytes.

uint32_t getHumidity = INT32_C(0);

Environmental_readHumidity(xdkEnvironmental_BME280_Handle,&getHumidity);

Environmental_readHumidityLSB(xdkEnvironmental_BME280_Handle,&getHumidity);

Full Data Reading

Alternative to the previously explained representation of the single environmental measurements of the environmental sensor, the entire data set (temperature, pressure and humidity) can be read at once. For this, Environmental_Data_T is used as the storage struct. If Environmental_readData() is used to read the data, then the measured environmental data is represented in their physical values. Otherwise if Environmental_readDataLSB() is used then the measured data is represented as bytes.

Environmental_readData(xdkEnvironmental_BME280_Handle,&bme280);

Environmental_readDataLSB(xdkEnvironmental_BME280_Handle, &bme280);

Compensating Temperature Data

Due to the fact that the environment sensor is attached to the board inside the XDK housing, it measures the temperature inside the housing. This leads to temperatures that deviate from the actual environment temperature, because the XDK’s housing temperature increased on runtime. This also affects the relative humidity, since it depends on the output of the environment sensor’s temperature sensor.

To get more usable temperature values, it is recommended to configure an offset that is applied to the temperature after reading. The following code snippet configures an offset of -5000 to compensate the temperature data by reducing it statically by 5 Kelvin.

int32_t offset = -5000; // -5000 milliKelvin / -5 Kelvin / -5 Degree Celsius
Environmental_setTemperatureOffset(xdkEnvironmental_BME280_Handle, offset);

If temperature has to be added instead, then the offset has to be configured as a positive integer.

Now that the offset is configured, data can be compensated as follows:

Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

Environmental_compensateData(xdkEnvironmental_BME280_Handle, &bme280);

This way, the original data can be stored in another variable if necessary, before it is compensated. Note that the function for compensation requires the entire BME Data struct, as the relative humidity will be adjusted as well.

The following code will immediately return the compensated data:

Environmental_readCompensatedData(xdkEnvironmental_BME280_Handle, &bme280)

Full Code Example

Note: The full code example is intended for XDK-Workbench versions 3.4.0 and higher.

/*----------------------------------------------------------------------------*/

/* --------------------------------------------------------------------------- |
 * INCLUDES & DEFINES ******************************************************** |
 * -------------------------------------------------------------------------- */

/* own header files */
#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  /* Module ID define before including Basics package*/
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

/* system header files */
#include <stdio.h>

/* additional interface header files */
#include "FreeRTOS.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"

#include "XdkSensorHandle.h"

#include "task.h"
#include "timers.h"

/* --------------------------------------------------------------------------- |
 * HANDLES ******************************************************************* |
 * -------------------------------------------------------------------------- */

static CmdProcessor_T * AppCmdProcessor;
xTimerHandle environmentalHandle = NULL;

/* --------------------------------------------------------------------------- |
 * EXECUTING FUNCTIONS ******************************************************* |
 * -------------------------------------------------------------------------- */

static void readEnvironmental(xTimerHandle xTimer)
{
    (void) xTimer;

    Retcode_T returnValue = RETCODE_FAILURE;

    /* read and print BME280 environmental sensor data */

    Environmental_Data_T bme280 = { INT32_C(0), UINT32_C(0), UINT32_C(0) };

    returnValue = Environmental_readData(xdkEnvironmental_BME280_Handle, &bme280);

    if ( RETCODE_OK == returnValue) {
        printf("BME280 Environmental Data : p =%ld Pa T =%ld mDeg h =%ld %%rh\n\r",
        (long int) bme280.pressure, (long int) bme280.temperature, (long int) bme280.humidity);
    }
}

// Function that initializes the Environmental sensor with the BME280 handler and with additional presettings
static void initEnvironmental(void)
{
    Retcode_T returnValue = RETCODE_FAILURE;
    Retcode_T returnOverSamplingValue = RETCODE_FAILURE;
    Retcode_T returnFilterValue = RETCODE_FAILURE;

    /* initialize environmental sensor */

    returnValue = Environmental_init(xdkEnvironmental_BME280_Handle);
    if ( RETCODE_OK != returnValue) {
        printf("BME280 Environmental Sensor initialization failed\n\r");
    }

    returnOverSamplingValue = Environmental_setOverSamplingPressure(xdkEnvironmental_BME280_Handle,ENVIRONMENTAL_BME280_OVERSAMP_2X);
    if (RETCODE_OK != returnOverSamplingValue) {
        printf("Configuring pressure oversampling failed \n\r");
    }

    returnFilterValue = Environmental_setFilterCoefficient(xdkEnvironmental_BME280_Handle,ENVIRONMENTAL_BME280_FILTER_COEFF_2);
    if (RETCODE_OK != returnFilterValue) {
        printf("Configuring pressure filter coefficient failed \n\r");
    }
}

/* --------------------------------------------------------------------------- |
 * BOOTING- AND SETUP FUNCTIONS ********************************************** |
 * -------------------------------------------------------------------------- */

static void AppControllerEnable(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    uint32_t timerBlockTime = UINT32_MAX;

    xTimerStart(environmentalHandle,timerBlockTime);
}

static void AppControllerSetup(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);
    Retcode_T retcode = RETCODE_OK;

    uint32_t oneSecondDelay = UINT32_C(1000);
    uint32_t timerAutoReloadOn = UINT32_C(1);

    initEnvironmental();

    environmentalHandle = xTimerCreate((const char *) "readEnvironmental", oneSecondDelay,timerAutoReloadOn, NULL, readEnvironmental);

    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));
    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

void AppController_Init(void * cmdProcessorHandle, uint32_t param2)
{
    BCDS_UNUSED(param2);

    Retcode_T retcode = RETCODE_OK;

    if (cmdProcessorHandle == NULL)
    {
        printf("AppController_Init : Command processor handle is NULL \r\n");
        retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_NULL_POINTER);
    }
    else
    {
        AppCmdProcessor = (CmdProcessor_T *) cmdProcessorHandle;
        retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerSetup, NULL, UINT32_C(0));
    }

    if (RETCODE_OK != retcode)
    {
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

/** ************************************************************************* */

Appendix

XDK Console Output example

The following console log is an example output of the code that has been implemented in the Sensors Environmental example guide:

fig2