Combined Features

This section introduces special features of the combined accelerometer and gyroscope BMI160, the magnetometer BMM150 and the environmental sensor BME280, which are available within the Sensor Toolbox of the XDK.

  1. Calibrated Sensors
  2. API Overview 1
  3. Initializing a calibrated sensor
  4. Reading calibration state
  5. Reading calibrated sensor data
  6. Full Code Example 1
  7. Appendix 1
    1. XDK Console Output example 1
  8. Orientation Sensor
  9. API Overview 2
  10. Initializing the orientation sensor
  11. Reading orientation data
  12. Full Code Example 2
  13. Appendix 2 1. XDK Console Output example 2
  14. Absolute humidity sensor
  15. API Overview 3
  16. Initializing the absolute humidity sensor
  17. Reading absolute humidity data
  18. Full Code Example 3
  19. Appendix 3 1. XDK Console Output example 3

Calibrated Sensors

The calibrated sensors include the calibrated accelerometer, gyroscope and magnetometer. These are special features of the BMI160 and the BMM150. The calibrated sensors implement the same functionality as the uncalibrated sensors. but allow an automatic calibration of their measurements. This means, that constant offsets as the earth acceleration, for example, are omitted during the measurements

For more information about the calibrated sensor feature please refer to the datasheets of the BMI160 and BMM150.

The following code examples will only cover the complete implementation of the calibrated accelerometer. The calibrated gyroscope and magnetometer can implemented in the same manor as the calibrated accelerometer.

API Overview 1

Initializing a calibrated sensor

Before we start with the implementation of the calibrated accelerometer, 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_CalibratedAccel.h. Afterwards the function CalibratedAccel_init() is used to initialize the sensor with the correct sensor specific handler.

/* Interface for all  sensors on the XDK */

#include "XdkSensorHandle.h"

CalibratedAccel_init(xdkCalibratedAccelerometer_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 Calibrated accelerometer */
extern CalibratedAccel_HandlePtr_T xdkCalibratedAccelerometer_Handle;

/* Sensor Handler for Calibrated gyroscope */
extern CalibratedGyro_HandlePtr_T xdkCalibratedGyroscope_Handle;

/* Sensor Handler for Calibrated magnetometer */
extern CalibratedMag_HandlePtr_T xdkCalibratedMagnetometer_Handle;

Reading calibration state

The calibrated sensors provide a new function called CalibratedAccel_getStatus() which returns the current calibration status. Depending on which state is set, the calibration can be low, medium or high. It is necessary for a properly working measurement to wait until the calibration state returns the configured calibration accuracy. The calibration is not done directly by initializing it and must be checked repeatedly (e.g. in a timer task or while loop) until the calibration state matches the desired behavior.

The following code snippet shows the declaration of the calibration variable calibrationStatus and the call of the function CalibratedAccel_getStatus() which stores the current calibration state in the passed reference of calibrationStatus.

CalibratedAccel_Status_T calibrationStatus = CALIBRATED_ACCEL_UNRELIABLE;

CalibratedAccel_getStatus(&calibrationStatus);

Reading calibrated sensor data

This section describes how to read data from the calibrated accelerometer after the calibration is done. To read data from the calibrated accelerometer are three functions available. First the function CalibratedAccel_readXyzMps2Value() is explained. To use the function a struct of the type CalibratedAccel_XyzMps2Data_T is declared and filled with zeros. Then the function CalibratedAccel_readXyzMps2Value() is called to store the data in a reference of the previous declared storage struct with the physical unit meters per square seconds.

/* Reading of the data of the calibrated accelerometer */

CalibratedAccel_XyzMps2Data_T getAccelMpsData = {INT32_C(0), INT32_C(0), INT32_C(0)};

CalibratedAccel_readXyzMps2Value(&getAccelMpsData);

In addition, the sensor data of the calibrated accelerometer can be received by using the function CalibratedAccel_readXyzGValue(), too. As such, this function standardizes the measured sensor values to the earth acceleration of 9.81 meters per square seconds.

CalibratedAccel_XyzGData_T getAccelGData = {INT32_C(0), INT32_C(0), INT32_C(0)};

CalibratedAccel_readXyzGValue(&getAccelGData);

The opposite to the two previous described functions is the function CalibratedAccel_readXyzLsbValue(). The function does not differ in the usage to the two other functions, but only in the unit of the stored sensor values. Here these are stored in their digital unit as bytes.

CalibratedAccel_XyzLsbData_T getAccelLsbData = {INT32_C(0), INT32_C(0), INT32_C(0)};

CalibratedAccel_readXyzGValue(&getAccelLsbData);

Full Code Example 1

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

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

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

#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  // [i] Module ID define before including Basics package
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

#include <stdio.h>
#include "BCDS_CmdProcessor.h"
#include "FreeRTOS.h"
#include "XdkSensorHandle.h"
#include "timers.h"
#include "BCDS_CalibratedAccel.h"

/* --------------------------------------------------------------------------- |
 * HANDLES ******************************************************************* |
 * -------------------------------------------------------------------------- */
static CmdProcessor_T * AppCmdProcessor;
xTimerHandle calibratedAccelerometerHandle = NULL;

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

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

    CalibratedAccel_Status_T calibrationAccuracy = CALIBRATED_ACCEL_UNRELIABLE;
    Retcode_T calibrationStatus = RETCODE_FAILURE;

    calibrationStatus = CalibratedAccel_getStatus(&calibrationAccuracy);

    if (calibrationAccuracy == CALIBRATED_ACCEL_HIGH && calibrationStatus == RETCODE_OK){
        Retcode_T returnDataValue = RETCODE_FAILURE;

        /* Reading of the data of the calibrated accelerometer */
        CalibratedAccel_XyzMps2Data_T getAccelMpsData = { INT32_C(0), INT32_C(0), INT32_C(0) };
        returnDataValue = CalibratedAccel_readXyzMps2Value(&getAccelMpsData);

        if (returnDataValue == RETCODE_OK){
            printf("Calibrated acceleration: %10f m/s2[X] %10f m/s2[Y] %10f m/s2[Z]\n\r",
                        (float) getAccelMpsData.xAxisData, (float) getAccelMpsData.yAxisData, (float) getAccelMpsData.zAxisData);
        }
    }
}

static void initCalibratedAccelerometer(void)
{
    Retcode_T calibratedAccelInitReturnValue = RETCODE_FAILURE;
    calibratedAccelInitReturnValue = CalibratedAccel_init(xdkCalibratedAccelerometer_Handle);

    if (calibratedAccelInitReturnValue != RETCODE_OK) {
        printf("Initializing Calibrated Accelerometer 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(calibratedAccelerometerHandle,timerBlockTime);
}

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

    Retcode_T retcode = RETCODE_OK;
    uint32_t timerDelay = UINT32_C(1000);
    uint32_t timerAutoReloadOn = UINT32_C(1);

    // Setup of the necessary module
    initCalibratedAccelerometer();

    // Creation and start of the timer
    calibratedAccelerometerHandle = xTimerCreate((const char *) "readCalibratedAccelerometer", timerDelay, timerAutoReloadOn, NULL, readCalibratedAccelerometer);
    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));

    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0);
    }
}

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

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

Appendix 1

XDK Console Output example 1

The following console log is an example output of the code that has been implemented in the Sensors Combined Feature Calibration Sensor example guide:

Image

Orientation Sensor

This chapter introduces another section of the combined features, namely the orientation sensor feature. This feature allows a tracking of the orientation of the XDK in the room by using the sensors of the BMI160 and the BMM150. It tracks the direct outputs of the device in two or three dimensions.

For more information about the calibrated sensor feature please refer to the datasheets of the BMI160 and BMM150.

API Overview 2

Initializing the orientation sensor

Before we start with the implementation of the orientation 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_Orientation.h. Afterwards the function Orientation_init() is used to initialize the sensor with the correct sensor specific handler.

/* Interface for the sensors on the XDK */

#include "XdkSensorHandle.h"

Orientation_init(xdkOrientationSensor_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 Orientation Sensor */
extern Orientation_HandlePtr_T xdkOrientationSensor_Handle;

Reading orientation data

This section describes how to read data from the orientation sensor. Three functions are available to read data of the orientation sensor.

In all cases a storage struct containing every axis orientation data needs to be declared. The data is then read by the Orientation_readQuaternionValue() function and stored in a passed reference of the declared storage struct. As such, the function Orientation_readQuaternionValue() stores the measured sensor values as quaternion values.

/* Reading of the data of the orientation sensor */

Orientation_QuaternionData_T getOrientationQuaternionData = { INT32_C(0), INT32_C(0),INT32_C(0), INT32_C(0) };

Orientation_readQuaternionValue(&getOrientationQuaternionData);

The opposite to the sensor data storage in quaternion values is the Euler representation. As such, the orientation sensor provides two additional functions Orientation_readEulerRadianVal() and Orientation_readEulerDegreeVal() to use the Euler representation. Orientation_readEulerRadianVal() stores the Euler represented values calculated in radian. Otherwise the Euler represented values can be also stored calculated in degrees by using the function Orientation_readEulerDegreeVal().

Orientation_QuaternionData_T getOrientationEulerData = { INT32_C(0), INT32_C(0),INT32_C(0) };

Orientation_readEulerRadianVal(&getOrientationEulerData);

Orientation_readEulerDegreeVal(&getOrientationEulerData);

Full Code Example 2

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

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

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

#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  // [i] Module ID define before including Basics package
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER
#include <stdio.h>
#include "BCDS_CmdProcessor.h"
#include "FreeRTOS.h"
#include "XdkSensorHandle.h"
#include "timers.h"
#include "BCDS_Orientation.h"

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

static CmdProcessor_T * AppCmdProcessor;
xTimerHandle orientationSensorHandle  = NULL;

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

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

    Retcode_T returnQuatValue = RETCODE_FAILURE;

    /* Reading of the data of the calibrated accelerometer */
    Orientation_QuaternionData_T QuaternionValues = { INT32_C(0), INT32_C(0), INT32_C(0), INT32_C(0) };
    returnQuatValue = Orientation_readQuaternionValue(&QuaternionValues);

    if (returnQuatValue == RETCODE_OK) {
            printf("Quaternions : %10f[X] %10f[Y] %10f[Z] %10f[W] \n\r",
                    QuaternionValues.x, QuaternionValues.y, QuaternionValues.z, QuaternionValues.w);
    }
}

static void initOrientationSensor(void)
{
    Retcode_T returnValue = RETCODE_FAILURE;

    returnValue = Orientation_init(xdkOrientationSensor_Handle);

    if (returnValue != RETCODE_OK) {
        printf("Initializing Orientation Sensor 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(orientationSensorHandle ,timerBlockTime);
}

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

    Retcode_T retcode = RETCODE_OK;
    uint32_t timerDelay = UINT32_C(1000);
    uint32_t timerAutoReloadOn = UINT32_C(1);

    // Setup of the necessary module
    initOrientationSensor();

    // Creation and start of the timer
    orientationSensorHandle = xTimerCreate((const char *) "readOrientationSensor", timerDelay, timerAutoReloadOn, NULL, readOrientationSensor);
    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));

    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0);
    }
}

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

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

Appendix 2

XDK Console Output example 2

The following console log is an example output of the code that has been implemented in the Sensors Combined Features Orientation Sensor example guide:

Image

Absolute humidity sensor

This section describes the absolute humidity feature of the environmental sensor BME280, that is included in the Sensor Toolbox of the XDK. The absolute humidity is calculated by measuring the humidity of two points. Therefore the XDK has to be moved to receive the required measurements and then a calculation can be done.

For more information about the absolute humidity feature please refer to the datasheet of the BME280.

API Overview 3

Initializing the absolute humidity sensor

Before we start with the implementation of the absolute humidity 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_AbsoluteHumidity.h. Afterwards the function AbsoluteHumidity_init() is used to initialize the sensor with the correct sensor specific handler.

/* Interface for the sensors on the XDK */

#include "XdkSensorHandle.h"

AbsoluteHumidity_init(xdkHumiditySensor_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 humidity Sensor */

extern AbsoluteHumidity_HandlePtr_T xdkHumiditySensor_Handle;

Reading absolute humidity data

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

First a storage variable for the absolute humidity data is declared. The data is then read by the AbsoluteHumidity_readValue() function and stored in a passed reference of the storage variable.

float getHumidityData = INT32_C(0);

AbsoluteHumidity_readValue(xdkHumiditySensor_Handle, &getHumidityData);

Full Code Example 3

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

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

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

#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  // [i] Module ID define before including Basics package
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

#include <stdio.h>
#include "BCDS_CmdProcessor.h"
#include "FreeRTOS.h"
#include "XdkSensorHandle.h"
#include "timers.h"
#include "BCDS_AbsoluteHumidity.h"

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

static CmdProcessor_T * AppCmdProcessor;
xTimerHandle absoluteHumidityHandle = NULL;

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

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

    Retcode_T returnDataValue = RETCODE_FAILURE;

    /* Reading of the data */
    float getHumidityData = INT32_C(0);

    returnDataValue = AbsoluteHumidity_readValue(xdkHumiditySensor_Handle, &getHumidityData);

    if (returnDataValue == RETCODE_OK) {
        printf("Absolute humidity: %f g/m3 \n\r", getHumidityData);
    }
    else
    {
        printf("Reading of the absolute humidity data failed! \n\r");
    }
}

static void initAbsoluteHumiditySensor(void)
{
    Retcode_T absoluteHumidityInitReturnValue = RETCODE_FAILURE;

    absoluteHumidityInitReturnValue = AbsoluteHumidity_init(xdkHumiditySensor_Handle);

    if (absoluteHumidityInitReturnValue != RETCODE_OK) {
        printf("Initializing Absolute Humidity Sensor 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(absoluteHumidityHandle ,timerBlockTime);
}

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

    Retcode_T retcode = RETCODE_OK;
    uint32_t timerDelay = UINT32_C(1000);
    uint32_t timerAutoReloadOn = UINT32_C(1);

    // Setup of the necessary module
    initAbsoluteHumiditySensor();

    // Creation and start of the timer
    absoluteHumidityHandle = xTimerCreate((const char *) "readAbsoluteHumiditySensor", timerDelay, timerAutoReloadOn, NULL, readAbsoluteHumiditySensor);
    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));

    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0);
    }
}

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);
    }
}
/*----------------------------------------------------------------------------*/

Appendix 3

XDK Console Output example 3

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

Image