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.

analogReference causing current loss

Other Parts Discussed in Thread: ENERGIA, MSP430G2553

My test Energia based program simply checks reference voltage in loop() and goes into LP3 sleep for 10 seconds. When I set analogReference to DEFAULT, the current consumption in sleep mode barely registers on my ammeter. Unfortunately, DEFAULT is not useful for internal voltage measurement. When I use INTERNAL2V5, for proper measurement, I run into a serious problem. In sleep mode, the launchpad draws about 180uA. Ouch!

That is when I thought of setting analogReference to INTERNAL2V5 just before measuring voltage and then back to DEFAULT after. That did not help. Its still drawing 180 uA.

The code snippet shows what I'm trying to do. I've stripped out everything else to find the culprit. LP3 sleep mode isn't working as expected when using analogReference(INTERNAL2V5) :-(. Am I doing something wrong? How can I conserve battery life?

void setup()
{
  // Use the 2.5V internal reference
  analogReference(INTERNAL2V5);
  //analogReference(DEFAULT);
}

void loop()
{
  // Get battery voltage
  //analogReference(INTERNAL2V5);
  int v = analogRead(11);
  //analogReference(DEFAULT);

  sleepSeconds(10);
}

  • You don’t write which MSP you’re using, but 100 to 200µA is the typical operating current of the internal voltage reference.

    Apparently does Energia activate the reference if you use it, but does not deactivate the reference if you switch the ADC back to default (or ‘default’ means ‘use what is currently active’, so it won’t do anything - is there a reference option ‘VCC’ or ‘supply’ or so? )

  • Jens-Michael is correct, this issue was identified after Energia 12 was released and I believe the upcoming Energia 13 will fix it:

    (from wiring_analog.c in current master branch 8/22/2014)

    #if defined(__MSP430_HAS_ADC10__)
        ADC10CTL0 &= ~ADC10ENC;                 // disable ADC
        ADC10CTL1 = ADC10SSEL_0 | ADC10DIV_4;   // ADC10OSC as ADC10CLK (~5MHz) / 5
        ADC10CTL0 = analog_reference |          // set analog reference
                ADC10ON | ADC10SHT_3 | ADC10IE; // turn ADC ON; sample + hold @ 64 × ADC10CLKs; Enable interrupts
        ADC10CTL1 |= (channel << 12);               // select channel
        ADC10AE0 = (1 << channel);                  // Disable input/output buffer on pin
        __delay_cycles(128);                    // Delay to allow Ref to settle
        ADC10CTL0 |= ADC10ENC | ADC10SC;        // enable ADC and start conversion
        while (ADC10CTL1 & ADC10BUSY) {         // sleep and wait for completion
            __bis_SR_register(CPUOFF + GIE);    // LPM0 with interrupts enabled
        }
        /* POWER: Turn ADC and reference voltage off to conserve power */
        ADC10CTL0 &= ~(ADC10ON | REFON);
    

  • Thanks for the responses. So I decided to compare current usage if I did the same in CCS. My proggy is sleeping all the time in LPM4 drawing 0.1 uA. Then guess what? I hit the interrupt to wake it up, get the internal voltage, go back to LPM4 sleep, and it continues to draw 184 uA. Argh! Same problem!

    Does my code have the same bug as Energia 12? Below is the main.c

    #include "msp430g2553.h"

    volatile float voltage;

    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      P1OUT &= 0x00;
      P1DIR &= 0x00;
      P1DIR |= BIT0;
      P1REN |= BIT3;
      P1OUT |= BIT3;
      P1IE |= BIT3;
      P1IES |= BIT3;
      P1IFG &= ~BIT3;
      _BIS_SR(LPM4_bits + GIE);  // Go to sleep
      while(1) // Forever
      {}
    }

    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
        unsigned int value=0;
        P1OUT ^= BIT0; // Turn on LED

        ADC10CTL0 = SREF_1 + REFON + REF2_5V + ADC10ON+ADC10SHT_3;    // Using internal reference of 2.5V
        ADC10CTL1 = INCH_11 + ADC10DIV_3;                            // Internal Voltage
        __delay_cycles(1000);                                        // Wait for ADC Ref to settle
        ADC10CTL0 |= ENC + ADC10SC;                                    // Sampling and conversion start
        while (ADC10CTL1 & BUSY);                                    // Wait for conversion to finish
        value = ADC10MEM;                                            // Fetch ADC value
        ADC10CTL0 &= ~(ENC + ADC10ON);                                // Does this turn off ADC?????
        voltage = (value * 2 * 2.5) / 1023;                            // Convert to volts

        P1OUT ^= BIT0;  // Turn off LED
        P1IFG &= ~BIT3; // Clear interrupt flag
        _BIS_SR(LPM4_bits + GIE);  // Go to sleep - Do I really need this?
    }

  • Solved the problem by turning off REFON and ENC. The same solution works for Energia as well.

  • Yes, REFON enables the internal reference, whether used or not. It is of course mandatory if the internal reference is used, but if you don’t (currently) need it, you may turn it off by clearing REFON, even if you still have the internal reference selected in the conversion registers (of course a conversion would fail then).

**Attention** This is a public forum