5.1. RFD Periodic Reporting of Battery Voltage and On-Chip Temperature

5.1.1. Description

Implements an RFD application in which the following data is reported to the gateway every few seconds.

  • On-chip temperature sensor output (2 bytes)
  • On-chip Vcc sensor output (2 bytes)

The RFD sleeps in low power mode and wakes up every few seconds to report sensor data. When sleeping, all the components (MSP430 and CC2520) are in low power/shutdown mode to reduce energy consumption thereby increasing battery life. On waking up, this app wakes up and triggers a single conversion each of the on-chip temperature and the Vcc sensor. It then sends a data frame to the gateway, receives an ack and goes back to low power mode.

When building an RFD executable which includes rfd_app.c, these macros need to enabled :-

  • DEV_TYPE_RFD
  • RFD_APP_0
  • PLTFRM_ON_CHIP_TEMP_SENSOR_ENA
  • PLTFRM_ON_CHIP_VCC_SENSE_ENA

The data packet sent out by this app has the following format :-

  • 2 bytes (packet sequence number)
  • 1 byte (sensor bit mask with value 0x7)
  • 2 bytes (On-chip Vcc sensor output (unsigned 2 byte value))
  • 2 bytes (On-chip temperature sensor output (signed 2 byte value))

The on-chip temperature sensor and on-chip Vcc sensor code is in pltfrm/src/temp_sensor.c and pltfrm/src/vcc_sense.c

To learn more about the sensors and the API, visit sections On-Chip Temperature Sensor (TI MSP430) and On-Chip Voltage Sensor (TI MSP430).

5.1.2. Code

#ifdef DEV_TYPE_RFD

#ifdef RFD_APP_0

#if defined(PLTFRM_ON_CHIP_VCC_SENSE_ENA) \
    && defined(PLTFRM_ON_CHIP_TEMP_SENSOR_ENA)

#include <typedefs.h>
#include <system.h>
#include <pltfrm.h>
#include <util.h>
#include <mac_pib.h>
#include <adp.h>
#include <rfd_app.h>

#define RFD_APP_DATA_SEQ_NR_SZ   2
#define RFD_APP_DATA_SNSR_BIT_MSK_SZ   1

UINT16_t RFD_APP_pktSeqNr = 0;

// Stats
UINT16_t RFD_APP_dataTxReqCnt = 0;
UINT16_t RFD_APP_dataRxReqFailCnt = 0;
UINT16_t RFD_APP_cnfrmOkCnt = 0;
UINT16_t RFD_APP_cnfrmFlrCnt = 0;

void RFD_APP_buildSendSnsrUpdate(void)
{
   UINT8_t pktLen = ADP_ELEMENT_TYPE_LEN
                    + RFD_APP_DATA_SEQ_NR_SZ
                    + RFD_APP_DATA_SNSR_BIT_MSK_SZ
                    + PLTFRM_ON_CHIP_VCC_SENSOR_OUTPUT_LEN
                    + PLTFRM_ON_CHIP_TEMP_SENSOR_OUTPUT_LEN;


   // seq-nr                            <2 bytes>
   // bit mask                          <1 byte / 3 bits valid (0, 1 and 2)>
   // On chip Vcc sensor o/p            <2 bytes>
   // Internal temp sensor o/p          <2 bytes>


   ADP_cntxt.txParams.bdHndl = SYS_allocMem(pktLen);

   if (SYS_BD_HNDL_IS_VALID(ADP_cntxt.txParams.bdHndl))
   {
       UINT8_t *buff_p = SYS_GET_BD_BUFF(ADP_cntxt.txParams.bdHndl);
       UINT8_t *flag_p, snsrFlag = 0x0;

       buff_p += ADP_ELEMENT_TYPE_LEN;

       RFD_APP_pktSeqNr ++;
       buff_p = UTIL_htons(buff_p, RFD_APP_pktSeqNr);

       flag_p = buff_p;
       buff_p ++;  // skip sensor flag field ...

       {
          UINT16_t vcc = 0;
          pltfrm_vccSenseInit( );
          vcc = pltfrm_vccSense();
          buff_p = UTIL_htons(buff_p, vcc);
          snsrFlag |= BIT0;
       }

       {
          SINT16_t temp16 = 0;
          PLTFRM_onChipTempSensorInit();
          temp16 = PLTFRM_readOnChipTempSensor();
          buff_p = UTIL_htons(buff_p, temp16);
          snsrFlag |= BIT1;
       }

       *flag_p = snsrFlag;

       ADP_cntxt.txParams.destShortAddr = LPWMN_COORD_MAC_SHORT_ADDR;

       RFD_APP_dataTxReqCnt ++;

       if (ADP_appPyldTxReq() != ADP_STS_SUCCESS)
       {
           RFD_APP_dataRxReqFailCnt ++;
           SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
       }
   }
}

void RFD_APP_wakeUpProc( )
{
   RFD_APP_buildSendSnsrUpdate();
}

void RFD_APP_nodeJoinDoneInd(void)
{
   RFD_APP_wakeUpProc( );
}

void RFD_APP_prepareToEnterLPM(void)
{
   // Interrupts are disabled globally at this point.
   // The MSP430 will go into deep sleep mode on returning
   // from this function.
   return;
}

void RFD_APP_wakeUpTimerExpEvt(void)
{
   return;
}

void APP_procGPIOEvt()
{
   return;
}

void RFD_APP_evtHndlr(UINT16_t globalEvtId, void *params_p)
{
   switch (globalEvtId)
   {
      case SYS_GLOBAL_EVT_ADP_DATA_CONFIRM:
           {
              ADP_dataCnfrmParams_s *dcParams_p = (ADP_dataCnfrmParams_s *)params_p;
              if (dcParams_p->sts == ADP_STS_SUCCESS)
              {
                  RFD_APP_cnfrmOkCnt ++;
              }
              else
              {
                  RFD_APP_cnfrmFlrCnt ++;
              }
              SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
           }
           break;

      default:
           break;
   }

   return;
}

void RFD_APP_init(void)
{
   SYS_SET_WAKEUP_INTERVAL(RFD_APP_0_DFLT_WAKE_UP_INTERVAL_SECS);
   return;
}

#endif
#endif
#endif