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.

MSP430F5529: Sample and store negative values in memory

Part Number: MSP430F5529
Other Parts Discussed in Thread: LMP7721

Hello all,

I have made a data acquisition system using MSP430F5529 system which is attached to my sensor. My sensor is producing both positive and negative values. I am able to store positive values but unable to store negative values. Can anyone suggest me how to do it? 

  • Hi Mukul,

    What type of sensor are using that produces both pos and neg values?

    It sounds like integer values are "un-signed" and therefore always positive.  You can declare your variables "signed" and the compiler will handle the rest for you.

    Example:  int16_t var1;

  • Hello Dennis,

    I am using the electrochemical sensor. It generates oxidation and reduction current where the oxidation current is positive and reduction current is negative. The current is converted to a voltage by a trans-impedance amplifier.  I need to sample this voltage which is both positive and negative.

    I have already assigned the variable to be signed integer. I want to know what change I need to give in my code.  I am writing my code below.



    #include <msp430.h>


    unsigned int i, b;

    signed int Adc_Data = 0 ;

    void main() {

    WDTCTL= WDTPW | WDTHOLD; // Stop watchdog timer

    ///////////////////////// Configurating REF Module ////////////////////

    REFCTL0 = 0x0000; // Disable REFMSTR

    //////////////////////// Port Configuration for COunter IC ////////////////
    P3DIR = 0x01; // port p3.0 provide Clock signal to synchronous counter
    P3OUT = 0x00; // initialise clock with zero
    P4DIR = 0x02; // port 4.1 acts as enable for counter IC
    P4OUT = 0x02; // Reset state for counter S0/S1.


    //////////////////////// Configuring UART ////////////////////////////////
    P4SEL |= BIT4+BIT5;
    UCA1CTL1 |= UCSWRST; // **Put state machine in reset**
    UCA1CTL1 |= UCSSEL_2; // SMCLK
    UCA1BR0 = 9; // 1MHz 115200 1/.1152 =9
    UCA1BR1 = 0; // 1MHz 115200
    UCA1MCTL |= UCBRS_1 + UCBRF_0; // Modulation UCBRSx=1, UCBRFx=0
    UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
    UCA1IE |= UCRXIE;
    UCA1IFG &= ~UCRXIFG; // Reset receive IFG flag

    ////////////////////// Configuring ADC //////////////////////////////////
    P6SEL |= 0x01;                                                                                                                                                             // P6.0 ADC option select
    ADC12CTL0 = ADC12SHT0_3 + ADC12ON + ADC12REFON ;                                                                                 // Sampling time, ADC12ON,
    ADC12CTL1 = ADC12SHP + ADC12SSEL_0 + ADC12CONSEQ_0 + ADC12DIV_0 + ADC12CSTARTADD_0;     // Use sampling timer for pulse mode + ADCCLK=SMCLK
    ADC12CTL2 = ADC12RES_2  + ADC12DF;                                                                                                               // Resolution = 12BIT
    ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_0;                                                                                                   // VR+ = 1.5V & VR- = 0V
    for ( i=0; i<0x50; i++);                                                                                                                                                  // Delay for reference start-up
    ADC12IE = 0x0001;
    ADC12IFG = 0x0000;
    Adc_Data = 0;

    while(1)
    {
    __bis_SR_register(LPM0_bits + GIE);                                                                                                                         // Enter LPM0, interrupts enabled
    __no_operation();
    }
    }


    //////////////////////// ISR- UART ////////////////////////////////
    #pragma vector=USCI_A1_VECTOR
    __interrupt void USCI_A1_ISR(void)
    {
    UCA1IFG &= ~UCRXIFG;
    b=0;
    P3OUT = 0;
    P4OUT = 0x00; // if P4.1 is 1, then S0/S1 is high and counter starts up counting.
    TA0CCTL0 = CCIE;
    TA0CTL = TASSEL_2 + ID_0 + TACLR + MC_1;
    TA0CCR0 = 21000;
    __bic_SR_register_on_exit(LPM0_bits);
    }

    //////////////////////// ISR- TIMER_A0 ////////////////////////////////
    #pragma vector = TIMER0_A0_VECTOR                                             // Timer0 A0 interrupt service routine
    __interrupt void TIMER0_A0_ISR(void)
    {
    ADC12CTL0 |= ADC12ENC + ADC12SC;                                             // Start sampling/conversion
    ADC12CTL0 = 0xFFFE;
    __delay_cycles(50);
    P3OUT ^= 1;
    b += 1;
    if(b > 511)
    {
    TA0CTL =0;
    P4OUT = 0x02;                                                                                    // asynchronous clear
    P3OUT=0;
    }

    }


    //////////////////////// ISR- ADC ////////////////////////////////
    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(void)

    {

    switch(__even_in_range(ADC12IV,34))
    {
    case 0: break; // Vector 0: No interrupt
    case 2: break; // Vector 2: ADC overflow
    case 4: break; // Vector 4: ADC timing overflow
    case 6: // Vector 6: ADC12IFG0

    Adc_Data = ADC12MEM0;
    ADC12IFG &= ~ADC12IFG0;
    while (!(UCA1IFG & UCTXIFG));
    UCA1TXBUF = (Adc_Data& 0x00FF); // sending Least Significant BYTES 1st

    while (!(UCA1IFG & UCTXIFG));
    UCA1TXBUF = ((Adc_Data & 0xFF00)>>8); // sending Most Significant BYTES

    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    break;
    case 8: break; // Vector 8: ADC12IFG1
    case 10: break; // Vector 10: ADC12IFG2
    case 12: break; // Vector 12: ADC12IFG3
    case 14: break; // Vector 14: ADC12IFG4
    case 16: break; // Vector 16: ADC12IFG5
    case 18: break; // Vector 18: ADC12IFG6
    case 20: break; // Vector 20: ADC12IFG7
    case 22: break; // Vector 22: ADC12IFG8
    case 24: break; // Vector 24: ADC12IFG9
    case 26: break; // Vector 26: ADC12IFG10
    case 28: break; // Vector 28: ADC12IFG11
    case 30: break; // Vector 30: ADC12IFG12
    case 32: break; // Vector 32: ADC12IFG13
    case 34: break; // Vector 34: ADC12IFG14
    default: break;
    }

    }

    Please tell me where I am going wrong.

    Thanks

    Mukul

  • Hi Mukul,

    Before we start digging through your code in detail, how is your amplifier biased?  What I mean is can its output go above and below ground potential?

    Reason I ask is the MSP430 ADC inputs are limited from VSS (ground) to +VREF, which in your case is 1.5. If you attempt to drive the ADC input below ground the measurement won't be accurate.

    If this is the case, can you apply an offset voltage to your ampilifer so it's common mode output is sitting at +VEF/2 or about 0.75v?  This way zero current will produce an output voltage of 0.75v, a "negative" current will produce a voltage on the amplifier output between 0.75 and 0v and a "positive" current will produce voltage output between 0.75 and +VREF (depending on the gain of the amplifer of course).

  • Dear Dennis,

    I am using IC LMP7721 which is an opamp. It is used in trans-impedance mode. It can take any positive and negative values within the saturation limit. I came to know that MSP430f5529 ADC cant take values below zero as you said.

    However, I gave an appropriate dc offset value and my work is done as you mentioned. Thankyou very much. 

    Mukul 

**Attention** This is a public forum