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.

CCS/MSP430G2553: need help using an accelerometer

Part Number: MSP430G2553
Other Parts Discussed in Thread: MSP430FR2311

Tool/software: Code Composer Studio

I have to put my micro in Low Power Mode after 10 seconds using a Timer interrupt. once its in LPM, I have to wake it up with an extreme value from the accelerometer in any axis using the ADC interrupt. also I have to use the onboard LEDs to indicate the state of the micro, RED for sleep, GREEN for Awake.

what I'm haing trouble with the most is understanding how to invoke the ADC ISR, when does the program go into that ISR?? 

here is my code:

#include <msp430g2553.h>

unsigned int tic = 0, sec = 1;

void main (void)
{
    //Setup
    WDTCTL = WDTPW + WDTHOLD; //Stop Watchdog Timer

    //Setup LEDs
    P1DIR |=  BIT0 + BIT6;
    P1OUT |=  BIT6;
    P1OUT &= ~BIT0;

    //Setup ADC
    ADC10CTL0 = SREF_0 + ADC10SHT_0 + ADC10SR + ADC10ON + ADC10IE;
    ADC10CTL1 = SHS_0 + ADC10DF + INCH_3 + ADC10DIV_0 + CONSEQ_0;
    ADC10AE0 = 0x0E; //set P1.1 P1.2 and P1.3 as ADC inputs

    //Setup Timer A0
    TA0CTL = 0X0210; //Setup Timer/Start Timer
    TA0CCTL0 = CCIE;  //Enable interrupt on TA0.0
    TA0CCR0 = 50000; //Period of 50ms or whatever interval you like.
    
    __enable_interrupt(); //Enable General Interrupts. Best to do this last.

    while (1){} //Empty infinite while loop.
}

// Timer 0 A0 Interrupt Service Routine
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer0_A0_ISR( void )
{
    tic++;

    if(tic % 20 == 0) //increase integer 'sec' after every second has passed
    {
        sec++; 
    }
    if(sec % 11 == 0) //after 10 seconds, turn off green LED and turn on red LED to indicate micro sleeping
    {
        P1OUT &= ~BIT6;
        P1OUT |=  BIT0;
        TA0CCR0 = 0; //stop the timer
        _BIS_SR(LPM4_bits + GIE);
    }
}

// ADC10 Interrupt Service Routine
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR( void )
{

    if (ADC10MEM < 0x88)
    {
        P1OUT &= ~BIT0;
        P1OUT |=  BIT6;
    }
    else
    {
        TA0CCR0 = 50000; //turn on timer
    }
}

  • The ADC ISR will be called when the conversion completes, but first the conversion has to be started.

    Since you used SHS_0, you should start it by setting ADC10SC somewhere.

    I recommend you look through the example programs (link from the Product page). msp430g2x33_adc10_10.c may be particularly relevant.
  • Thank you that helps but now I don't understand how moving my accelerometer helps invoke that ISR. It seems that as soon as I enable and start the conversion the program goes into the ADC ISR without me touching the accelerometer.
  • The ADC (ADC10SC->ISR) gives you the level at the moment you ask for it -- i.e. a polling mechanism. In order to sense motion, you need to poll frequently enough to detect the motion you're looking for [Nyquist again]. This could be done in the background, e.g. using a low-power timer, but the software still has to wake up each time to do the comparison. (By contrast, the MSP430FR2311 (e.g.) ADC has thresholding; with that the hardware could do the comparison as well.)

    I suspect you want something more like a comparator (COMP_A), which runs continuously, but it looks like the G2553 only has one of those, i.e. you can only watch one axis at a time. There exist comparators as separate ICs as well.

    There are also accelerometer devices which can trigger interrupts based on motion. These are most/all digital (SPI/I2C) devices, and they do the polling/comparison for you -- the work is still being done, but since they're purpose-built they may be able to do it at lower power than you can. As far as I know, TI doesn't sell these [so I guess I can mention brand-names], but ST Micro e.g. has a collection of them.
  • If you can define an "extreme value from the accelerometer" we can help you better on meeting the "wake up" req't.
  • Yeah so apparently I have to tilt my accelerometer ( I'm using an MMA7361 by the way) and program it so that when I tilt it enough the micro comes out of low power mode. But I have no idea how to do that, what can I do to my program so that the micro waits for me to tilt the acceleremoter and make it get out of low power mode.
  • for the '2553 and mma7631 by themselves , best you can _reasonably_do, I think, wrt the 'wake up when something major happens' requirement is use a rising edge from the 0g-detect output of the accelerometer. start with detecting that, in any case. (see section 8.2.7 of SLAU144)
    here's the catch, as I see/understand it: normally a 'jerk' on the accelerometer causes a jump in one or more of the analog output voltage, the jump can be positive or negative... but you won't necessarily see said jump unless you're already awake and running adc conversions.
    there is one possible alternative gimmick I see that you can perhaps use: treat the accelerometer's outputs as digital signals. in which case ( as an example) a jerk of an accelerometer output from "< 0.3*Vcc" to about "0.6*Vcc" or more is in effect a rising edge on the pin and can cause a wakeup. but what will it take, shake-wise, to get any output to hit the threshold for '1'?

  • Do you have a precise specification for what you're trying to do? I suspect the words are important. My guess is that the intention was for you to use your engineering skills, not invent a never-before-seen technique (though those are fun too).

    Strictly speaking, the CPU is not in "Low Power Mode" if it's executing any instructions. I'll point out that your original code doesn't quite fit this, since it has to wake up to compare ADC10MEM.

    However, sometimes "Low Power Mode" is used in a looser sense, meaning that main() executes (e.g.) "LPM0;", but there are still interrupts going off. In that context, "coming out of LPM" means waking up main() using (e.g.) "LPM0_EXIT;". That definition would allow for periodic polling using the ADC.
  • Basically go into low power mode then exit low power mode by moving/tilting the accelerometer. but my main problem is I don't know how to get any output from shaking the accelerometer what must I write into my code for the msp430 to take an input from the accelerometer and produce an output.

    I connected the MMA7361 x, y, and z pins onto p1.1, p1.2, p1.3 respectively if that helps..
  • Perhaps the simplest way to get a periodic poll is to set up a periodic timer interrupt, and inside that ISR set ADC10SC . When the ADC completes, the ADC ISR will be called, and you can compare the result against your threshold. By adjusting the timer's CCR0 value, you can make the poll as fast or slow as you wish. You may want to get this working first, based on the code above, but that will only watch 1 channel (axis).

    Since you're watching 3 channels, you'll need to read up on CONSEQ, MSC, and the DTC feature. These are all illustrated in that example (adc10_10.c) I referred you to before. SLAU144J Figure 22-6 is also informative.

    Go into LPM by executing "LPM0;" in main() (not in an ISR).
  • Ok thank you you've been of great help, I'll see what I can do from here :)

**Attention** This is a public forum