Thursday, July 1, 2021

How to build OpenThread Sleepy MTD CoAP temperature sensor using Simplicity Studio v5 and BRD4161A

The following steps show you how to build an OpenThread Sleepy MTD CoAP temperature sensor using Simplicity Studio v5 and BRD4161A

1. Start Simplicity Studio v5 and connect EFR32MG12 BRD4161A. Form Launcher tab, select sleepy-demo-mtd (I use OpenThread SDK 1.2.0.0 when I test this) to create the project.

 


2.  We will add temperature reading (from Si7021) related codes in this step.

2.1 In Simplicity IDE tab, open sleepy-demo-mtd.slcp to make sure you enable "Relative Humidity and Temperature sensor" and set proper I2C pins.



2.2 You also need to check sl_board_control_config.h and make sure SL_BOARD_ENABLE_SENSOR_RHT is defined as "1" and SL_BOARD_ENABLE_SENSOR_RHT_PORT/SL_BOARD_ENABLE_SENSOR_RHT_PIN are defined to correct port/pin which is PB10 on BRD4161A. 

2.3 Set "sl_i2cspm_t *i2cspm_sensor = sl_i2cspm_inst0;" in sl_sensor_select.c.

2.4 Create periodic event to read temperature from humidity/temperature sensor Si7021.

2.4.1 Add the following header files for humidity/temperature reading and timer event.

#include "sl_i2cspm_instances.h"
#include "sl_si70xx.h"
#include "sl_sleeptimer.h"
#include <stdio.h>
#include <string.h>


2.4.2 Add the following lines in app_init in app.c to initialize Si7021 humidity/temperature sensor.

    otCliOutputFormat("app_init: sl_si70xx_init\r\n");
    sl_si70xx_init(sl_i2cspm_inst0, SI7021_ADDR);
 


 2.4.3 Add timer related defines/variables/callback function and add timer start in app_init in app.c.

#define MEASUREMENT_INTERVAL_MS      5000
static sl_sleeptimer_timer_handle_t measurement_timer;



static void measurement_callback(sl_sleeptimer_timer_handle_t *handle, void *data)
{
  otCliOutputFormat("measurement_callback\r\n");
  sl_si70xx_measure_rh_and_temp(sl_i2cspm_inst0, SI7021_ADDR, &rh_data, &temp_data);
  memset(str_buf,0,64);
  sprintf(str_buf,"rh=%f, temperature=%f\r\n",((float)rh_data/1000.0),((float)temp_data/1000.0));
  otCliOutputFormat(str_buf);
}



void app_init(void)
{
... 
otCliOutputFormat("app_init: Setup periodic measurement timer \r\n");
sl_sleeptimer_start_periodic_timer_ms(&measurement_timer, MEASUREMENT_INTERVAL_MS, measurement_callback, NULL, 0, 0);
...
}


3.  Change related network settings in setNetworkConfiguration function (in sleepy-mtd.c) so the device can join matched OpenThread Border Router network (refer to here to setup OpenThread Border Router).



4. Implement CoAP related codes.

4.1 Add the following header files in app.c

#include <openthread/coap.h>
#include "utils/code_utils.h"


 4.2 Add CoAP related defines and variables.

#define TEMPERATURE_STATE_URI     "temp/celcius"
otCoapResource mResource_TEMPERATURE_STATE;
const char mTEMPERATUREStateUriPath[]=TEMPERATURE_STATE_URI;

4.3 Implement CoAP processing callback

static void temperature_state_coapHandler(void *aContext, otMessage *aMessage,
                             const otMessageInfo *aMessageInfo)
{
    otCliOutputFormat("sleepy-demo-mtd temperature_state_coapHandler\r\n");
    otError error = OT_ERROR_NONE;
    otMessage *responseMessage;
    otCoapCode responseCode = OT_COAP_CODE_CHANGED;
    otCoapCode messageCode = otCoapMessageGetCode(aMessage);
    otCoapType messageType = otCoapMessageGetType(aMessage);

    responseMessage = otCoapNewMessage((otInstance*)aContext, NULL);
    otEXPECT_ACTION(responseMessage != NULL, error = OT_ERROR_NO_BUFS);

    otCoapMessageInitResponse(responseMessage, aMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode);
    otCoapMessageSetToken(responseMessage, otCoapMessageGetToken(aMessage),
                         otCoapMessageGetTokenLength(aMessage));
    otCoapMessageSetPayloadMarker(responseMessage);

    if(OT_COAP_CODE_GET == messageCode)
    {
        memset(str_buf,0,64);
        sprintf(str_buf,"%f",((float)temp_data/1000.0));
         otCliOutputFormat("\r\nsleepy-demo-mtd coap get\r\n");
        otCliOutputFormat(str_buf);
        error = otMessageAppend(responseMessage, str_buf,
                                strlen((const char*)str_buf));
        otEXPECT(OT_ERROR_NONE == error);

        error = otCoapSendResponse((otInstance*)aContext, responseMessage,
                                   aMessageInfo);
        otEXPECT(OT_ERROR_NONE == error);
    }

exit:

    if (error != OT_ERROR_NONE && responseMessage != NULL)
    {
        otMessageFree(responseMessage);
    }
}


 4.4 Add CoAP start codes in app_init.

otCoapStart(otGetInstance(),OT_DEFAULT_COAP_PORT);

mResource_TEMPERATURE_STATE.mUriPath = mTEMPERATUREStateUriPath;    

mResource_TEMPERATURE_STATE.mContext = otGetInstance(); 

mResource_TEMPERATURE_STATE.mHandler = &temperature_state_coapHandler;

strncpy(mTEMPERATUREStateUriPath, TEMPERATURE_STATE_URI, sizeof(TEMPERATURE_STATE_URI));

otCoapAddResource(otGetInstance(),&mResource_TEMPERATURE_STATE);


 5. Build and download sleepy-demo-mtd.hex into your BRD4161A.


6.Reset BRD4161A to join OpenThread Border Router and use CLI command "ipaddr" to output IPv6 address of Sleepy End Device. 

 

7.Now, you can run coap-client (install libCoAP) on Raspberry Pi OTBR to get temperature reading through CoAP server running on BRD4161A Sleepy End Device.

 


 

1 comment:

  1. Hello. I like your projects. I´m actually trying to do this project too. But when I come to build (step 5), SS5 gives me the error that in sl_sensor_rht.c the #include "app_assert.h" was not succesful since there is no "app_assert.h" found. Did you have similar problems or can this be explained? I am using the BRD4162A A02 board. Many thanks for the help.

    ReplyDelete