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.

MSP430FR5994: Problem measuring ADC12 BATTMAP

Part Number: MSP430FR5994

I have a problem with a system that is powered by a 3.6V LiSOCl2 lithium cell. These batteries sometimes have the strange behaviour that they have a low capacity although their voltage is above the cutoff level. The system is performing a ratiometric measurement of a resistive sensor against a reference sensor with an external 2-channel ADC. If the battery has the mentioned problem the voltage will fall during the measurement of the two resistors (the 2 ADC channels) which causes a big measurement error. To detect this error I am measuring the battery voltage after the conversion of each channel with the ADC12 BATTMAP input and check if they are nearly equal. But from time to time this values differ significantly although the voltage is stable between the two conversions. Sometimes more than 100 AD steps. I guess it must be a kind of timing problem but I can't find the reason

bool batFlag = false;

void ADC12_init(void)
{
    while (Ref_A_isRefGenBusy(ADC12_B_BASE));
    REFCTL0 |= REFVSEL_1 | REFON; // 2,0 V

    ADC12_B_configureMemoryParam configureMemoryParam = {0};
    configureMemoryParam.memoryBufferControlIndex = ADC12_B_MEMORY_0;
    configureMemoryParam.inputSourceSelect = ADC12_B_INPUT_BATMAP;
    configureMemoryParam.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
    configureMemoryParam.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;
    configureMemoryParam.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
    configureMemoryParam.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;

    ADC12_B_initParam initParam = {0};
    initParam.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;
    initParam.clockSourceSelect = ADC12_B_CLOCKSOURCE_ADC12OSC;                         // = 5 MHz MODOSC / ALT: ADC12_B_CLOCKSOURCE_ACLK _MCLK _SMCLK
    initParam.clockSourceDivider = ADC12_B_CLOCKDIVIDER_5;                              // -> 1 MHz ALT: ADC12_B_CLOCKDIVIDER_1;
    initParam.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
    initParam.internalChannelMap = ADC12_B_BATTMAP;                                     // Interner Kanal: Spannungsteiler Versorgungsspannung (1/2 AVCC

    ADC12_B_init(ADC12_B_BASE, &initParam);
    
    ADC12_B_enable(ADC12_B_BASE);

    ADC12_B_setResolution(ADC12_B_BASE, ADC12_B_RESOLUTION_12BIT); //ADC12_B_RESOLUTION_8BIT);

    ADC12_B_setAdcPowerMode(ADC12_B_BASE, ADC12_B_LOWPOWERMODE);

    ADC12_B_setupSamplingTimer(ADC12_B_BASE,
                               ADC12_B_CYCLEHOLD_512_CYCLES, 
                               ADC12_B_CYCLEHOLD_512_CYCLES,   
                               ADC12_B_MULTIPLESAMPLESDISABLE);

    ADC12_B_configureMemory(ADC12_B_BASE, &configureMemoryParam);

    ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE0, 0, 0);

    while(!(REFCTL0 & REFGENRDY));  
}

void ADC12_measure(void)
{
    ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_MEMORY_0, ADC12_B_SINGLECHANNEL);
}

uint16_t ADC12_getResult(void)
{
  return ADC12_B_getResults(ADC12_B_BASE, ADC12_B_MEMORY_0);
}

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
    switch (__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
    {
    case ADC12IV_ADC12IFG0: 
        batFlag = true;
         __bic_SR_register_on_exit(LPM0_bits | GIE); // Exit CPU, clear interrupts
    break;
    default: break;
    }
}

The main thread will check if the batFlag is true and will call the ADC12_getResult function and go back to LPM0. The measurement will be triggered by the main thread with ADC12_measure() after the conversion of the external ADC. I have already tried to lower the clock speed and to increase sampling times of the ADC with no effect. In the fastest measurement mode the battery voltage will be measured 6 times per second. What could be the problem?

  • Hi Holger,

    But from time to time this values differ significantly although the voltage is stable between the two conversions

    How often does this occur?  Multiple times in a minute, hour, day...etc.?

  • Hard to say. May be once in 50 Measurements. I changed the program that it calculates the mean of the difference of 20 battery measurement pairs and if it is above 10 ADC steps (which already causes an error of slightly more than the allowed 0,2%) it displays an error. The next morning 2 of 3 tested instruments showed that error. Then I changed this threshold to 20 ADC steps and there was no error overnight. Also they are detecting faulty batteries correctly after a while. But I’m not really happy with that “solution”. Is the BATTMAP- signal this noisy?

  • Hi Holger,

    This is a good question.  I'll need to reach out to one of our designers who might be able to shed some light on this.

    Have you tried measuring the BATMAP channel back-back during each sample and compare two consecutive results?

    Also, looking at your code, the conversion is started by software in the ADC12_B_startConversion function, which is fine.  Looking at your ISR, I'm guessing after returning from this function you enter an LPMx and wait for the interrupt to wake the CPU to get the results?   Can you confirm?  What I'm looking for is if it possible to not have the CPU clocking while the BATMAP channel is being measured.

    It might be worth setting up some simple test code that keeps the CPU in LPM3 while a Timer (see table page 84 in datasheet) starts the conversion on some periodic time that matches how often you do it in your code.  Then the only time the CPU wakes is from the ADC EOC interrupt to grab the result.  Let me know if this is something you can try, else I can try on my side.

**Attention** This is a public forum