This post is to explain my understanding on the Contiki demo code for the SensorTag CC2650 platform.

Contiki 3.0, commit 9f383ba

SensorTag CC2650 includes Bosch BMP280 (temperature, barometric pressure sensor), TI TMP007 (Infrared Thermopile Contactless Temperature Sensor), TI OPT3001 (Digital ambient light sensor), InvenSense MPU-9250 (Gyro, Accelerometer, Compass), TI HDC1000 (Humidity, temperature). The demo code also supports reading voltage and temperature from the on-chip battery monitor.

Sensors usage

Firstly, activate measurement by calling SENSORS_ACTIVATE

static void init_sensor_readings(void)


in which hdc_1000_sensor, tmp_007_sensor, opt_3001_sensor and bmp_280_sensor are SENSORS_SENSOR structure variables defined in the corresponding drivers, .c files, in contiki/platform/srf006-cc26xx/sensortag, for example, in bmp-280-sensor.c

SENSORS_SENSOR(bmp_280_sensor, "BMP280", value, configure, status);

Details of the SENSORS_SENSOR structure and SENSORS_ACTIVATE can be found in contiki/core/lib/sensors.h. In fact, SENSORS_ACTIVATE is the configure function in the driver of the sensor with the ACTIVE parameter set to 1.

After a successful measurement, the sensor finishes its conversion, generate a sensors_event, and the data will be put in the ev variable together with the name of the sensor in the data variable of the PROCESS_THREAD.

PROCESS_THREAD(cc26xx_demo_process, ev, data)


Use ev and data to determine the event and process it correspondingly

else if(ev == sensors_event && data == &bmp_280_sensor) {
} else if(ev == sensors_event && data == &opt_3001_sensor) {
} else if(ev == sensors_event && data == &hdc_1000_sensor) {
} else if(ev == sensors_event && data == &tmp_007_sensor) {
} else if(ev == sensors_event && data == &mpu_9250_sensor) {

Then, get_xxx_reading() deactivates the sensor and it schedules another conversion by calling SENSOR_ACTIVATE again, through init_xxx_reading(). For example, in the get_mpu_reading() function

static void get_tmp_reading()
  ... // more code here


  ctimer_set(&tmp_timer, next, init_tmp_reading, NULL);

static void init_tmp_reading(void \*not_used)

In the ctimer_set() function, next is a time period to execute the callback function init_tmp_reading. In the demo, next is around 20 seconds

clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM);

Integrated battery monitor

Additionally, CC26xx includes a battery monitor, which is accessible by functions in bat-mon.h and bat-mon.c in contiki/cpu/cc26xx-cc13xx/dev.

static void get_sync_sensor_readings(void)
  int value;


  value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
  printf("Bat: Temp=%d C\n", value);

  value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
  printf("Bat: Volt=%d mV\n", (value * 125) >> 5);


Here, the data can be accessed at anytime, anywhere in the process (sync?), without waiting for a conversion. Or maybe it is probably just a register reading (need to look further into the CC2650 datasheet). Therefore, no sensors_event is required, just call

PROCESS_THREAD(cc26xx_demo_process, ev, data)

  ... // more code here

  ... // more code here



BLE Beacon is not working

Description The demo supports advertising BLE beacon. However, I cannot detect the beacon using TI app.

Solution Use the default Bluetooth function in Android to search for the beacon.

Enable/disable BLE beacon function by


The reason for this is the rf_ble_beacond_config() function in contiki/cpu/cc26xx-cc13xx/rf-core/rf-ble.c requires RF_BLE_ENABLED defined, see here. In fact, RF_BLE_ENABLED will be RF_BLE_CONF_ENABLED or 1 if RF_BLE_CONF_ENABLED, see contiki/cpu/cc26xx-cc13xx/rf-core/rf-ble.h.


  1. Contiki demo