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.

ADC12 reading messed up in high temperature ?

Other Parts Discussed in Thread: MSP430F5335

We are using ADC12_A modele of MSP430F5335 to measure Temperature sensor inside MSP430

and the voltage of backup battery.

It works fine most of the time, can measure temperature accurately  from 20C Degree all the way up to 95C degree.

See my previous post:

http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/281286/982162.aspx#982162

The calibration value from TLV is  0x4FA at 30 Degree and 0x5D7 at 85 Degree.

In a normal condition, if ADC12 returns 0x6FE as temperature sensor reading

it gives the MSP430 temperature as 94 degree, pretty close to what measured with a handheld instruments.

But many times we found that if we power down MSP430 at high temperature,

lets say 85 or 90 degree, and power on again,

the read value from ADC12 are leading to impossible high temperature and voltage readings.

For example, ADC12 returns 0xFE5, and gives temperature result is 755 C Degree.

The same thing happens to ADC channel that measures battery value:

normally it returns 0x5F6, battery voltage is 3.2, when the messed up happens

ADC12 returns 0xFF4 and voltage becomes 7.4.

 

If we power off the device and let the test environment cools downs (cools down MSP430F5335)

and restart power, all ADC value returns normal.

The messed up only happens if we restart the MSP430 at high temperature, if MSP430 stays in temperature,

then ADC reading remains valid and reasonable.

 

  • qinghui tang said:

    The same thing happens to ADC channel that measures battery value:

    normally it returns 0x5F6, battery voltage is 3.2, when the messed up happens

    ADC12 returns 0xFF4 and voltage becomes 7.4.

    Does it really "hangs" and give such values over many reads, like during couple of seconds?

    I ask because perhaps you don't let reference or (for god's sake VCC) to settle and take ADC measurement just too soon after power-up? What kind of clock do you use for ADC? Please show ADC setup

  • It keeps give such readings.

    I believe our code considered the settle time for ADC.

  • qinghui tang said:

    It keeps give such readings.

    I believe our code considered the settle time for ADC.

    Then I am out of ideas. Especially if you refuse to show microcontroller and ADC init

  • Please refer to the following code

    void adc_temp_init(void)
    {
        /* Initialize the shared reference module */
        REFCTL0 &= ~REFVSEL_3;
    #ifdef ADC_REF_VOLTAGE_2_0_V
        REFCTL0 |= REFVSEL_1;                               // Configure internal 2.0V reference
    #endif
    #ifdef ADC_REF_VOLTAGE_2_5_V
        REFCTL0 |= REFVSEL_2;                               // Configure internal 2.5V reference
    #endif
    
        ADC12CTL2 = 0x0020;
    
        
        ADC12CTL0 &= ~ADC12ENC;                             // Ensure ENC is clear
        // 5.4MHz (MODOSC_max) * 100 us (t_sensor)= 540 cycles min sampling time
        ADC12CTL0 = ADC12SHT0_11 + ADC12ON + ADC12MSC;       // Set sample time to 540 cycles
        
        //enable to measure battery voltage
        BAKCTL |= BAKADC;
        BAKCHCTL =  CHPWD + CHV0 + CHC0 + CHC1 + CHEN  ;//charge with VCC, resistor = 20K, DONOT use |=
        
        //external ref ADC voltage
        P5SEL |= BIT1 + BIT0;
        P5DIR &= ~(BIT1 + BIT0);  // PORT 5 in perihperal mode and input
       
        ADC12CTL1 = ADC12CONSEQ_1 + ADC12SHP;               // Enable sequence-of-channels & sample
                                                            // timer
        ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_10;            // ADC input ch A10 => temp sense
        ADC12MCTL1 = ADC12SREF_1 + ADC12INCH_11;            // ADC input ch A11 => Vcc
    
        ADC12MCTL2 = ADC12SREF_1 + ADC12INCH_3;             // ADC input ch A3 is outside temperature sensor
        ADC12MCTL3 = ADC12SREF_1 + ADC12INCH_12 + ADC12EOS; // backup batteray voltage, use system 3.3v as reference voltage
        ADC12IE = 0x00;                                     // Ensure all interrupts are disabled
    
        //enable to measure battery voltage
        
    }
    
    // get_cpu_temp_voltage get called from a non-interrupt type timer routine
    
    void get_cpu_temp_voltage(uint16_t * temperature, uint16_t * voltage, uint16_t * OutTempInC, uint16_t * backupBattVoltage)
    {
        unsigned long temp_temp = 0;
        unsigned long temp_vcc = 0;
        unsigned long outside_temp = 0;
        unsigned long backup_batt_temp = 0;
        float m = 0, c = 0;
        int CAL_ADC_T30, CAL_ADC_T85 ;
    
        volatile unsigned long IntDegC, IntDegF;
        volatile unsigned long batt_voltage;
    
        volatile float OutsideMeasuredVoltage;
        volatile float OutsideTempC;
        //uint16_t final_backup_voltage;
        REFCTL0 |= REFON;                               // Enable internal reference
        __delay_cycles(1600);                           // Settling time for reference  20MHz * 75us = 1500 cycles
        ADC12CTL0 |= ADC12ENC + ADC12SC;                // (Re)enable & trigger conversion
    
        // Poll IFG until all four memory loaded signifying sequence is complete
        while (!((ADC12IFG & 0xF) == 0xF)) ;
        
        ADC12CTL0 &= ~ADC12ENC;                         // Disable conversions to configure REF
        REFCTL0 &= ~REFON;                              // Disable internal reference
        temp_temp = ADC12MEM0;
        backup_batt_temp = ADC12MEM3;
        
    #ifdef ADC_REF_VOLTAGE_2_0_V
        CAL_ADC_T30 = (*(int *)0x01A1E);                      //ADC temp calibration consts for 2.0V
                                                              // ref
        CAL_ADC_T85  = (*(int *)0x01A20);
    #endif
    
    #ifdef ADC_REF_VOLTAGE_2_5_V    
        CAL_ADC_T30 = (*(int *)0x01A22);                      //ADC temp calibration consts for 2.5V
                                                              // ref
        CAL_ADC_T85 = (*(int *)0x01A24);
    #endif    
        m = (85 - 30) / (float)(CAL_ADC_T85  - CAL_ADC_T30); //calculate the slope
        c = 85 - m * CAL_ADC_T85 ;
    
    
        IntDegC = (unsigned long) (temp_temp * m + c);
    
        *temperature = IntDegC;
    
       
        //measure battery voltage of backup, VBAT3 is only 1/3 of VBAT
        // 10 * Batt voltage = 2.5V(A12/4096) * 10 * 3= 75(A11)/4096
        
        batt_voltage = ((backup_batt_temp &0xffff)* 75) >> 12;
        *backupBattVoltage = batt_voltage;
        //Display((" back up battery voltage = %d\r\n", final_backup_voltage));
    
         
    }
    

  • Here are some log

    2014-02-20 16:32:13.954 [INFO] Notify data = <2f000800 5d000a07 2000ef05>
    2014-02-20 16:32:13.955 [DEBUG] Board Battery = 3.200000, CPU Temp = 93 <-- Temperature reach 93, ready to power off MSP430
    2014-02-20 16:32:13.956 [DEBUG] Value1 = 070A, Value2 = 05EF

    2014-02-20 16:35:08.467 [INFO] Notify data = <2f000800 f302e40f 4a00f30f>
    2014-02-20 16:35:08.468 [DEBUG] Board Battery = 7.400000, CPU Temp = 755 <-- Restarted MSP430, got incorrect reading
    2014-02-20 16:35:08.469 [DEBUG] Value1 = 0FE4, Value2 = 0FF3

    2014-02-20 16:35:44.137 [INFO] Notify data = <2f000800 f302e50f 4a00f40f> <-- start cool down MSP430 with a fan
    2014-02-20 16:35:44.138 [DEBUG] Board Battery = 7.400000, CPU Temp = 755
    2014-02-20 16:35:44.139 [DEBUG] Value1 = 0FE5, Value2 = 0FF4

    2014-02-20 16:36:28.237 [INFO] Notify data = <2f000800 f302e40f 4a00f30f>
    2014-02-20 16:36:28.239 [DEBUG] Board Battery = 7.400000, CPU Temp = 755
    2014-02-20 16:36:28.240 [DEBUG] Value1 = 0FE4, Value2 = 0FF3

    2014-02-20 16:37:12.338 [INFO] Notify data = <2f000800 f302e40f 4a00f60f>
    2014-02-20 16:37:12.339 [DEBUG] Board Battery = 7.400000, CPU Temp = 755
    2014-02-20 16:37:12.341 [DEBUG] Value1 = 0FE4, Value2 = 0FF6

    2014-02-20 16:37:54.856 [INFO] Notify data = <2f000800 f302e40f 4a00f60f>
    2014-02-20 16:37:54.858 [DEBUG] Board Battery = 7.400000, CPU Temp = 755
    2014-02-20 16:37:54.859 [DEBUG] Value1 = 0FE4, Value2 = 0FF6

    2014-02-20 16:38:38.957 [INFO] Notify data = <2f000800 f302e40f 4a00f50f>
    2014-02-20 16:38:38.958 [DEBUG] Board Battery = 7.400000, CPU Temp = 755
    2014-02-20 16:38:38.960 [DEBUG] Value1 = 0FE4, Value2 = 0FF5

    2014-02-20 16:39:23.058 [INFO] Notify data = <2f000800 67000707 20001706> <-- recover to normal
    2014-02-20 16:39:23.059 [DEBUG] Board Battery = 3.200000, CPU Temp = 103
    2014-02-20 16:39:23.060 [DEBUG] Value1 = 0707, Value2 = 0617

    2014-02-20 16:40:07.158 [INFO] Notify data = <2f000800 5d000807 2000f105> <-- return to correct readings
    2014-02-20 16:40:07.160 [DEBUG] Board Battery = 3.200000, CPU Temp = 93
    2014-02-20 16:40:07.161 [DEBUG] Value1 = 0708, Value2 = 05F1

    2014-02-20 16:40:51.259 [INFO] Notify data = <2f000800 57000a07 2000db05>
    2014-02-20 16:40:51.260 [DEBUG] Board Battery = 3.200000, CPU Temp = 87
    2014-02-20 16:40:51.262 [DEBUG] Value1 = 070A, Value2 = 05DB

    2014-02-20 16:41:35.389 [INFO] Notify data = <2f000800 52000b07 2100c805>
    2014-02-20 16:41:35.391 [DEBUG] Board Battery = 3.300000, CPU Temp = 82
    2014-02-20 16:41:35.392 [DEBUG] Value1 = 070B, Value2 = 05C8


    2014-02-20 16:43:03.590 [INFO] Notify data = <2f000800 4a000e07 2100a905>
    2014-02-20 16:43:03.591 [DEBUG] Board Battery = 3.300000, CPU Temp = 74
    2014-02-20 16:43:03.593 [DEBUG] Value1 = 070E, Value2 = 05A9

    2014-02-20 16:43:47.691 [INFO] Notify data = <2f000800 47000f07 21009d05>
    2014-02-20 16:43:47.692 [DEBUG] Board Battery = 3.300000, CPU Temp = 71
    2014-02-20 16:43:47.693 [DEBUG] Value1 = 070F, Value2 = 059D

  • qinghui tang said:
    We are using ADC12_A modele of MSP430F5335 to measure Temperature sensor inside MSP430 and the voltage of backup battery.

    It works fine most of the time, can measure temperature accurately  from 20C Degree all the way up to 95C degree.

    What is the Optional: Temperature Range of the MSP430F5335 (since some are not specified to operate at 95 C). Not sure that could explain the problem though.

  • Well, the MSP is specified for -40°C to 85°C. You're operating it above the upper temperature limit. While this might work (and seems to, as long as you don't power it down or up at this temperature), this is not guaranteed.

    Maybe the reference module won't start up properly at this temperature. After all, it is a band gap reference and therefore sensitive to overtemperature effects.

    I'm a bit puzzled about your log file. It says 93°C, fine, power down, power up, wrong value, then cool down (from where? Still 93°C?) and after some time of cooling, 93°C is correct again (how could it, if the MSP was cooled down in the meantime?)

  • MSP430 is giving wrong readings (anything between 695degC and 755degC) when it is powered OFF above 75 degC and powered ON again even after tens of seconds. This behavior is not acceptable even after considering the temperature range of -45degC to 85degC. Usually it should work up to 95degC. What is going wrong? Why ADC providing corrupt values?

  • Treys another clock source for your ADC and divide it to a frequency (far) below 5MHz.

  • Hey Leo,

    We tried that but still not helping. We divided the frequency by factor of 4 - from about 5MHz to about 1.25MHz. Any other idea? Thanks for your help!

  • swapnil jain said:
    Any other idea? Thanks for your help!

    Reduce your test code down to absolute minimum needed to test ADC. Better write simple ADC test snippet from scratch.

    Check that after "hot" power-up your ADC clock is running within spec - route it to pin, measure using freq counter or scope.

    Try more than one chip. Yours could be damaged somehow.

    Try measuring some external known voltage source, compare to temperature sensor and VCC divider readings.

    Try using VCC as reference or external reference source.

  • swapnil jain said:
    We tried that but still not helping. We divided the frequency by factor of 4 - from about 5MHz to about 1.25MHz

    But did you try another clock source ACLK, SMCLK or MCLK. The same as you describe occurs when the ADC clock is too high, I can imagine that the (maybe simple) ADC12OSC is not starting properly at high temperature.

  • We did try SMCLK and divided by 4 (using 5MHz recommended in the datasheet), also tested at about 0.625MHz and 2.5MHz clock frequency though. In addition, we tried external reference voltage, VCC (3.3V) and none of these changes helped. Our code is already barebone code, we are not running any realtime system except running the TI bluetooth stack. So don't think we can make ADC code more simpler.

  • It seems to me like Errata. If you can replicate problem on more than one/few chips then you shall contact your supplier and/or TI field application engineer.

  • Yes, we are observing this issue with all MSP430 processors. Able to repeat the problem on multiple chips for sure.

  • “Usually it should work up to 95degC”
    Well, if it is specified for 85C, then you cannot say ‘usually it works on higher temp too’.  ‘Usually’ doesn’t mean ‘guaranteed’.
    However, it indeed should work up to 85C.

    Due to your experiments, it seems to be not a problem of the clock signal, nor a reference problem.
    I could imagine some problem with the analog supply, or an initialization problem with the ADC state machine at this high temperature.

    What happens when you do not power-off the MSP, but rather do a software POR? Or swtich the ADC off and on again. Or start the system but not the ADC at nromal temperature, then heat it up and then start the ADC? Does it still fail if there is no real power cycle?

    It could be interesting to see what direct results the ADC gives, rather than the already calculated voltage/temperature values.
    Sometimes the bit pattern of the raw reading gives an idea of what happens. Especially if accompanied by the expected values (current ambient temperature or input voltage)

  • Hello qinghui,

    I've been looking through this thread, and I think that before we call this a silicon errata, we should test this with as simple of code as possible, and ensure that it occurs within the specified operating temperature of the MSP430. 

    Explicitly speaking, I'd like you to try running one of our code examples written for the MSP430F5335 that was set up for measuring the temperature with the internal sensor, within our specified temperature range. The reason I state this so boldly is because a majority of the values you show in your data (when the setup fails, and even when it is running correctly) are above the +85C threshold. I don't mean to come off too bluntly, but it is important to understand we cannot guarantee the performance of any of our modules outside of the specified operating temperature range for which the part has been qualified

    I have attached the appropriate simplified code example below.

    4454.msp430f66xx_adc_10.c
    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *******************************************************************************
     * 
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //  MSP430F66xx Demo - ADC12, Sample A10 Temp and Convert to oC and oF
    //
    //  Description: A single sample is made on A10 with reference to internal
    //  1.5V Vref. Software sets ADC12SC to start sample and conversion - ADC12SC
    //  automatically cleared at EOC. ADC12 internal oscillator times sample
    //  and conversion. In Mainloop MSP430 waits in LPM4 to save power until
    //  ADC10 conversion complete, ADC12_ISR will force exit from any LPMx in
    //  Mainloop on reti.
    //  ACLK = n/a, MCLK = SMCLK = default DCO ~ 1.045MHz, ADC12CLK = ADC12OSC
    //
    //  Uncalibrated temperature measured from device to devive will vary do to
    //  slope and offset variance from device to device - please see datasheet.
    //
    //  NOTE:1. REFMSTR bit in REFCTL0 regsiter is reset to allow the ADC12_A reference
    //    control regsiters handle the reference setting. Upon resetting the REFMSTR
    //    bit, all the settings in REFCTL are 'dont care' and the legacy ADC12  
    //    control bits (ADC12REFON, ADC12REF2_5, ADC12TCOFF and ADC12REFOUT) control 
    //    the reference system.
    //        2. Use the TLV calibrated temperature to measure temperature 
    //        (the TLV CALIBRATED DATA IS STORED IN THE INFORMATION SEGMENT, SEE DEVICE DATASHEET)
    //
    //                MSP430F6638
    //             -----------------
    //         /|\|              XIN|-
    //          | |                 |
    //          --|RST          XOUT|-
    //            |                 |
    //            |A10              |
    //
    //   F. Chen
    //   Texas Instruments Inc.
    //   Dec. 2012
    //   Built with IAR Embedded Workbench Version: 5.51.1 & Code Composer Studio V5.2.1
    //******************************************************************************
    
    #include <msp430.h>
    
    #define CALADC12_15V_30C  *((unsigned int *)0x1A1A)   // Temperature Sensor Calibration-30 C
                                                          //See device datasheet for TLV table memory mapping
    #define CALADC12_15V_85C  *((unsigned int *)0x1A1C)   // Temperature Sensor Calibration-85 C
    
    unsigned int temp;
    volatile float temperatureDegC;
    volatile float temperatureDegF;
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      REFCTL0 &= ~REFMSTR;                      // Reset REFMSTR to hand over control to 
                                                // ADC12_A ref control registers  
      ADC12CTL0 = ADC12SHT0_8 + ADC12REFON + ADC12ON;
                                                // Internal ref = 1.5V
      ADC12CTL1 = ADC12SHP;                     // enable sample timer
      ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_10;  // ADC i/p ch A10 = temp sense i/p
      ADC12IE = 0x001;                          // ADC_IFG upon conv result-ADCMEMO
      __delay_cycles(100);                      // Allow ~100us (at default UCS settings)
                                                // for REF to settle
      ADC12CTL0 |= ADC12ENC;
    
      while(1)
      {
        ADC12CTL0 &= ~ADC12SC;  
        ADC12CTL0 |= ADC12SC;                   // Sampling and conversion start
    
        __bis_SR_register(LPM4_bits + GIE);     // LPM0 with interrupts enabled
        __no_operation();
    
        // Temperature in Celsius. See the Device Descriptor Table section in the
        // System Resets, Interrupts, and Operating Modes, System Control Module
        // chapter in the device user's guide for background information on the
        // used formula.
        temperatureDegC = (float)(((long)temp - CALADC12_15V_30C) * (85 - 30)) /
                (CALADC12_15V_85C - CALADC12_15V_30C) + 30.0f;
    
        // Temperature in Fahrenheit Tf = (9/5)*Tc + 32
        temperatureDegF = temperatureDegC * 9.0f / 5.0f + 32.0f;
    	 
        __no_operation();                       // SET BREAKPOINT HERE
      }
    }
    
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC12ISR (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
        temp = ADC12MEM0;                       // Move results, IFG is cleared
        __bic_SR_register_on_exit(LPM4_bits);   // Exit active CPU
      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;
      }
    }
    

    If you could please test this piece of code out at/around +85C, and update me with the results, I would appreciate it.

**Attention** This is a public forum