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.

How to connect a (Temperature) sensor to the MSP430

Other Parts Discussed in Thread: MSP430F2274

Hello,

I found this TI code on internet (I use a MSP430F2274) :

 

//******************************************************************************
//  MSP430F22x4 Demo - ADC10, 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 ADC10SC to start sample and conversion - ADC10SC
//  automatically cleared at EOC. ADC10 internal oscillator/4 times sample
//  (64x) and conversion. In Mainloop MSP430 waits in LPM0 to save power until
//  ADC10 conversion complete, ADC10_ISR will force exit from LPM0 in
//  Mainloop on reti. Temperature in oC stored in IntDegC, oF in IntDegF.
//  Uncalibrated temperature measured from device to device will vary with
//  slope and offset - please see datasheet.
//  ACLK = n/a, MCLK = SMCLK = default DCO ~1.2MHz, ADC10CLK = ADC10OSC/4
//
//                MSP430F22x4
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |A10              |
//
//  A. Dannenberg
//  Texas Instruments Inc.
//  October 2006
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
//******************************************************************************
#include "msp430x22x4.h"

long temp;
volatile long IntDegC;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1MHz
  DCOCTL = CALDCO_1MHZ;
  ADC10CTL1 = INCH_10 + ADC10DIV_3;         // Temp Sensor ADC10CLK/4
  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
  TACCR0 = 30;                              // Delay to allow Ref to settle
  TACCTL0 |= CCIE;                          // Compare-mode interrupt
  TACTL = TASSEL_2 + MC_1;                  // TACLK = SMCLK, Up mode
  __bis_SR_register(CPUOFF + GIE);          // LPM0, TA0_ISR will force exit
  TACCTL0 &= ~CCIE;                         // Disable timer Interrupt

  while(1)
  {
    ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled

    // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
    temp = ADC10MEM;
    IntDegC = ((temp - 673) * 423) / 1024;

    __no_operation();                       // SET BREAKPOINT HERE
  }
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

#pragma vector=TIMERA0_VECTOR
__interrupt void TA0_ISR(void)
{
  TACTL = 0;                                // Clear Timer_A control registers
  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)

}

This code allows us to manage the conversion of the ADC10 but I don't know on which pin of the microcontroller I have to connect my temperature sensor. Because I want to convert the analog tension, that the sensor provide, to a digital tension, to finally determine the temperature. And I really want to know how to change the code to read the tension. please help me... ^^

Thank's for your time,

Matthias

  • Hi Matthias,

    the temperature sensor used in this code example is the internal of the MSP430. You don't need to connect an external in addition.
    In this code the input 10 of the ADC is selected on which the internal temp. sensor is connected.

    Best regards,
    Mario

  • In the F2xx UserGuide (http://focus.ti.com/lit/ug/slau144f/slau144f.pdf) you can find on page 603 some additional information about the internal temp. sensor.

    Regards,
    Mario

  • Thank you for your answers Mario,

    I tried to get the value of the internal sensor but i didn't succeded, my code is the folowing :

    #include  "msp430x22x4.h"
    #include "stdlib.h"
    #include "string.h"
    #include "intrinsics.h"
    #include "PaLFI_Transponder.h"
    #include "DCO_Library.h"

    unsigned int i;
    volatile long temp;
    volatile long IntDegC;
    int result;


    void main(void)
    {
       
        WDTCTL = WDTPW + WDTHOLD;
       
        BCSCTL3 |= (XCAP0 + XCAP1);
       
        Delay_500ms();
           
        P1DIR = 0xFF;
        P1OUT = 0;
        P2OUT = 0;
        P2DIR = 0xFC;
        P2OUT = 0;
        P3SEL |= 0x30;
        P3DIR = 0xFB;
        P3OUT = 0;
        P4DIR = 0xFF;
        P4OUT = 0;
        P1DIR |= 0x03;

        MSP430_SPI_Init();

        while (1)
        {
        ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
        __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled

            // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
            temp = ADC10MEM;
            IntDegC = ((temp - 673) * 423) / 1024;
            IntDegC= (int)IntDegC;
      
            LED_ON (LED_RED); //  make blink the Red Led to show initialization
            Delay_500ms();
            LED_OFF (LED_RED);
           
                                // Allows to know the value of IntDegC with the led
                            while(IntDegC>=100)        // counting the hundreds   (Loop 1)
                            {
                            IntDegC=IntDegC-100;
                            LED_ON (LED_RED);
                            LED_ON (LED_GREEN);
                            Delay_500ms();
                            LED_OFF (LED_RED);
                            LED_OFF (LED_GREEN);
                            Delay_500ms();
                            Delay_500ms();
                            }
                            while(IntDegC>=10)    // counting the tens 
    (Loop 2)
                            {
                            IntDegC=IntDegC-10;
                            LED_ON (LED_RED);
                            Delay_500ms();
                            LED_OFF (LED_RED);
                            Delay_500ms();
                            Delay_500ms();
                            }
                            while(IntDegC>=1)    // counting units 
    (Loop 3)
                            {
                            IntDegC=IntDegC-1;
                            LED_ON (LED_GREEN);
                            Delay_500ms();
                            LED_OFF (LED_GREEN);
                            Delay_500ms();
                            Delay_500ms();
                            }
           
        }   
    }

    void LED_ON (int LED)
    {
        P1OUT |= LED;
    }

    void LED_OFF (int LED)
    {
        P1OUT &= ~LED;
    }

    void Delay_500ms(void)
    {
        TACCTL0 &= ~CCIFG;
        TACCTL0 = CCIE;
        TACTL = TASSEL_1 + MC_1;
        TACCR0 = 16384;
        __bis_SR_register(LPM3_bits + GIE);   
    }

    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A(void)
    {
        __bic_SR_register_on_exit(LPM3_bits + GIE);
    }

    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
      __bic_SR_register_on_exit(CPUOFF);
    }

    So this code doesn't work because the loop 1 is infinite (red and green LED never stop to blink at the same time), so the value of IntDegC might be more than 20000 °C...

    Do you see any mistake ? I think it becomes from the conversion of  IntDegC (long to int) but I don't know how to solve it....

    Thank you for the answers ;)

    Matthias

  • Matthias JUSTON said:
    IntDegC = ((temp - 673) * 423) / 1024;
            IntDegC= (int)IntDegC;

    If you get an ADC reading of less than 673 then your value will wrap around to a very large number - you should consider a slightly different calculation e.g.

    if(val>673)
       perform calculation normally
    else
       set result=0

  • I agree with you, but with this modification the temperature is always at 0°C (and normally it might be about 22°C)

  • Sounds like the ADC sampling is not working as expected.  You haven't listed any of the ADC initialisation code...perhaps you are selecting the wrong ADC channel?

  • You're right for the ADC initialisation that I forgot. So now, It doesn't work very well yet but the microcontroller tells me that the temperature is about 17°C (normally about 24°C).

    My new code :

    #include  "msp430x22x4.h"
    #include "stdlib.h"
    #include "string.h"
    #include "intrinsics.h"
    #include "PaLFI_Transponder.h"
    #include "DCO_Library.h"

    char buf[5] = {0};
    int i;
    volatile long temp;
    volatile long IntDegC;
    int result;


    void main(void)
    {
            WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
            ADC10CTL1 = INCH_10 + ADC10DIV_3;         // Temp Sensor ADC10CLK/4
            ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
            TACCR0 = 30;                              // Delay to allow Ref to settle
            TACCTL0 |= CCIE;                          // Compare-mode interrupt
            TACTL = TASSEL_2 + MC_1;                  // TACLK = SMCLK, Up mode
            __bis_SR_register(CPUOFF + GIE);          // LPM0, TA0_ISR will force exit
            TACCTL0 &= ~CCIE;                         // Disable timer Interrupt
      
        BCSCTL3 |= (XCAP0 + XCAP1);
      
        Delay_500ms();
          
        P1DIR = 0xFF;
        P1OUT = 0;
        P2OUT = 0;
        P2DIR = 0xFC;
        P2OUT = 0;
        P3SEL |= 0x30;
        P3DIR = 0xFB;
        P3OUT = 0;
        P4DIR = 0xFF;
        P4OUT = 0;
        P1DIR |= 0x03;

        while (1)
        {
        ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
        __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled

            // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
            temp = ADC10MEM;
            IntDegC = ((temp - 673) * 423) / 1024;
            IntDegC= (int)IntDegC;
     
            Delay_500ms();
            LED_ON (LED_RED); //  make blink the Red Led to show initialization
            Delay_500ms();
            LED_OFF (LED_RED);
                    
                            while(IntDegC>=10)
                            {
                            IntDegC=IntDegC-10;
                            LED_ON (LED_RED);
                            LED_ON (LED_GREEN);
                            Delay_500ms();
                            LED_OFF (LED_RED);
                            LED_OFF (LED_GREEN);
                            Delay_500ms();
                            Delay_500ms();
                            }
                            while(IntDegC>=1)
                            {
                            IntDegC=IntDegC-1;
                            LED_ON (LED_GREEN);
                            Delay_500ms();
                            LED_OFF (LED_GREEN);
                            Delay_500ms();
                            Delay_500ms();
                            }
        }  
    }

    void LED_ON (int LED)
    {
        P1OUT |= LED;
    }

    void LED_OFF (int LED)
    {
        P1OUT &= ~LED;
    }

    void Delay_500ms(void)
    {
        TACCTL0 &= ~CCIFG;
        TACCTL0 = CCIE;
        TACTL = TASSEL_1 + MC_1;
        TACCR0 = 16384;
        __bis_SR_register(LPM3_bits + GIE);  
    }

    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A(void)
    {
        __bic_SR_register_on_exit(LPM3_bits + GIE);
    }

    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
      __bic_SR_register_on_exit(CPUOFF);
    }


    Do you have any idea about this mistake of 8°C (17°C -> 25°C) ??? Is this a sensor with very low accuracy ???

    Thank you for the answers

    Matthias

  • It's all rigth, it's working well I think. To my mind, the mistake of 8°C is due to the internal temperature sensor because it is locked inside the MSP430, so it can't be very reagent.


    Now, I would like to mesure a tension (external temperature sensor) on the pin 4.5 (for example), so now I know how to manage the ADC10 but I still don't know how to specify in the code the connection with the pin 4.5.

    Do you have any idea how to do that ?

    Thank you for the answers and for your time,

    Matthias

  • Matthias JUSTON said:
    To my mind, the mistake of 8°C is due to the internal temperature sensor because it is locked inside the MSP430,

    Yes. +8° is what you can expect from a working MSP. IIRC, 10° are deducted from the maximum ambient temperature against junction temperature in the datasheet, to cover the self-heating.

    My own experiments with the temperature sensor got similar differences of chip surface temperature and internal sensor. (>30°C in a 24°c room)

  • Hi Matthias,

    you just have to look into the datasheet of your device and select a unused pin with a analog input function (Axx, like A1 or A14). Select this as the ADC input, instead of A10 (the internal connected temp. sensor).
    Last thing you have to do is configure the port pin to work as a analog input and not as an digital i/o.

    The code examples (http://www.ti.com/lit/zip/slac123) will also help you, I think.

    Best regards,
    Mario

  • Jens-Michael Gross said:
    Yes. +8° is what you can expect from a working MSP

    My mistake. You're reading -8°C. This is odd.

    However, both, the offset and the factor for the temperature calculation undergo a wide variation form device to device. The values from the users guide are only an example. YOu need to calibrate it per device.

    On some MSPs, the 'real' calibration values are available in form of ADC10MEM readings for 0° and 80° (so you can extrapolate offset and increment) for both references. On others, all you can do it doing exactly this: bring the MSP on two controlled temperatures and calibrate it (two-point calibration)

     

**Attention** This is a public forum