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.

MSP432P401R: DriverLib example: Measuring internal temperature

Part Number: MSP432P401R

I am using the DriverLib ADC14 example that measures the internal temperature of the chip I am using the new red Launchpad:

/*******************************************************************************
 * MSP432 ADC14 - Single Channel Repeat Temperature Sensor
 *
 * Description: This example shows the use of the internal temperature sensor.
 * A simple continuous ADC sample/conversion is set up with a software trigger.
 * The sample time is set to TBD as speced by the User's Guide. All calculations
 * take place in the ISR which take advantage of the Stacking Mode of the FPU.
 * The temperature is calculated in both Celsius and Fahrenheit.
 *
 *                MSP432P401
 *             ------------------
 *         /|\|                  |
 *          | |                  |
 *          --|RST         P5.5  |
 *            |                  |
 *            |                  |
 *            |                  |
 *
 * Author: Timothy Logan
 ******************************************************************************/
/* DriverLib Includes */
#include "driverlib.h"

/* Standard Includes */
#include <stdint.h>

#include <string.h>

volatile float tempC;
volatile float tempF;

int main(void)
{
    /* Halting WDT  */
    WDT_A_holdTimer();
    Interrupt_enableSleepOnIsrExit();

    /* Enabling the FPU with stacking enabled (for use within ISR) */
    FPU_enableModule();
    FPU_enableLazyStacking();

    /* Initializing ADC (MCLK/1/1) with temperature sensor routed */
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,
            ADC_TEMPSENSEMAP);

    /* Configuring ADC Memory (ADC_MEM0 A22 (Temperature Sensor) in repeat
     * mode).
     */
    ADC14_configureSingleSampleMode(ADC_MEM0, true);
    ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
            ADC_INPUT_A22, false);

    /* Configuring the sample/hold time for TBD */
    ADC14_setSampleHoldTime(ADC_PULSE_WIDTH_192,ADC_PULSE_WIDTH_192);

    /* Enabling sample timer in auto iteration mode and interrupts*/
    ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
    ADC14_enableInterrupt(ADC_INT0);

    /* Setting reference voltage to 2.5 and enabling temperature sensor */
    REF_A_setReferenceVoltage(REF_A_VREF2_5V);
    REF_A_enableReferenceVoltage();
    REF_A_enableTempSensor();

    /* Enabling Interrupts */
    Interrupt_enableInterrupt(INT_ADC14);
    Interrupt_enableMaster();

    /* Triggering the start of the sample */
    ADC14_enableConversion();
    ADC14_toggleConversionTrigger();

    /* Going to sleep */
    while (1)
    {
        PCM_gotoLPM0();
    }
}

/* This interrupt happens every time a conversion has completed. Since the FPU
 * is enabled in stacking mode, we are able to use the FPU safely to perform
 * efficient floating point arithmetic.*/
void ADC14_IRQHandler(void)
{
    uint64_t status;
    uint32_t cal30, cal85;

    status = ADC14_getEnabledInterruptStatus();
    ADC14_clearInterruptFlag(status);

    if(status & ADC_INT0)
    {
        cal30 = SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF,
                SYSCTL_30_DEGREES_C);
        cal85 = SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF,
                SYSCTL_85_DEGREES_C);

        tempC = (float) (((uint32_t) ADC14_getResult(ADC_MEM0) - cal30) * (85 - 30))
                / (cal85 - cal30) + 30.0f;
        tempF = tempC * 9.0f / 5.0f + 32.0f;
    }

}

When I run it, cal30 = 4702, cal85 = 5401 and my ADC reads about 3500.

Firstly:

In case someone measures temp below 30 C, I think you should make all the int variables signed. I got really confused when I measured a huge temperature. 8^)

However, even after I fixed that, I still measured about -60C, which is obviously not correct. What am I doing wrong?

  • Keith,

    There was an issue with this code discovered recently and a fix has been implemented which will come out soon to TI-Rex (TI Resource Explorer).  Please try the following code and let me know if you continue to see issues.


    /* * ------------------------------------------- * MSP432 DriverLib - v4_00_00_11 * ------------------------------------------- * * --COPYRIGHT--,BSD,BSD * Copyright (c) 2017, 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. * --/COPYRIGHT--*/ /******************************************************************************* * MSP432 ADC14 - Single Channel Repeat Temperature Sensor * * Description: This example shows the use of the internal temperature sensor. * A simple continuous ADC sample/conversion is set up with a software trigger. * The sample time is set to TBD as speced by the User's Guide. All calculations * take place in the ISR which take advantage of the Stacking Mode of the FPU. * The temperature is calculated in both Celsius and Fahrenheit. * * MSP432P401 * ------------------ * /|\| | * | | | * --|RST P5.5 | * | | * | | * | | * * Author: Timothy Logan ******************************************************************************/ /* DriverLib Includes */ #include <ti/devices/msp432p4xx/driverlib/driverlib.h> /* Standard Includes */ #include <stdint.h> #include <string.h> volatile uint32_t cal30; volatile uint32_t cal85; volatile float calDifference; volatile float tempC; volatile float tempF; int main(void) { /* Halting WDT */ WDT_A_holdTimer(); Interrupt_enableSleepOnIsrExit(); /* Enabling the FPU with stacking enabled (for use within ISR) */ FPU_enableModule(); FPU_enableLazyStacking(); /* Initializing ADC (MCLK/1/1) with temperature sensor routed */ ADC14_enableModule(); ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, ADC_TEMPSENSEMAP); /* Configuring ADC Memory (ADC_MEM0 A22 (Temperature Sensor) in repeat * mode). */ ADC14_configureSingleSampleMode(ADC_MEM0, true); ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A22, false); /* Configuring the sample/hold time for 192 */ ADC14_setSampleHoldTime(ADC_PULSE_WIDTH_192,ADC_PULSE_WIDTH_192); /* Enabling sample timer in auto iteration mode and interrupts*/ ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION); ADC14_enableInterrupt(ADC_INT0); /* Setting reference voltage to 2.5 and enabling temperature sensor */ REF_A_enableTempSensor(); REF_A_setReferenceVoltage(REF_A_VREF2_5V); REF_A_enableReferenceVoltage(); cal30 = SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_30_DEGREES_C); cal85 = SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_85_DEGREES_C); calDifference = cal85 - cal30; /* Enabling Interrupts */ Interrupt_enableInterrupt(INT_ADC14); Interrupt_enableMaster(); /* Triggering the start of the sample */ ADC14_enableConversion(); ADC14_toggleConversionTrigger(); /* Going to sleep */ while (1) { PCM_gotoLPM0(); } } /* This interrupt happens every time a conversion has completed. Since the FPU * is enabled in stacking mode, we are able to use the FPU safely to perform * efficient floating point arithmetic.*/ void ADC14_IRQHandler(void) { uint64_t status; int16_t conRes; status = ADC14_getEnabledInterruptStatus(); ADC14_clearInterruptFlag(status); if(status & ADC_INT0) { conRes = ((ADC14_getResult(ADC_MEM0) - cal30) * 55); tempC = (conRes / calDifference) + 30.0f; tempF = tempC * 9.0f / 5.0f + 32.0f; } }

  • I will try, but I still see problems.

    Since cal30 and the ADC14 result are unsigned the result of this:
    conRes = ((ADC14_getResult(ADC_MEM0) - cal30) * 55);

    will still be a large number if the ADC result is less than cal30, like my case.

    As far as I can tell, the only change is to change the order of REF_A_enableTempSensor() and move getting cal30 and cal85 out of the ISR. If I still get the same values, I still have the same issues, will I get different values with the new code?

    What values do you get for cal30, cal85 and the ADC reading?
  • Keith,

    I am seeing results of 21.5 for TempC and 70.7 for TempF, which seems about accurate in my current environment (room temperature about 70 F ).

    With the previous version (downloaded directly from TI-Rex), I was getting wildly erroneous values such as 6429519.5 for TempC and 11573167.0 for TempF.

    Are we seeing the same issues or separate?

    This is the code you are referring to, yes? Link to Code.

  • Yes, that is the code.

    The huge numbers are the results of using unsigned ints for the subtraction. I guess you fixed the issue by multiplying by the (signed int) 55 causing the result to be signed and coming out OK when converted to float. You are still depending on the C standard too much, IMHO. I think that any time you might be working with negative numbers you should use signed ints, that is what they are there for!

    Assuming your cal85 and cal30 numbers are close to mine, you must be getting about 4594 for the ADC14 reading which makes sense. I got about 3500, or 1000 counts lower, which comes out to about -64C

  • Thank you for your suggestion concerning the unsigned vs signed int.

    Are you testing at room temp as well? You're right that your ADC14 reading is much lower than my own.

    Can you look at the device and tell if it says MSP432P401R or XMS432P401R?  I am trying to think of reasons why you might be getting these lower values.

  • The chip is marked: 69ALKGW64 MSP432P401R Rev C

    And I am at room temperature.

  • I used your code above and it worked. I don't really see a difference, so now it is going to bug me until I hunt it down. 8^)
  • It looks like the most significant change here is the line: ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A22, false); where INTBUF was changed from AVCCC for the VREFPOS.

    I ran the older version, then changed only that one line (AVCC becomes INTBUF) and saw the difference you were talking about where the ADC14MEM0 register shows ~3600 and then jumps to ~4500 after making the change.

    It also looks like the fetch instructions to get cal30 and cal85 values and some of the math that only needs to be done one time is removed from the ISR; which is a good practice to lighten the load inside ISRs.

    Hopefully this helps.
  • Thanks for doing my work for me! Now I can sleep tonight.

**Attention** This is a public forum