Showing posts with label temperature monitoring. Show all posts
Showing posts with label temperature monitoring. Show all posts

Thursday, August 10, 2023

LPSTK-CC1352R/HDC2080 measurement

Use the following code relacing mainThread in i2copt3001_cpp.cpp of i2copt3001_cpp example to read LPSTK-CC1352R/HDC2080 temperature/humidity measurement

/*
 *  ======== mainThread ========
 */
uint8_t reg_addr, high_id, low_id, drdy, high_temp, low_temp, high_humi, low_humi;
uint16_t temp16, humi16;
float temperature, humidity;
uint8_t drdy_int_conf[2];

void *mainThread(void *arg0)
{
    uint16_t sample;
    int32_t luxValue;
    uint8_t data;
    uint8_t addr;

    /* I2C structures*/
    I2C_Handle      i2c;
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;

    /* Call driver init functions */
    Display_init();
    GPIO_init();
    I2C_init();

    /* Open the UART display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        while (1);
    }

    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(CONFIG_I2C_OPT3001, &i2cParams);
    if (i2c == NULL) {
        Display_printf(display, 0, 0, (char *)"Error Initializing I2C!\n");
        while (1);
    }
    else {
        Display_printf(display, 0, 0, (char *)"I2C Initialized!");
    }

    i2cTransaction.targetAddress=0x41; //HDC2080 device address

    /* Read Device ID High byte */
    reg_addr=0xFF;
    i2cTransaction.writeBuf = &reg_addr;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf = &high_id;
    i2cTransaction.readCount = 1;
    if (I2C_transfer(i2c, &i2cTransaction)){
        Display_printf(display, 0, 0,
                        (char *)"I2C device High ID 0x%x!", high_id);
    }

    /* Read Device ID Low byte */
    reg_addr=0xFE;
    i2cTransaction.writeBuf = &reg_addr;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf = &low_id;
    i2cTransaction.readCount = 1;
    if (I2C_transfer(i2c, &i2cTransaction)){
        Display_printf(display, 0, 0,
                        (char *)"I2C device Low ID 0x%x!", low_id);
    }

    while(1)
    {
        //Write drdy_int_conf to 5 samples per second
        drdy_int_conf[0]=0x0F;
        drdy_int_conf[1]=0x01;
        i2cTransaction.writeBuf = drdy_int_conf;
        i2cTransaction.writeCount = 2;
        i2cTransaction.readBuf = &drdy;
        i2cTransaction.readCount = 0;
        if (I2C_transfer(i2c, &i2cTransaction)){
            Display_printf(display, 0, 0,
                            (char *)"Data ready byte? 0x%x", drdy);
        }

        //read if data is ready
        reg_addr=0x04;
        i2cTransaction.writeBuf = &reg_addr;
        i2cTransaction.writeCount = 1;
        i2cTransaction.readBuf = &drdy;
        i2cTransaction.readCount = 1;
        if (I2C_transfer(i2c, &i2cTransaction)){
            Display_printf(display, 0, 0,
                            (char *)"Data ready byte? 0x%x", drdy);
        }

        if(drdy&0x80)
        {
            //Data is ready and start to read temperature and temperature data
            /* Read Temperature Low byte */
            reg_addr=0x00;
            i2cTransaction.writeBuf = &reg_addr;
            i2cTransaction.writeCount = 1;
            i2cTransaction.readBuf = &low_temp;
            i2cTransaction.readCount = 1;
            if (I2C_transfer(i2c, &i2cTransaction)){
                Display_printf(display, 0, 0,
                                (char *)"Temperature Low byte 0x%x!", low_temp);
            }

            /* Read Temperature High byte */
            reg_addr=0x01;
            i2cTransaction.writeBuf = &reg_addr;
            i2cTransaction.writeCount = 1;
            i2cTransaction.readBuf = &high_temp;
            i2cTransaction.readCount = 1;
            if (I2C_transfer(i2c, &i2cTransaction)){
                Display_printf(display, 0, 0,
                                (char *)"Temperature high byte 0x%x!", high_temp);
            }

            temp16=(uint16_t)high_temp;
            temp16=(temp16<<8)|((uint16_t)low_temp);
            temperature = (((float)temp16)/65535)*165-40.5;
            Display_printf(display, 0, 0,(char *)"Temperature: %.1f", temperature);

            /* Read Humidity Low byte */
            reg_addr=0x02;
            i2cTransaction.writeBuf = &reg_addr;
            i2cTransaction.writeCount = 1;
            i2cTransaction.readBuf = &low_humi;
            i2cTransaction.readCount = 1;
            if (I2C_transfer(i2c, &i2cTransaction)){
                Display_printf(display, 0, 0,
                                (char *)"Temperature Low byte 0x%x.1!", low_humi);
            }

            /* Read Humidity High byte */
            reg_addr=0x03;
            i2cTransaction.writeBuf = &reg_addr;
            i2cTransaction.writeCount = 1;
            i2cTransaction.readBuf = &high_humi;
            i2cTransaction.readCount = 1;
            if (I2C_transfer(i2c, &i2cTransaction)){
                Display_printf(display, 0, 0,
                                (char *)"Temperature high byte 0x%x!", high_humi);
            }

            humi16=(uint16_t)high_humi;
            humi16=(humi16<<8)|((uint16_t)low_humi);
            humidity = (((float)humi16)/65535)*100;
            Display_printf(display, 0, 0,(char *)"Humidity: %f", humidity);
        }
    }
    return (NULL);
}
 

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.

 


 

Wednesday, November 26, 2014

How to do temperature monitoring using CC2530 with TI Z-Stack

The battery monitor can also be used to do some simple temperature monitoring in CC2530. When the battery monitor is connected to the internal temperature sensor instead of the supply voltage AVDD5.

The following readTemperature function provides capability to read temperature using CC2530 internal ADC and sensor. When first time call this function, you have to keep temperature at 22oC for calibration.

int8 readTemperature(void)
{
  static uint16 voltageAtTemp22;
  static uint8 bCalibrate=TRUE; // Calibrate the first time the temp sensor is read
  uint16 value;
  int8 temp;

  ATEST = 0x01;
  TR0  |= 0x01;
 
  /* Clear ADC interrupt flag */
  ADCIF = 0;

  ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_512 | HAL_ADC_CHN_TEMP);

  /* Wait for the conversion to finish */
  while ( !ADCIF );

  /* Get the result */
  value = ADCL;
  value |= ((uint16) ADCH) << 8;

  // Use the 12 MSB of adcValue
  value >>= 4;
 
  /*
   * These parameters are typical values and need to be calibrated
   * See the datasheet for the appropriate chip for more details
   * also, the math below may not be very accurate
   */
    /* Assume ADC = 1480 at 25C and ADC = 4/C */
  #define VOLTAGE_AT_TEMP_25        1480
  #define TEMP_COEFFICIENT          4

  // Calibrate for 22C the first time the temp sensor is read.
  // This will assume that the demo is started up in temperature of 22C
  if(bCalibrate) {
    voltageAtTemp22=value;
    bCalibrate=FALSE;
  }
 
  temp = 22 + ( (value - voltageAtTemp22) / TEMP_COEFFICIENT );
 
  // Set 0C as minimum temperature, and 100C as max
  if( temp >= 100)
  {
    return 100;
  }
  else if (temp <= 0) {
    return 0;
  }
  else {
    return temp;
  }
}