MSP430 Temperatursensor

Texas Instruments hat bei einigen MSPs einen Temperatursensor integriert (wie z.B. MSP430G2231, MSP430G2452, MSP430G2553 etc.). Dieser kann ziemlich einfach benutzt werden und reicht für viele Anwendungen (z.B. Raumtemperatur messen, eine hohe Genauigkeit darf man aber hier nicht erwarten). In diesem Artikel soll es um die Initialisierung und die Temperatur-Auswertung gehen. Es gibt verschiedene Möglichkeiten aus dem eingelesenen ADC-Wert die Temperatur zu berechnen/ermitteln.

Der Temperatursensor wird durch folgende Geradengleichung beschrieben (siehe User-Guide S. 556):

V_{temp}=0.00355V/^{\circ}C*(Temp_C)+0.986V

Gleichung 1.0

  • V_temp = eine bestimmte Spannung, die der Sensor bei einer bestimmten Temperatur liefert
  • Temp_c = die Temperatur in Grad-Celsius
  • Faktor “0.00355” = 3,55mV pro °C (die Steigung “m”)
  • Faktor “0.986” = bei 0°C gibt der Sensor eine Spannung von 0,986V raus, gewisser Offset (Verschiebung auf der Y-Achse, oder auch “b”)

msp430_temperatur

Der Ausgang von dem Sensor ist an Kanal 10 von dem 10bit-ADC angeschlossen, die Spannung wird digitalisiert. Also muss die Geradengleichung umgestellt werden. Die Gleichung wird nach “Temp_c” umgestellt:

Temp_C=\frac{V_{temp}-0.986V}{0.00355V/^{\circ}C}

Gleichung 1.1

Der ADC-Wert (also die Spannung am Eingang umgewandlet in einen digitalen Wert) berechnet sich aus:

ADC_{int}=\frac{V_{port}}{V_{ref}}*1023

Gleichung 2.0

  • ADC_int = digitaler Spannungswert vom 10bit-ADC als Integer-Wert
  • V_port = analoge EIngangs-Spannung am Port
  • V_ref = Referenzspannung (V_ref liegt bei 1,5V, wird automatisch bei der ADC-Initialisierung ausgewählt und sollte auch gewählt werden!)

Diese Gleichung umgestellt nach V_port ergbit:

V_{port}=\frac{V_{ref}}{1023}*ADC_{int}

Gleichung 2.1

Es gilt:

V_{port}=V_{temp}

Somit kann Gleichung 2.1 in Gleichung 1.1 eingesetzt werden:

 

Gleichung 3.0

Gleichung 3.0 könnte jetzt schon direkt in C programmiert werden, da der MSP430 Float-Berechnungen unterstützt. Float-Berechnungen werden aber nur “emuliert” und fressen somit einiges an Speicher und Zyklen, ist also nicht unbedingt zu empfehlen. Um eine Ganzzahlige-Berechnung durchzuführen muss Gleichung 3.0 noch vereinfacht werden. Dazu wird der Zähler durch 3.55mV/°C geteilt:

Gleichung 3.1

Gleichung 3.2

C-Programm

Ganzahlige-Berechnung

In dem ersten Programm wird die Gleichung 3.2 in C umgesetzt.

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     main_int.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2452.h>
  12. #define time 500
  13.  
  14. void main(void)
  15. {
  16.     volatile int m_sec=time;
  17.     volatile long temp_c=0;         //important! reserve 4bytes
  18.  
  19.     WDTCTL=WDTPW+WDTHOLD;           //stop WDT
  20.  
  21.     //Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  22.     ADC10CTL1=INCH_10+ADC10DIV_3;
  23.     //Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  24.     ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;
  25.  
  26.     for(;;)
  27.     {
  28.         ADC10CTL0|=ENC+ADC10SC;     //start & enable conversion
  29.         while(ADC10CTL1&ADC10BUSY); //ADC busy?
  30.  
  31.         //calculate temperature
  32.         temp_c=(((long)ADC10MEM*422)/1023)-277;
  33.  
  34.         while(m_sec--)          //wait 500ms
  35.             __delay_cycles(1000);
  36.         m_sec=time;
  37.     }
  38. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     main_int.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2452.h>
#define time 500

void main(void)
{
	volatile int m_sec=time;
	volatile long temp_c=0;			//important! reserve 4bytes

	WDTCTL=WDTPW+WDTHOLD;			//stop WDT

	//Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  	ADC10CTL1=INCH_10+ADC10DIV_3;
  	//Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  	ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;

  	for(;;)
  	{
  		ADC10CTL0|=ENC+ADC10SC;		//start & enable conversion
  		while(ADC10CTL1&ADC10BUSY);	//ADC busy?

  		//calculate temperature
  		temp_c=(((long)ADC10MEM*422)/1023)-277;

  		while(m_sec--)			//wait 500ms
			__delay_cycles(1000);
		m_sec=time;
  	}
}

Gleitkommazahl-Berechnung

Dieses Programm ist identisch zur ganzzahligen Berechnung, nur die Berechnung der Temperatur wird per Float-Wert berechnet (nicht unbedingt sinnvoll, aber sowas ist mit dem MSP430 möglich und in manchen Fällen kann es brauchbar sein).

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     main_float.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2452.h>
  12. #define time 500
  13.  
  14. void main(void)
  15. {
  16.     volatile int m_sec=time;
  17.     volatile float temp_c=0;
  18.  
  19.     WDTCTL=WDTPW+WDTHOLD;           //stop WDT
  20.  
  21.     //Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  22.     ADC10CTL1=INCH_10+ADC10DIV_3;
  23.     //Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  24.     ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;
  25.  
  26.     for(;;)
  27.     {
  28.         ADC10CTL0|=ENC+ADC10SC;     //start & enable conversion
  29.         while(ADC10CTL1&ADC10BUSY); //ADC busy?
  30.  
  31.         //calculate temperature
  32.         temp_c=(((1.5*(float)ADC10MEM)/1023)-0.986)/0.00355;
  33.  
  34.         while(m_sec--)          //wait 500ms
  35.             __delay_cycles(1000);
  36.         m_sec=time;
  37.     }
  38. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     main_float.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2452.h>
#define time 500

void main(void)
{
	volatile int m_sec=time;
	volatile float temp_c=0;

	WDTCTL=WDTPW+WDTHOLD;			//stop WDT

	//Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  	ADC10CTL1=INCH_10+ADC10DIV_3;
  	//Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  	ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;

  	for(;;)
  	{
  		ADC10CTL0|=ENC+ADC10SC;		//start & enable conversion
  		while(ADC10CTL1&ADC10BUSY);	//ADC busy?

  		//calculate temperature
  		temp_c=(((1.5*(float)ADC10MEM)/1023)-0.986)/0.00355;

  		while(m_sec--)			//wait 500ms
			__delay_cycles(1000);
		m_sec=time;
  	}
}

Zum Vergleich die Größen beider Programme:

Ganzzahl: Code Size – Text: 370 bytes Data: 2 bytes
Gleitkomma:
Code Size – Text: 894 bytes Data: 2 bytes

Berechnung über vordefiniertes Array

Wie im Beispiel-Programm Segmentanzeige über ein Potentiometer steuern (10bit ADC), kann ein Array mit vordefinierten Werten erstellt werden. Es muss nur noch das Feldelement aus dem ADC-Wert berechnet werden (Feldindex).

Nachteil: Es kann nur ein bestimmter Bereich definiert werden und kostet Speicher, je nachdem wie groß der Bereich ausfällt. Nicht mehr dynamisch, da vorher eine Tabelle angefertigt werden muss.

Vorteil: Schnelle Berechnung, möglicherweise niedriger Speicherverbrauch

Zunächst muss Gleichung 3.0 oder 3.2 nach “ADC_int” umgestellt werden:

Daraus kann nun der Integer-Wert berechnet werden (hier in einem Bereich von 15-30°C):

Temp in °C ADC_int ADC_int/2
15 708 354
16 710 355
17 713 356
18 715 357
19 717 358
20 720 360
21 722 361
22 724 362
23 727 363
24 729 364
25 732 366
26 734 367
27 736 368
28 739 369
29 741 370
30 744 372

Der berechnete ADC-Wert wird in der 3. Spalte durch 2 geteilt, somit wird der Abstand für das linear interpolierte Feld verringert (weniger Werte, das Feld soll so klein wie möglich bleiben).

Das linear interpolierte Feld lautet folgendermaßen:

15,16,17,18,19,19,20,21,22,23,24,24,25,26,27,28,29,29,30 (19 Werte)

Nun muss bei einem eingelesenen ADC-Wert das zugehörige Feldelement (also die Temperatur) berechnet bzw. ermittelt werden. Der Ablauf:

  1. ADC-Wert einlesen (z.B. 742)
  2. Wertebereichsüberprüfung
  3. ADC-Wert normalisieren: 742/2=371
  4. Feldelement berechnen: Der Anfangswert, also 15°C, hat einen ADC-Wert von 354, dieser Wert wird nun den 371 subtrahiert: 371-354=17
  5. Das 17. Element aus dem Feld lautet: 29°C

Das zugehörige C-Programm:

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     main_array.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2452.h>
  12. #define time        500
  13. #define start_temp  354         //15°C (708/2) is first value
  14.  
  15. const char temp_c_array[]={15,16,17,18,19,19,20,21,22,23,
  16.                             24,24,25,26,27,28,29,29,30};
  17.  
  18. void main(void)
  19. {
  20.     volatile int m_sec=time;
  21.     volatile int temp_c=0;
  22.  
  23.     WDTCTL=WDTPW+WDTHOLD;                   //stop WDT
  24.  
  25.     //Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  26.     ADC10CTL1=INCH_10+ADC10DIV_3;
  27.     //Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  28.     ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;
  29.  
  30.     for(;;)
  31.     {
  32.         ADC10CTL0|=ENC+ADC10SC;             //start & enable conversion
  33.         while(ADC10CTL1&ADC10BUSY);         //ADC busy?
  34.         temp_c=ADC10MEM/2;                  //normalize index
  35.         temp_c-=start_temp;
  36.  
  37.         //range test
  38.         if(temp_c>=temp_c_array[0]||temp_c<=temp_c_array[sizeof(temp_c_array)-1])
  39.             temp_c=temp_c_array[temp_c];    //get temperature
  40.         else
  41.             _NOP();                         //error or something else
  42.  
  43.         while(m_sec--)                      //wait 500ms
  44.             __delay_cycles(1000);
  45.         m_sec=time;
  46.     }
  47. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     main_array.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2452.h>
#define time 		500
#define start_temp	354			//15°C (708/2) is first value

const char temp_c_array[]={15,16,17,18,19,19,20,21,22,23,
							24,24,25,26,27,28,29,29,30};

void main(void)
{
	volatile int m_sec=time;
	volatile int temp_c=0;

	WDTCTL=WDTPW+WDTHOLD;					//stop WDT

	//Channel 10 (Temp. Sensor); ADC10 CLK divider /4; CLK=ADC10OSC
  	ADC10CTL1=INCH_10+ADC10DIV_3;
  	//Vref+=Vr+ and Vss=Vr- ; reference ON (1,5V); S&H time 16x; ADC10 on
  	ADC10CTL0=SREF_1+REFON+ADC10SHT_3+ADC10ON;

  	for(;;)
  	{
  		ADC10CTL0|=ENC+ADC10SC;				//start & enable conversion
  		while(ADC10CTL1&ADC10BUSY);			//ADC busy?
  		temp_c=ADC10MEM/2;					//normalize index
  		temp_c-=start_temp;

  		//range test
  		if(temp_c>=temp_c_array[0]||temp_c<=temp_c_array[sizeof(temp_c_array)-1])
  			temp_c=temp_c_array[temp_c];	//get temperature
  		else
  			_NOP(); 						//error or something else

  		while(m_sec--)						//wait 500ms
			__delay_cycles(1000);
		m_sec=time;
  	}
}

3 thoughts on “MSP430 Temperatursensor

  1. hannes

    Hi, mein Dozent meinte ich solle IQMathlib benutzen. Hat jemand eine Ahnung was das ist?

    Reply
  2. Jörg

    Hey, ich soll in meinem Studienprojekt, welches auch den Temp. Sensor beinhaltet, nun einige Testdaten erstellen. Hat wer eine Ahnung was damit gemeint ist?

    MfG

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.