This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2433: Daily Temperature Recorder in LPM3 Mode

Part Number: MSP430FR2433
Other Parts Discussed in Thread: ENERGYTRACE

Hello forumites.

I am planning to develop a year long experimental prototype with 2xAA battery. My aim is reducing the mean current as much as possible. For that purpose, I am using Energy Trace(not++) so I can only see how much current my launchpad spends- or power and energy. Obviously for development purposes, I am recording temperature for every 8 seconds.

I am using LPM3 mode with periodic wake ups and I activate internal temperature sensor interrupts after waking up-so I can do single reading and go to sleep again. But how can I squeeze more energy out of this prototype? I am doing what ULP advises me to do so: converting all pins except A12(Pin 1.2) to Input with Pulldown enabled. I am using ACLK clock for both ADC Core and Timer. Any suggestion is much appreciated. I don' t ask anyone to give me code, don't get me wrong but tell me activate this disable that etc.

I also spend 100 uA in the sleep mode(LMP0 stated as 40uA, LPM3 with RTC spends 1uA according to the data sheet), there must be some peripherals active that I need to disable more somewhere.

//******************************************************************************
// In this example project, we are mostly sleeping and waking up every 8 seconds
// to measure temperature and record it to FRAM Information Memory Region.
//
// Memory Layout:
//   Byte 1: Session ID(To track how many times recording session is started)
//   Byte 2: How many recordings are saved in the session
//   Byte 3-..: Start to put recordings from byte 3 and onward. Use the counter
//     value in Byte 2 to understand how many readings are valid.
//******************************************************************************

#include <msp430.h> 

void FRAMWriteTemp(void);
void FRAMWriteSession(void);
void initGPIOUnusedInputPulldown(void);
void initADC(void);
void initACLKTimer(void);

// See device datasheet for TLV table memory mapping
#define CALADC_15V_30C  *((unsigned int *)0x1A1A)                 // Temperature Sensor Calibration-30 C
#define CALADC_15V_85C  *((unsigned int *)0x1A1C)                 // Temperature Sensor Calibration-85 C
#define FRAM_TEST_START 0x1800

volatile long temp = 0;
volatile long ADC_Value = 0;
unsigned int count = 0;

char *FRAM_start_ptr = (char*) FRAM_TEST_START;
char *FRAM_count_ptr = (char*) (FRAM_TEST_START + 1);
char *FRAM_write_ptr = (char*) (FRAM_TEST_START + 2);

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    initGPIOUnusedInputPulldown();

    initACLKTimer();

    initADC();

    FRAMWriteSession();

    while (count < 250)
    {
        // The temperature (Temp, C)=
        temp = (ADC_Value - CALADC_15V_30C) * 55
                / (CALADC_15V_85C - CALADC_15V_30C) + 30;
        FRAMWriteTemp();

        __bis_SR_register(GIE | LPM3_bits); // Enable maskables and start Low Power Mode 0
    }

    return 0;
}

// Timer A0 interrupt service routine: Enable the ADC interrupts and start
// ADC conversion. Delay for some time to settle ref voltage setting.
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
    TA0CTL &= ~(TAIFG);         // Clear the interrupt
    ADCIE |= ADCIE0;            // Enable the conversion complete interrupt;
    ADCCTL0 |= ADCENC | ADCSC;  // Enable and start the conversion
    __delay_cycles(400);        // Delay for reference settling
}

// Record ADC Reading and disable ADC Interrupts. After this ISR, control goes
// to main loop
#pragma vector = ADC_VECTOR
__interrupt void ADC_ISR(void)
{
    __bic_SR_register_on_exit(LPM3_bits);
    ADC_Value = ADCMEM0;

    ADCIE &= ~ADCIE0;            // Disable the conversion complete interrupt;
}

void FRAMWriteTemp(void)
{
    SYSCFG0 = FRWPPW | PFWP; // This instruction removes DFWP, makes FRAM writeable
    *FRAM_count_ptr = (*FRAM_count_ptr) + 1;    // Update count field in FRAM
    *FRAM_write_ptr++ = temp;                   // Record the temperature
    SYSCFG0 = FRWPPW | PFWP | DFWP;     // This instruction locks FRAM again
    count++;                            // Update count
}

void FRAMWriteSession(void)
{
    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_start_ptr = (*FRAM_start_ptr) + 1;
    *FRAM_count_ptr = 0;
    SYSCFG0 = FRWPPW | PFWP | DFWP;
}

void initGPIOUnusedInputPulldown(void)
{
    // Set all P1 pins except 1.2 to input with pulldown resistor
    P1SEL1 = P1SEL0 = 0;
    P1DIR = 0;
    P1OUT &= ~(BIT0 | BIT1 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    P1REN |= BIT0 | BIT1 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7;

    // Set all P2 pins to input with pulldown resistor
    P2SEL1 = P2SEL0 = 0;
    P2DIR = 0;
    P2OUT = 0;
    P2REN = 0xFF;

    // Set all P3 pins to input with pulldown resistor
    P3SEL1 = P3SEL0 = 0;
    P3DIR = 0;
    P3OUT = 0;
    P3REN = 0xFF;

    // Finally, set P1.2 to analog function
    P1SEL1 |= BIT2;
    P1SEL0 |= BIT2;             // Set 11 to both bits for Temp Sensor(A12 -> P1.2)

    PM5CTL0 &= ~LOCKLPM5;       // Turn on IO
}

// Configure Analog 12(Internal Temp Sensor)
void initADC(void)
{
    // Configure the ADC
    ADCCTL0 &= ~ADCSHT_15;      // Clear Conversion Clock Cycles
    ADCCTL0 |= ADCSHT_1;        // Set SHT to 8 Conversion Clock Cycles
    ADCCTL0 |= ADCON;           // Set ADC Core on

    ADCCTL1 |= ADCSSEL_1;       // Choose ACLK as Source Clock
    ADCCTL1 |= ADCSHP;          // Sample signal source = sampling timer
    //ADCCTL1 |= ADCDIV_7;      // ADC Clock Divider set to /8 to slow sampling

    ADCCTL2 |= ADCRES_1;        // 10-bit conversion results
    //ADCCTL2 |= ADCPDIV__64;   // ADC Pre Clock Divider set to /64 to slow sampling

    ADCMCTL0 |= ADCSREF_1 | ADCINCH_12;      // Set A2 as ADC Input

    // Configure reference
    PMMCTL0_H = PMMPW_H;                             // Unlock the PMM registers
    PMMCTL2 |= INTREFEN | TSENSOREN; // Enable internal reference and temperature sensor
}
// Intended to raise interrupt every 8 seconds to initiate temperature sensing
void initACLKTimer(void)
{
    TA0CTL |= TASSEL__ACLK;                     // Set clock source to ACLK
    TA0CTL |= TAIE;                             // Enable Timer A Interrupts
    TA0CTL |= TACLR;                            // Clear Timer A Register
    TA0CTL |= ID_2;                             // Slow Timer by 2^X (ID_X)
    //TA0EX0 |= TAIDEX_7;                       // Slow timer by Y+1 times (TAIDEX_Y)
    TA0CTL |= MC__CONTINUOUS;                   // Set continuous mode
}

  • The Usual Suspects:

    1) If you're using the Launchpad, remove all the jumpers except 3V3/GND/SBWTDIO/SBWTCK.

    2) When using EnergyTrace, use "Free Run" rather than "Run".

    3) Use a 32kHz crystal if at all possible. The REFOCLK on the FR2433 costs about 20uA. The  Launchpad has a crystal at Q1, but you'll need some light soldering to connect it.

  • Thanks for your suggestions. I have two main questions.

    1. I could not find any good information about why jumpers are used in 3 related datasheets-user guides for FR2433. Where can I find concise info about them?
    3. I tried to feed ACLK with XT1 or even using RTC butI was not able to understand why I was always in oscillator fault test loop in FR2433 RTC examples. Probably not soldering it was the problem?

  • 1 The jumper descriptions are scattered through Section 2 of the Launchpad User Guide (SLAU739). The descriptions are brief; full details are in the schematics (Section 6).

    3) Yes, to connect the crystal you need to make solder bridges across the R2 and R3 positions (near Q1)  [Ref User Guide Sec 2.5]. You probably should remove the 0-Ohm resistors at R4/R5 to disconnect from the P2.0/1 pins, though that isn't strictly necessary (if you're careful).

    ------------

    Unsolicited:

    A) P1.2 is A2, not A12. A12 (temperature) doesn't have a pin, but you need to set TSENSOREN. I don't expect this is contributing to your symptom.

    B) To use the temperature sensor effectively you'll need the internal reference (INTREFEN). The data sheet doesn't seem to say, but on other FR2 devices I've measured it at 60uA, so you'll want to turn it on and off as needed. (For your final device, you may want to consider an external temperature sensor, which will be more accurate and maybe lower-power.)

    [Edit: Looking again, I see you Are turning INTREFEN on. This is probably contributing to your power usage, so you should duty cycle it.]

    C) I encourage you to look over the Examples, which can provide paste-able code as well a point of comparison. Particularly relevant might be msp430fr243x_adc10_16.c [temperature] and msp430fr243x_LPM3_01.c [LPM3]:

    https://dev.ti.com/tirex/explore/node?node=AJ4FbEhpy0QN9VgmlO5i8g__IOGqZri__LATEST

  • Many thanks to you. The real culprit was leaving INTREFEN enabled during the sleep mode as you told. Now I slashed average current expenditure to 31 uA(more than 65 uA uA spending during sleep is gone). Now Energy Trace calculates this prototype would run  over 6 years if I use 2250 mAH, just amazing. Obviously I checked the recorded values and they are correct temperature.

    Next I will try to put XT1 into working mode but I just do not trust my soldering/desoldering skills for that for now. Maybe I will need more FR2433 launchpads and will sacrifice one or two of them during desoldering. If I can reduce it 20 uA expenditure from REFO using over XT1, it might be like 18 year experiment. I do not how much I can squeeze more. I will convert busy delay function to Timer interrupt also, but that is really miniscule upgrade since sleep mode dominates and saving 400 cycle of MCU running every 12 hours wont give me that much.

    What kind of battery setup would you suggest? I have 2200 mAH Lipo which gives 4.1 V when fully loaded but it is beyond the optimal range. I am also thinking using 2xNiMh batteries(2.4V total) and it is inside limits I can see(2.2V is needed for FRAM operations). Or should I go for Lipo plus 3.3 LDO?

  • I have 2200 mAH Lipo which gives 4.1 V when fully loaded but it is beyond the optimal range. I am also thinking using 2xNiMh batteries(2.4V total) and it is inside limits I can see(2.2V is needed for FRAM operations). Or should I go for Lipo plus 3.3 LDO?

    I haven't measured it, but on a quick search rechargeable cells may have a self-discharge which could limit their use for continuous lower power operation lasting years.

    E.g. see the mention of self-discharge in BU-802b: What does Elevated Self-discharge Do?

  • That is more in favor of regular coin batteries bound in parallel then, as my friend warned supplying extra voltage will make the system spend more current for the same output. 3V is not so high compared to what Lipo provides. Maybe even 2 x AA batteries might be the best solution.