Zephyr RTOS support

Last updated on: December 31, 2022

The Zephyr RTOS provides support for the sensors and SD-card through a set of drivers. This enables the use of the environmental FeatherWing with e.g. an Icarus IoT Board. Examples on enabling and using the sensors with Zephyr is shown in the following sections.

Enabling the SI7060 temperature sensor

The SI7060 temperature sensor can be used with Zephyr by adding a node to the device-tree overlay of your project and enabling the driver in your configuration file. Follow these steps to enable the SI7060 on the Icarus IoT Board:

  1. Navigate to your project and create/enter the boards directory.
  2. Create a overlay file with the exact name of your board. E.g: actinius_icarus_ns.overlay.
  3. Copy and paste the following device-tree node to the overlay file (change the i2c bus according to your board):
&i2c2 {
si7060@32 {
compatible = "silabs,si7060";
reg = <0x32>;
label = "SI7060";
};
};
  1. Add the following configuration options to your prj.conf file:
CONFIG_I2C=y
CONFIG_I2C_2=y
CONFIG_SENSOR=y
CONFIG_SI7060=y

Enabling the OPT3002 ambient light sensor

The OPT3002 ambient light sensor can be used with Zephyr by adding a node to the device-tree overlay of your project and enabling the driver in your configuration file. Follow these steps to enable the OPT3002 on the Icarus IoT Board:

  1. Navigate to your project and create/enter the boards directory.
  2. Create a overlay file with the exact name of your board. E.g: actinius_icarus_ns.overlay.
  3. Copy and paste the following device-tree node to the overlay file (change the i2c bus according to your board):
&i2c2 {
opt3002@44 {
compatible = "ti,opt3001";
reg = <0x44>;
label = "OPT3002";
};
};
  1. Add the following configuration options to your prj.conf file:
CONFIG_I2C=y
CONFIG_I2C_2=y
CONFIG_SENSOR=y
CONFIG_OPT3001=y

Enabling the BME688 sensors

The BME688 gas sensors can be used with Zephyr by adding a node to the device-tree overlay of your project and enabling the driver in your configuration file. See the Zephyr sample /ncs/zephyr/samples/sensor/bme680/ or follow these steps to enable the BME688 sensors on the Icarus IoT Board:

  1. Navigate to your project and create/enter the boards directory.
  2. Create a overlay file with the exact name of your board. E.g: actinius_icarus_ns.overlay.
  3. Copy and paste the following device-tree node to the overlay file (change the i2c bus according to your board). Only add the second BME688 node if you have a environmental FeatherWing with 2 BME688 sensors:
&i2c2 {
bme688-1@76 {
compatible = "bosch,bme680";
reg = <0x76>;
label = "BME688_1";
};
bme688-2@77 {
compatible = "bosch,bme680";
reg = <0x77>;
label = "BME688_2";
};
};
  1. Add the following configuration options to your prj.conf file:
CONFIG_I2C=y
CONFIG_I2C_2=y
CONFIG_SENSOR=y
CONFIG_BME680=y

Example code for reading environmental FeatherWing sensor data

The following configuration and code shows you how to setup the Icarus IoT Board to read data from each sensor and print it to a serial monitor. You can use this example as a reference for your own project.

  1. Navigate to your project and create/enter the boards directory.
  2. Create a overlay file with the filename: actinius_icarus_ns.overlay.
  3. Copy and paste the following device-tree node to the overlay file:
&i2c2 {
/* Node definition for the main BME688 sensor */
bme688-1@76 {
compatible = "bosch,bme680";
reg = <0x76>;
label = "BME688_1";
};
/* Node definition for the second BME688 sensor (optional) */
bme688-2@77 {
compatible = "bosch,bme680";
reg = <0x77>;
label = "BME688_2";
};
/* Node definition for the OPT3002 sensor */
opt3002@44 {
compatible = "ti,opt3001";
reg = <0x44>;
label = "OPT3002";
};
/* Node definition for the SI7060 sensor */
si7060@32 {
compatible = "silabs,si7060";
reg = <0x32>;
label = "SI7060";
};
};
  1. Add the following configuration options to your prj.conf file:
CONFIG_I2C=y
CONFIG_I2C_2=y
CONFIG_SENSOR=y
CONFIG_BME680=y
CONFIG_OPT3001=y
CONFIG_SI7060=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_PRINTK=y
  1. Add the following code to your main.c file:
#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>
#include <stdio.h>
void main(void)
{
/* Create all devices and add bindings */
const struct device *bme_1 = device_get_binding("BME688_1");
const struct device *bme_2 = device_get_binding("BME688_2");
const struct device *si = device_get_binding("SI7060");
const struct device *opt = device_get_binding("OPT3002");
/* Variables for raw and float data */
struct sensor_value temp_raw, press_raw, humidity_raw, gas_res_raw, light_raw;
double temp, press, humidity, gas_res, light;
printf("Device %p name is %s\r\n", bme_1, bme_1->name);
printf("Device %p name is %s\r\n", bme_2, bme_2->name);
printf("Device %p name is %s\r\n", si, si->name);
printf("Device %p name is %s\r\n", opt, opt->name);
while (1)
{
k_sleep(K_MSEC(500));
/* BME688_1 measurement */
sensor_sample_fetch(bme_1);
sensor_channel_get(bme_1, SENSOR_CHAN_AMBIENT_TEMP, &temp_raw);
sensor_channel_get(bme_1, SENSOR_CHAN_PRESS, &press_raw);
sensor_channel_get(bme_1, SENSOR_CHAN_HUMIDITY, &humidity_raw);
sensor_channel_get(bme_1, SENSOR_CHAN_GAS_RES, &gas_res_raw);
temp = sensor_value_to_double(&temp_raw);
press = sensor_value_to_double(&press_raw);
humidity = sensor_value_to_double(&humidity_raw);
gas_res = sensor_value_to_double(&gas_res_raw);
printf("BME688_1 T: %f; P: %f; H: %f; G: %f\r\n", temp, press, humidity, gas_res);
/* -------------------------------------------------------- */
/* BME688_2 measurement */
sensor_sample_fetch(bme_2);
sensor_channel_get(bme_2, SENSOR_CHAN_AMBIENT_TEMP, &temp_raw);
sensor_channel_get(bme_2, SENSOR_CHAN_PRESS, &press_raw);
sensor_channel_get(bme_2, SENSOR_CHAN_HUMIDITY, &humidity_raw);
sensor_channel_get(bme_2, SENSOR_CHAN_GAS_RES, &gas_res_raw);
temp = sensor_value_to_double(&temp_raw);
press = sensor_value_to_double(&press_raw);
humidity = sensor_value_to_double(&humidity_raw);
gas_res = sensor_value_to_double(&gas_res_raw);
printf("BME688_2 T: %f; P: %f; H: %f; G: %f\r\n", temp, press, humidity, gas_res);
/* -------------------------------------------------------- */
/* SI7060 measurement */
sensor_sample_fetch(si);
sensor_channel_get(si, SENSOR_CHAN_AMBIENT_TEMP, &temp_raw);
temp = sensor_value_to_double(&temp_raw);
printf("SI7060 T: %f\r\n", temp);
/* -------------------------------------------------------- */
/* OPT3002 measurement */
sensor_sample_fetch(opt);
sensor_channel_get(opt, SENSOR_CHAN_LIGHT, &light_raw);
light = sensor_value_to_double(&light_raw);
printf("OPT3002 LUX: %f\r\n\r\n", light);
}
}
  1. Build the code. Either through the nRF Connect SDK extenstion for Visual Studio Code or by using West. For more information, see the Building and application page.

  2. Flash the binary to your device using the Actinius Programmer, West or MCUBoot. For more information, see the Flashing an application page.