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.

MSP430G2553: Problem with MSP430G2553 ADC

Part Number: MSP430G2553

I am using MSP-EXP430G2 Launchpad (with MSP430G2553 microcontroller) to take samples from a voltage divider. To be more specific, I have an FSR (force sensitive resistor) sensor in series with a 10 K-Ohm fixed resistor as my voltage divider. I am powering up the FSR sensor using the Vcc from my launchpad. The output of the voltage divider or the input of the ADC is variable and dependent on the amount of pressure exerted on the FSR sensor (more pressure on FSR sensor generates higher voltage on the voltage divider output). I set up my code such that my microcontroller is normally in low power mode 3 (LPM3) and only when my up-mode counter overflows, an interrupt service routine (ISR) is generated to take a single ADC sample using channel 0 (A0) of the ADC. The trouble I am having is the fact that the sampled value from my ADC channel stays only in the range of 0 to 80 depending on the amount of pressure I exert on the FSR. In other words, I should see a value of around 1023 (because of the 10 bit ADC) when I exert a lot of pressure on the sensor. However, the ADC output only shows 80. In addition, when I remove the ISR section of the code and move the code to take the ADC sample from my main function, the ADC works fine (I have a value of around 1000 for ADC output when I compress the FSR sensor really hard). I will appreciate any suggestions/help to solve this issue. 

#include <msp430g2553.h>
#define CONSEQ_0
volatile unsigned int ADC_value=0;
void FaultRoutine(void);


int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
FaultRoutine(); // If calibration data is erased run FaultRoutine()

//Configure Clock
BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ;
DCOCTL = CALDCO_1MHZ; //Set DCO = 1MHz
BCSCTL2 = DIVS_0; //SMCLK = DCO = 1MHz
BCSCTL3 |= LFXT1S_0 + XCAP_3; // clock system setup to run with watch crystal at 32 KHz
IFG1 &= ~OFIFG; // Clear OSCFault flag

//Configure pins
P1DIR = 0xFF; // all pins in port 1 as output
P1OUT = 0; // assign zero (low) to all pins in port 1
P2DIR = 0xFF; // all pins in port 2 as output
P2OUT = 0; // assign zero (low) to all pins in port 2

//Configure Timer
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 3277; //0.1s intervals between ISRs
TACTL = TASSEL_1 + MC_1; // Timer clock source ACLK, (MC_1 is up-mode)


while(1)
{
_bis_SR_register(LPM3_bits + GIE); // Enter LPM3 with interrupts
}

}

void FaultRoutine(void)
{
P1OUT = 0x01; // red LED on
while(1); // TRAP
}

//Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
#else
#error Compiler not supported!
#endif
{
// FSR is powered up using Vcc
ADC10CTL1 = INCH_0+ADC10DIV_0+ + ADC10SSEL_1; // Channel A0, ADC10CLK/1, ACLK as ADC clock
ADC10CTL0 = SREF_0 + ADC10SHT_0 +REFON+ ADC10ON + ADC10IE; // Vcc & Vss as reference, Sample and hold for 4 Clock cycles, ADC on
_delay_cycles(5);
ADC10CTL0 |= ENC + ADC10SC;
__delay_cycles(13);
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
ADC10CTL0 &= ~ENC;
ADC10CTL0 &= ~(REFON+ADC10ON);
ADC_value = ADC10MEM;
CCR0 +=3277;
}

  • 1--- I don't know about FSR (force sensitive resistors).
    Could the INPUT IMPEDANCE of the 2553 ADC mux be interfering? (datasheet SLAS735J page 37 be interfering?
    In other words, do you get the desired voltage at the voltage divider whrn measured only with a DVM?

    2--- You are using ADC channel A0 on a Launchpad?
    Could the RED LED be interfering? If so, remove the jumper.

    Lastly, we would like to know about the FSR. And also, how the voltage divider is connected :
    - (Vcc >> 10K >> FSR >> GND)
    -or-
    - (Vcc >> FSR >> 10K >> GND)

    As you stated, the 2553 ADC A0 is connected to the V divider between FSR and 10K.

    Good luck!!
  • Hi Sevak!

    If the ADC result is fine when not using the interrupt, then maybe your conversion is somehow disturbed by the timing. One thing I see is that you're using up mode for the timer and you add 100ms to CCR0 inside your ADC ISR. This is unusual - in up mode, the timer counts to the given value and then jumps back to 0. Adding a value to the CC register is normally used in continuous mode. You are changing the period in every cycle. By the way - there is no need to re-initialize the ADC for every conversion. This can be done once.

    Dennis
  • Hi there,
    Thanks for your reply. The problem was in the fact that I defined all my pins as output and low. In order to have a successful ADC reading, I just needed to define the ADC channel as input at the beginning of my ISR and then switch it back to output at the end of the ISR. That solved the problem.
    Best wishes,
  • Hi Dennis,
    Thanks for your reply. I modified my code and added your suggestions to it.
    However, the problem I had was due to the fact that I had all my pins defined as output and low in my main function. In order to have a successful ADC reading inside my ISR, I just needed to define the ADC channel as input at the beginning of my ISR and then switch it back to output at the end of the ISR. That solved the problem.
    Best wishes,
  • Glad to hear it works, but the input / output direction and the function selection bits are don't care for the ADC module - the configuration of the ADC overwrites the pin direction:

    So your solution is something else ;)

    Dennis

**Attention** This is a public forum