5.3. RFD Periodic Reporting of Ambient Temperature from LM75B

5.3.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)
  • External temperature sensor output “LM75B” (2 bytes)

The RFD sleeps in low power mode and wakes up every few seconds to report sensor data. Note that the LM75B is configured to operate in “NORMAL” mode. In this mode, the LM75B samples the ambient temperature once every 100 milliseconds. The micro wakes up every few seconds and reads the latest temperature sampled by the LM75B, sends the data to the gateway, shuts down the radio and goes to low power mode (LPM3). The LM75B is not put into low power/shutdown mode.

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

  • DEV_TYPE_RFD
  • RFD_APP_2
  • PLTFRM_ON_CHIP_VCC_SENSE_ENA
  • PLTFRM_LM75B_TEMP_SENSOR_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 (lm75b sensor output (signed 2 byte value))

The LM75B driver code is in pltfrm/src/lm75b.c

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

5.3.2. Code

#ifdef DEV_TYPE_RFD

#ifdef RFD_APP_2

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

#include <typedefs.h>
#include <system.h>
#include <pltfrm.h>
#include <util.h>
#include <mac_pib.h>
#include <adp.h>
#include <rfd_app.h>
#include <lm75b.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
                    + LM75B_SENSOR_OUTPUT_VALUE_SZ;

   // seq-nr                            <2 bytes>
   // bit mask                          <1 byte / 2 bits valid (0 and 1)>
   // On-chip Vcc sensor o/p            <2 bytes>
   // External temp sensor LM75B 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;
          if (LM75B_startSingleConv(PLTFRM_LM75B_1_DEV_ID, &temp16, NULL) != PLTFRM_STS_SUCCESS)
              SYS_fatal();
          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)
{
   PLTFRM_sts_t sts = PLTFRM_STS_SUCCESS;

   SYS_SET_WAKEUP_INTERVAL(RFD_APP_2_DFLT_WAKE_UP_INTERVAL_SECS);

   /*
    * In normal operation mode, the temperature-to-digital conversion is executed
    * every 100 milli-secs and the "Temp" register is updated at the end of each
    * conversion. This app is not putting the LM75B back into shutdown mode after
    * each conversion as a result the energy consumption is not trivial.
    */
   sts = LM75B_cfg(PLTFRM_LM75B_1_DEV_ID, LM75B_OPN_MODE_NORMAL);
   if (sts != PLTFRM_STS_SUCCESS)
   {
       SYS_fatal();
   }

   return;
}

#endif
#endif
#endif