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.

Internal Temperature sensor of LM4F232

Hi,

Consider this code snippet from Stellarisware/Examples/ADC/temperature_sensor.c:

ulTemp_ValueC = ((1475 * 1023) - (2250 * ulADC0_Value[0])) / 10230;

The value of ulADC0_VAlue[0] is 1750 (otained through UART printing); When we calculate the ulTemp_Value using this 1750,  manually, we get the value -237 Celsius. But the UART printed value of ulTemp_ValueC is 419604 Celsius.

Now consider the execution of the following snippet:

ulTemp_ValueC = ((1475 * 1023) - (2250 *1750)) / 10230;

Now the Expected value is -237, and it is printed.

In either case, I havent got the actual temperature, which must be around 30 Celsius.

  • Hi Karthi,

        I copied and pasted that code snippet to the hello project of my EK-LM3S6965, and works just fine. Printed out this below at Tera Term. That's the internal temperature of the chip. Expect the temp to be higher than 30 Celsius.

        "Temperature = 43*C or 109*F"

    -kel

  • Hi Mikel,

         The code I used is: (from stellarisware/examples/peripherals/adc/temperature_sensor.c)

    //*****************************************************************************
    //
    // temperature_sensor.c - Example demonstrating the internal ADC temperature
    // sensor.
    //
    // Copyright (c) 2010-2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 9453 of the Stellaris Firmware Development Package.
    //
    //*****************************************************************************
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/sysctl.h"
    #include "utils/uartstdio.h"
    //*****************************************************************************
    //
    //! \addtogroup adc_examples_list
    //! <h1>ADC Temperature Sensor (temperature_sensor)</h1>
    //!
    //! This example shows how to setup ADC0 to read the internal temperature
    //! sensor.
    //!
    //! NOTE: The internal temperature sensor is not calibrated.  This example
    //! just takes the raw temperature sensor sample and converts it using the
    //! equation found in the LM3S9B96 datasheet.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioInit(0);
    }
    //*****************************************************************************
    //
    // Configure ADC0 for the temperature sensor input with a single sample.  Once
    // the sample is done, an interrupt flag will be set, and the data will be
    // read then displayed on the console via UART0.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // This array is used for storing the data read from the ADC FIFO. It
        // must be as large as the FIFO for the sequencer in use.  This example
        // uses sequence 3 which has a FIFO depth of 1.  If another sequence
        // was used with a deeper FIFO, then the array size must be changed.
        //
        unsigned long ulADC0_Value[1];
        //
        // These variables are used to store the temperature conversions for
        // Celsius and Fahrenheit.
        //
        unsigned long ulTemp_ValueC;
        unsigned long ulTemp_ValueF;
        //
        // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
        SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
        //
        // Set up the serial console to use for displaying messages.  This is just
        // for this example program and is not needed for ADC operation.
        //
        InitConsole();
        //
        // Display the setup on the console.
        //
        UARTprintf("ADC ->\n");
        UARTprintf("  Type: Internal Temperature Sensor\n");
        UARTprintf("  Samples: One\n");
        UARTprintf("  Update Rate: 250ms\n");
        UARTprintf("  Input Pin: Internal temperature sensor\n\n");
        //
        // The ADC0 peripheral must be enabled for use.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        //
        // Enable sample sequence 3 with a processor signal trigger.  Sequence 3
        // will do a single sample when the processor sends a singal to start the
        // conversion.  Each ADC module has 4 programmable sequences, sequence 0
        // to sequence 3.  This example is arbitrarily using sequence 3.
        //
        ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
        //
        // Configure step 0 on sequence 3.  Sample the temperature sensor
        // (ADC_CTL_TS) and configure the interrupt flag (ADC_CTL_IE) to be set
        // when the sample is done.  Tell the ADC logic that this is the last
        // conversion on sequence 3 (ADC_CTL_END).  Sequence 3 has only one
        // programmable step.  Sequence 1 and 2 have 4 steps, and sequence 0 has
        // 8 programmable steps.  Since we are only doing a single conversion using
        // sequence 3 we will only configure step 0.  For more information on the
        // ADC sequences and steps, reference the datasheet.
        //
        ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE |
                                 ADC_CTL_END);
        //
        // Since sample sequence 3 is now configured, it must be enabled.
        //
        ADCSequenceEnable(ADC0_BASE, 3);
        //
        // Clear the interrupt status flag.  This is done to make sure the
        // interrupt flag is cleared before we sample.
        //
        ADCIntClear(ADC0_BASE, 3);
        //
        // Sample the temperature sensor forever.  Display the value on the
        // console.
        //
        while(1)
        {
            //
            // Trigger the ADC conversion.
            //
            ADCProcessorTrigger(ADC0_BASE, 3);
            //
            // Wait for conversion to be completed.
            //
            while(!ADCIntStatus(ADC0_BASE, 3, false))
            {
            }
            //
            // Clear the ADC interrupt flag.
            //
            ADCIntClear(ADC0_BASE, 3);
            //
            // Read ADC Value.
            //
            ADCSequenceDataGet(ADC0_BASE, 3, ulADC0_Value);
            //
            // Use non-calibrated conversion provided in the data sheet.  Make
            // sure you divide last to avoid dropout.
            //
            ulTemp_ValueC = ((1475 * 1023) - (2250 * ulADC0_Value[0])) / 10230;
            //
            // Get fahrenheit value.  Make sure you divide last to avoid dropout.
            //
            ulTemp_ValueF = ((ulTemp_ValueC * 9) + 160) / 5;
            //
            // Display the temperature value on the console.
            //
            UARTprintf("Temperature = %3d*C or %3d*F\r", ulTemp_ValueC,
                       ulTemp_ValueF);
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 250ms arbitrarily.
            //
            SysCtlDelay(SysCtlClockGet() / 12);
        }
    }

    I ran this code on LM4F232 kit and got the value  Temperature = 419602*C or 755322*F.

    Where could be the mistake?

  • Hi,

       I used the same code. The only difference is my uc is Fury Class, and I commented out the GPIOPinConfigure(). I am out of ideas, why you are getting those values. If I would guess, try lowering the optimization of your compiler to -O0, and see if you still get the same values..

    -kel

  • Your problem is the 1023 value & old equation - that is for older/past M3 which had 10 bit A to D.

    Newer LX4F and rebrand have graduated to 12 bits (4095/6). 

    From w/in my LX4F MCU manual - ADC Section: " Temperature = 147.5 - ((225 × ADC) / 4095)"

    Running these numbers (w/your 1750 value) yields Temp = 147.5 - 96.2 = 51.3° C   (should be good for G'ovt Work...)

    Caution: for you/others - many code examples were developed for MCUs current - at that time!  May not be fully appropriate when copied and used - w/out proper "adapting" into agreement w/ latest/greatest MCUs.

    Your failed UART print value appears to be another matter - and is outside of the subject/title of this posting.  (make a 2nd thread (new posting) for that - if that UART print value continues to defy logic.)  Forum owner advises against multiple subjects w/in one thread - this confounds future "searches/answers..."

    Perhaps you'll "consider" Green Verify Answer - always gratefully accepted - merci...

  • Hi cb1,

         The LM4F232H5QD datasheet says the formula as: TEMP = 147.5 - ((75 * (VREFP - VREFN) × ADCCODE) / 4096); 

        How did you quote the formula as TEMP = 147.5 - ((225 * (VREFP - VREFN) × ADCCODE) / 4096) in your reply??

    Thanks!

  • Thank you - appreciated.  Glad that my writing encouraged you to check your MCU datasheet.

    As stated (my answering post) formula I presented was direct extract from our LX4F - 64 pin MCU.  This smaller pin-count device (at least ours) does not include the VREFP nor VREFN pins - likely explaining formula's difference.  In fact - replacing those VREFs w/ 3.0 (3.0V - 0V) yields 75 * 3 = 225.  Q.E.D.  (perhaps warrants 2nd green)

    You were sufficiently resourceful to find and employ that code example.  Recall that LM3S was vendor's sole issue for ~first five years - thus many examples so targeted.  Newer LX4F (and rebrand) overlap many - but not all - capabilities & functions - thus you must be "on guard" for critical differences when importing code not specifically targeting your MCU...

  • Hello.

    Im sitting here on a similar problem. I try to use the example temperature_sensor.c to get the temperutre from the bord and to send it via usb to the computer. can someone help me to integrate the c-code in (for example) the example usb_dev_serial.uproj

    Im using the EKK LM4F232.

    would be great.