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.

MSP430G2452 - PinOsc interfering with LPM3 ?

Other Parts Discussed in Thread: MSP430G2452

Hi guys!

I am building a LED wristwatch based on the MSP430G2452. A 32.768kHz crystal is attached and used as ACLK.

MCLK and SMCLK are from the DCO @ 8MHz.

Every 250ms, the WDT (clocked with ACLK) interrupts the MCU to count time (1/4th of a second) and to check the if the user pushed the only touch button (measurement method is RO_PINOSC_TA0 from the CTS library).

It works fine, but the average supply current is around 35µA and I am not able to find this number.

I set the P1.0 pin when I leave LPM3 and I clear it when I enter LPM3. The same goes for P1.6 and LPM0.

The MCU spend 70µs in Active Mode (AM) and what is left of the 250ms in LPM3.

So it is consuming 2.5mA for 70µs (AM @ 8MHz, Vcc = 3.3V) and 1.0µA for 250ms (LPM3 with LFXT1). This leads to 1.7µA average supply current.

This is very different from the measured 35µA.

I'm not using ADC10 or Comp A+. Just TimerA for touch sensing.

I am starting to consider that the MCU is not entering correctly LPM3 as LPM2 or LPM0 current consumption is gives 27µA or 56µA average.

What am I not taking into account ?

main.c : http://pastebin.com/Hz4Aeb3K
RTC.c : http://pastebin.com/3cY2nh6j
RTC.h : http://pastebin.com/jrf7WK9r
state.c : http://pastebin.com/xTwjSKHQ
state.h : http://pastebin.com/6iQG3i4N
CTS_HAL.c (partial) : http://pastebin.com/VcuTk3RA

Thanks

  • Hi Valentin,

    Do you have anything connected to P1.0 or P1.6 that you are setting high and low? If you have LEDs connected (since you mentioned an LED wristwatch) these can consume a fair bit of current which you would also have to consider.

    In addition, have you set up all of your GPIO that are unused as outputs? By default at startup MSP430 pins start as inputs, and if you have nothing connected to these pins and don't reconfigure them, they will be floating and this can throw off your power numbers (this is a topic discussed in many threads in the forum if you want more info - search for floating pins). The recommendation in the device user's guide is to set any unused, unconnected pins as output low in software to eliminate this. If you look in the code examples folder for MSP430G2452, http://www.ti.com/lit/zip/slac467 in the example msp430g2xx2_lpm3.c you'll see an example of how to configure the pins for low power.

    Sorry that I have not looked at your code to check for this myself - that website is not one that I have access to unfortunately. I hope my suggestions will help give you some places to look in your code for extra current though!

    Regards,

    Katie

  • I remembered one more thing that I forgot to add -  there is a software tool called ULP Advisor that can generate remarks on ways you may be able to reduce power based on things in your code. This is another good tool to use (the remarks will show up in the window when you compile your code, like warnings do but marked slightly differently). I believe it is already built-in on the latest versions of CCS and IAR: http://www.ti.com/tool/ulpadvisor

    More info on ULP Advisor: http://processors.wiki.ti.com/index.php/ULP_Advisor?DCMP=MSP430&HQS=Other+OT+ulpadvisor

  • Hello Katie,

    Thanks for your answer. For the measurements, the LEDs are disconnected from the MCU. The only parts connected to it are the reset pull-up, the 32.768kHz crystal and the touch button. All pins are indeed set up as output low, expect for P1.2 which monitors the touch button.

    I will upload my code when I get home to somewhere you can look at it (my Dropbox maybe). I will take a look at ULP Advisor too, thanks for pointing it to me!

    I read that some peripherals request clocks when the MCU goes to LPMx, and thus preventing it to enter this specific LPM, but entering LPMy with y < x. Is it the case for the MSP430G2452 ?

    Regards,

    Val.

  • Hi Val,

    Valentin TRIMAILLE said:
    I read that some peripherals request clocks when the MCU goes to LPMx, and thus preventing it to enter this specific LPM, but entering LPMy with y < x. Is it the case for the MSP430G2452 ?

    That is definitely true on devices that have the "clock request enable" type of feature, which is primarily F5xx/6xx and FR5xx devices. These devices have a register setting you can use to control clock requests where by default the LPM will not shut off a clock if it is currently being requested by a module, potentially causing you to be in a lesser LPM than you expected from your code (e.g., source a timer from SMCLK, then try to go to LPM3 - SMCLK would stay on).

    However, this feature is not present on 2xx devices like the G2452 you are using - on these devices if you have a module like your timer requesting SMCLK on a 2xx device then try to go to LPM3 where SMCLK is normally turned off, the module just won't be getting any clock. So this is likely not your issue (though it is something good to be aware of if you ever use some of these other families that I mentioned). A great way to test this out for yourself, is to configure pins on your device to output all of the clocks (ACLK, MCLK, SMCLK), and then on a scope or logic analyzer you can see the clocks going on and off as you change operating modes.

    I have another question - do you have the debugger connected when doing the measurement, or running a debug session? I know that this can also impact current consumption and is often something that gets missed.

    Regards,

    Katie

  • Ok, it is clear now.

    I configured P1.0 to output ACLK and P1.4 to output SMCLK. ACLK is always on (this is the 32.768kHz crystal) and SMCLK is actually turned off when in LPM3 and does not turn back on before another 250ms. So this is the expected behavior.

    The debugger part of the TI MSP430 launchpad was connected through the jumpers and now I always make measurements with RESET and TEST pins disconnected and after pressing the reset button to be sure. So no debugger.

    I used ULP advisor to clean my code as much as I could, but some required divisions can't be removed. Now the Active Mode is 65µs long, not 70µs. (Optimisation settings tuned and debugger symbols removed). But I am still at ~30µA average current.

    Here is my code on my Dropbox.

  • Hi again !

    I think I have identified the cause of the problem, but I don't know if it is normal behavior or my design is bad.

    In the CTS_HAL.c file, I disabled the configuration of the P1.2 pin as a PinOsc. So the TimerA will not count, but still capture the WDT rising or falling edge and interrupt the same way as if it was counting (the capacitance measurement will be 0 each time).

    This allows me to keep the same time in Active Mode (60µs instead of 65µs is close enough) than if the measurement would take place, but without the current consumption of it.

    And now, I have a stable 1.7µA average current. The high current consumption is caused by the PinOsc feature.

    The P1.2 pin is only in PinOsc mode for about 35µs every 250ms and cause a 30µA raise in average current. I work out that the relaxation osc uses 214mA !!! (214mA for 35µA every 250ms results in an increase of 30µA average current). This can't be right, but obviously the PinOsc function interfere with something even if the TimerA and P1SEL and P1SEL2 registers are saved and then restored to shut down the feature.

    This is weird and I don't know what to think about. When I see the Application Report SLAA515B, nothing is said about the Relaxation Oscillator's power consumption.

    Regards,

    Val.

  • Valentin,

    I would guess there is a component of your calculation of expected current that is missing. There is probably some time that you are in active mode that you are not accounting for. In addition, depending on how you have the cap touch set up, the library may be putting the part in LPM0 for some of the time (not LPM3) depending on how it is configured to use clocks etc - this would also throw off your calculation, especially if there is a very long dwell time for your sensor. I would look through the code and through the library in more detail to find where you might be in active without your pin set that you are using to track the modes you're in on the scope, and for what amount of time you might be in LPM0 not LPM3.

    There's also a number of other cap touch app notes out there as well - I can see that in www.ti.com/lit/pdf/slaa574 there is some discussion of power consumption. There's also www.ti.com/lit/pdf/slaa576 and some others linked here: http://www.ti.com/ww/en/touch_screen_controllers_and_haptics/buttons_sliders_wheels.htm?DCMP=capacitivetouch&HQS=captouch

    I hope this helps. Some of this can quickly become difficult to try to calculate expected power because of so many variables. From what I've seen in Chapter 6 of www.ti.com/lit/pdf/slaa576 it says that average power consumption per electrode for capacitive touch is usually in the tens of uA on average, so I do think the average number you are seeing sounds realistic - it's just understanding what parts are making up that average. I hope the things I've linked will help you look into the performance of your system in more detail and better understand what's going on.

    Regards,

    Katie

  • Thanks again for your answer.

    This "missing component" in my calculation is driving me crazy. Everything I do tells me that about 2µA average current should be possible (and thus validate my 2nd version design), but I can't achieve it.

    I found TI's "Capacitive Touch Power Designer v1.1 here : http://www.ti.com/tool/msptouchpowerdesignergui?DCMP=msp-touch&HQS=cte-pr-ctpd. With the device MSP430G2xx2 series, at 3.6V and 8MHz for the DCO, I add 1 button with a gate time of 24µs (the measured gate time for my configuration), and a refresh rate of 4Hz (250ms response time).

    The result ? 1.32µA average.

    I will continue to look for the cause of it. By the way, the "tens of microamps" is for a button with about 50-100Hz of refresh rate.

    Thanks for the links and your help.

    Regards,

    Val

  • Hi Valentin,

    Are you using your own custom board, or the launchpad? Perhaps it is hardware causing the extra current somewhere (though your description before sounded like you had a pretty minimal setup).

    Just as a sanity check: on the hardware you are using, what current do you see if you load the LPM3 code example for G2452 (I mentioned/linked in one of the earlier posts) and run that? With that code you should be able to get in the range of the datasheet number for LPM3.

    Regards,

    Katie

  • Hi,

    My hardware (LEDs removed) is very similar to the one on the launchpad. all the measurements were made on the launchpad.

    With the lpm3 (ACLK @ 32.768kHz) code example for MSP430G2452, I measrue the following currents:
    - 0.7µA on the launchapd
    - 0.8µA on my watch

    My multimeter is only a 3 3/4 digits dans the display said 000.7µA or 000.8µA, so it's not really precise.

    Regards,

    Val.

  • Hi Val,

    Ok, so it sounds like you got pretty much the exact LPM3 XT1 number from the datasheet for this device (.7uA typ, 1uA max). This I think would mean it probably isn't your hardware and there's still something else in the software that is different and helping to contribute to the current. At this point you may want to start taking out pieces of code until you get back to that LPM3 current and start putting them back in to see what part of the code seems to be the main contributor. Best of luck in your search, and sorry that I can't be much more help in this specific debugging effort!

    Regards,

    Katie

  • Valentin TRIMAILLE said:
    My hardware (LEDs removed) is very similar to the one on the launchpad. all the measurements were made on the launchpad.

    You mentioned earlier that you're removing the test/reset jumpers from the launchpad during current measurement. Have you also removed the UART TX/RX jumpers? One of those connects P1.2 to the emulation section of the launchpad.

  • Hello again,

    I attain a 1.5µA average current when commenting those two lines:

    *((group->arrayPtr[i])->inputPxselRegister) &= ~((group->arrayPtr[i])->inputBits);
    *((group->arrayPtr[i])->inputPxsel2Register) |= ((group->arrayPtr[i])->inputBits); 

    Those lines put the P1.2 pin into PinOsc mode.

    Thanks for your help and perseverance.

    Val.

  • Valentin TRIMAILLE said:
    Those lines put the P1.2 pin into PinOsc mode.

    Well, PinOsc does what it says: it lets the pin oscillate. And oscillation means input logic state changes, which in turn means current consumption. (actually, a certain charge in pAs is required for each state change, which multiplies with the number of transition and divided by the time gives an average current). The smaller the capacitance on the pin, the higher the oscillation frequency and the higher the current consumption. Also, if a timer is switched to operate in PinOsc mode, each oscillation causes a timer action, causing additional operating current, even if the clocks are off.

  • Hello there,

    I know this post is old but all of the information and reflexion we put together is here.
    So, I have some time to work on this again.

    I should summarize a bit maybe.

    I have a MSP430G2452 with one capacitive touch sensor. The MCU sleeps and wakes up every 250ms (WDT+ timed by ACLK from a 32kHz crystal on LFXT1). It wakes for about 2ms to measure the cap sensor and goes back to sleep.
     The measurement method is RO_PINOSC_TA0_WDTp (cf. http://www.ti.com/lit/ug/slaa490b/slaa490b.pdf). Basically, the timer A clock source is the relaxation osc. from the cap sensor pin, and a capture is made after the WDT interrupts (configured as a 1.9ms interval timer). During the 1.9ms, the MCU goes to LPM3.


    Problem: With this setup I should be around 1-2µA of average current on those 250ms, and I measure about 40µA.

    The 1-2µA comes from several sources (the TI touch sensor GUI, simple calculations, ...).

    What I found out recently: the RO_PINOSC_TA0_WDTp measurement method goes to LPM3 while waiting for the WDT interrupt (1.9ms). BUT if I replace this __bis_SR_register(LPM3_bits+GIE); (go to LPM3) with this __bis_SR_register(LPM0_bits+GIE); (same thing but in LPM0), I get the same average current (about 40µA average).

    I deduce that the MCU can't reach LPM3, it is blocked to LPM0 by something, but what ?

    Regards,
    Val.

    Here is the RO_PINOSC_TA0_WDTp measurement function:

    #ifdef RO_PINOSC_TA0_WDTp 
    /***************************************************************************//**
     * @brief   RO method capactiance measurement using PinOsc IO, TimerA0, and WDT+
     *
     *          Schematic Description: 
     * 
     *     \n   element-----+->Px.y
     * 
     *     \n   The WDT+ interval represents the measurement window.  The number of 
     *          counts within the TA0R that have accumulated during the measurement
     *          window represents the capacitance of the element.
     * 
     * @param   group Pointer to the structure describing the Sensor to be measured
     * @param   counts Pointer to where the measurements are to be written
     * @return  none
     ******************************************************************************/
    void TI_CTS_RO_PINOSC_TA0_WDTp_HAL(const struct Sensor *group,uint16_t *counts)
    { 
        uint8_t i;
    
    //** Context Save
    //  Status Register: 
    //  WDTp: IE1, WDTCTL
    //  TIMERA0: TA0CTL, TA0CCTL1
    //  Ports: PxSEL, PxSEL2 
        uint8_t contextSaveSR; 
        uint8_t contextSaveIE1;
        uint16_t contextSaveWDTCTL;
        uint16_t contextSaveTA0CTL,contextSaveTA0CCTL1,contextSaveTA0CCR1;
        uint8_t contextSaveSel,contextSaveSel2;
    
        contextSaveSR = __get_SR_register();
        contextSaveIE1 = IE1;
        contextSaveWDTCTL = WDTCTL;
        contextSaveWDTCTL &= 0x00FF;
        contextSaveWDTCTL |= WDTPW;        
        contextSaveTA0CTL = TA0CTL;
        contextSaveTA0CCTL1 = TA0CCTL1;
        contextSaveTA0CCR1 = TA0CCR1;
        
    //** Setup Measurement timer***************************************************
    // Choices are TA0,TA1,TB0,TB1,TD0,TD1 these choices are pushed up into the 
    // capacitive touch layer.
     
     // Configure and Start Timer
        TA0CTL = TASSEL_3+MC_2;                // TACLK, cont mode
        TA0CCTL1 = CM_3+CCIS_2+CAP;            // Pos&Neg,GND,Cap
        IE1 |= WDTIE;                         // enable WDT interrupt
        for (i = 0; i<(group->numElements); i++)
        {
            // Context Save
            contextSaveSel = *((group->arrayPtr[i])->inputPxselRegister);
            contextSaveSel2 = *((group->arrayPtr[i])->inputPxsel2Register);
    	      // Configure Ports for relaxation oscillator
    	      *((group->arrayPtr[i])->inputPxselRegister) &= ~((group->arrayPtr[i])->inputBits);
    	      *((group->arrayPtr[i])->inputPxsel2Register) |= ((group->arrayPtr[i])->inputBits);
            //**  Setup Gate Timer ********************************************************
    	      // Set duration of sensor measurment
    	      //WDTCTL = (WDTPW+WDTTMSEL+group->measGateSource+group->accumulationCycles);
            WDTCTL = (WDTPW+WDTTMSEL+(group->measGateSource)+(group->accumulationCycles));  
            TA0CTL |= TACLR;                     // Clear Timer_A TAR
            if(group->measGateSource == GATE_WDT_ACLK)
            {
            	//P1OUT &= ~BIT0;
    
                //__bis_SR_register(LPM3_bits+GIE);   // Wait for WDT interrupt
            	__bis_SR_register(LPM0_bits+GIE);
            	//while(!(IFG1 & WDTIFG));
            	//IFG1 &= ~WDTIFG;
    
            	//P1OUT |= BIT0;
            }
            else
            {
    	          __bis_SR_register(LPM0_bits+GIE);   // Wait for WDT interrupt
            }
    	      TA0CCTL1 ^= CCIS0;                   // Create SW capture of CCR1
    	      counts[i] = TA0CCR1;                 // Save result
    	      WDTCTL = WDTPW + WDTHOLD;           // Stop watchdog timer
            // Context Restore
            *((group->arrayPtr[i])->inputPxselRegister) = contextSaveSel;
            *((group->arrayPtr[i])->inputPxsel2Register) = contextSaveSel2;
        }
        // End Sequence
        // Context Restore
        __bis_SR_register(contextSaveSR);   
        if(!(contextSaveSR & GIE))
        {
            __bic_SR_register(GIE);   //        
        }
        IE1 = contextSaveIE1;
        WDTCTL = contextSaveWDTCTL;
        TA0CTL = contextSaveTA0CTL;
        TA0CCTL1 = contextSaveTA0CCTL1;
        TA0CCR1 = contextSaveTA0CCR1;
    }
    #endif
  • I don't know what is blocking the MSP from entering LPM3, what are the things to check (what could prevent entering LPM3) ?

    Val.

  • LPM3 stops MCLK and SMCLK and disables the bias generator for the DCO. If you don’t use SMCLK for anything, then there is no difference between LMP2 and LPM3. If the DCO is required for ACLK or SMCLK, there is no difference between LPM0 and LPM2.

    Entering LPM is not a “now consume less energy” command (if this were possible, why not using less energy all the time?). It is a “switch off this or that if it isn’t otherwise required” command. With “not otherwise required” being the key. (e.g. if DMA is active, entering LPM0 will not disable MCLK as long as the DMA requires it – and peripherals running from MCLK will get those clock ticks, just not the CPU)

    Also keep in mind that a pin that is set for PinOsc will oscillate – whether the timer is counting these oscillations or not. So only one pin must be selected for PinOsc, and only as long as the measurement takes place.
    The library function takes care of selecting the pin that is to be measured, and restoring the original state at the end. So do not select any pin for PinOsc on your own. It will be undone by the library during the measurement, so it doesn’t affect operation, but it will waste energy all the time you are not measuring. And PinOsc does consume a LOT of energy.

  • That's what I thought. I need to take some time and verify that nothing is using SMCLK and MCLK.

    The WDT is used by the pinosc routine and using ACLK with LFXT1 and a 32kHz crystal, this shouldn't require the DCO right?

    PinOsc might be using a lot of energy, but the Application Note SLAA515B shows a current consumption of 1.3µA for a duty cycle of 1s. So with with 250ms, I should (roughly) be around 5-7µA, not 32µA.

    I am going to check is a clock source is used when it shouldn't be.

    Val.

  • If the WDT is running from XT1 (and XT1 is working) or VLO, then DCO is not required for it. Be sure that the timers aren’t using SMCLK.
    The calculation for your expected current isn’t exact. Because DCO takes some time before it releases the CPU. So you are effectively a few µs in LPM0 before you enter AM. But of course the difference is small.

    Nevertheless, the apparent current for PinOsc when running from SMCLK (as in this application note) is ~340µA.For the pin capacitance attached to the pin in this demo scenario. If you have a larger capacitance, the current significantly increases.

    Did you actually measure your AM current (e.g. in a while(1) loop).

    How do you measure your current? Note that normal multimeters are unable to correctly measure currents or voltages with spikes. They work best for constant current and fail when the waveform strays too much for DC. Which definitely is the case here.

     

    Some comments for your code:

    DIVA_0 is 0, so BCSCTL1 |= DIVA_0 has no effect.

    You do P1DIR = 0xFF&~BIT2, but the comment talks about BIT2+BIT6 being inputs. (BIT6 now isn’t)

    And I don’t really understand what you’re doing in your sleep function:
    You enable timer overflow interrupt an set the timer cycle to 4*ms. However, the timer at this point may have any value, even >CCR0. So it may immediately overflow, or at any other time between zero and the desired duration.
    So my guess is: you are spending much less time than you want in LPM, executing the active-mode stuff much more often than planned. Hence the higher average current.

    You should at least set the TACLR bit when starting the delay. And perhaps some checking, because if ms I >16k, the function will also fail.

    A better approach would be to let the timer run in cont mode all the time (it is already running 99.9% of the time for the sleep), use the CCRx interrupt instead of the timer overflow (and the TIMER0_A0_VECTOR), and just set CCRx to TAR+4*ms for the delay.

  • Thanks for the advice Jens-Michael.

    I desperately tried to find what peripheral could use MCLK or SMCLK but found nothing.

    The current consumption is still "too" high with TimerA turned off and sourced from ACLK. USI and ADC10 are off and not using SMCLK.

    I made a smaller project with only the watchdog timer interrupt every 1.9ms (for tests, should be 250ms in release), PinOsc measurement and sleep to LPM3 until WDT wake us up.

     I measure with a multimeter in the µA range. It is not the best but it gives me a good idea IMO.

    Measured current in active mode (constantly measuring touch sensor, no LPM3): 2.78mA
    Measured current with LPM3 (measuring touch sensor then LPM3 for the rest of the 1.9ms): 141µA
    Touch sensor measurement takes 62µs.

    This once again corresponds to 62µs of active mode followed by 1.9ms of LPM0 (not LPM3...):

    (62µs*2.78mA + 1.9ms*0.7µA)/(1.9ms + 62µs) = 141µA

    Here is the project: Dropbox.

    Val.

  • I kept this thread open for some time, in case I do have another idea, but I don’t. Your test program verifies the basic assumptions for the PinOsc and LPM3 currents. If your whole project gives unexpected results, it is apparently doing something unexpected. Like not doing the timing you expect (spending more time in active mode than you think).

    Sorry, but I don’t have the time to dig into foreign code too deeply. Also, my own code is already dancing before my eyes. :(

**Attention** This is a public forum