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.

Temp sensor issue

Other Parts Discussed in Thread: MSP430G2553

I am using MSP430G2553 for temperature sensor application. i am pasting here 2 types od codes

code 1:

#include <msp430g2553.h>

unsigned int T_count;
unsigned int emflag =0;
unsigned int B_count;
long ActualTemp;
long IntDegC;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
T_count =0;
DCOCTL = 0;
BCSCTL1= CALBC1_8MHZ; // System Clock Settings
DCOCTL = CALDCO_8MHZ; // use calibrated 8MHz settings
P1DIR |= BIT0+BIT2+BIT3; // P1.2 and P1.3 output
P1SEL |= 0x0C; // P1.2 and P1.3 TA1/2 options
_bis_SR_register(GIE);

TA1CCR1 = 5000;
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CTL = TASSEL_2 + MC_2 + ID_3 + TAIE; // SMCLK, contmode
}

#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_B (void)
{
switch (__even_in_range(TA1IV, 10)) // Efficient switch-implementation
{
case 0:
break;
case 2:
TA1CCR1 += 50000; //50ms //6/10/2010
break;
case 10: //655.35ms
T_count++;
if(T_count >= 4)
{
T_count = 0;
ADC10CTL1 = INCH_10 + ADC10DIV_3;
ADC10CTL0 = SREF1 + ADC10SHT_3 + ADC10ON + REFON;
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
ActualTemp = ADC10MEM;
IntDegC = ((ActualTemp - 673) * 423) / 1024;
__no_operation(); // break point here
}
break;
}
}

When i put break point on  _no_operation(); to read "IntDegC" @ room temp (25C) i am getting 144 decimal. I am debugging on computer with TI launchpad.

here is the code 2:

#include <msp430.h>

long temp;
long IntDegF;
long IntDegC;

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
temp = ADC10MEM;
IntDegF = ((temp - 630) * 761) / 1024;
temp = ADC10MEM;
IntDegC = ((temp - 673) * 423) / 1024;

__no_operation(); // SET BREAKPOINT HERE

}

This code works fine and at breakpoint i am readin temp 22C which is very close to ambient temperature.

Since, in my application i want to read temperature every 1 min, i want to use timer in continuous mode with interrupt every minute. so code 1 should work.

tell me if anything is wrong with the code 1.

Thanks

Abhishek

  • Code 2 can't reliably work (in other words: it is pure coincidence):

    abhishek Sabnis said:
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    temp = ADC10MEM;


    Here you start the conversion and in the very next instruction you read the result. Now it takes some time to complete a conversion. You must check whether the conversion is complete (by either checking the ADC10BUSY bit or the ADC10IFG bit) before you read the result. Else you read the result of the last conversion or (after power-up) maybe a random result. But not the result of the converison you just started.
    With SHT_3, a converison takes 64+13 =77 ADC10CLK cycles, which (depending on your specific part) is 12-22µs or 12-22 CPU instructions (assuming 1MHz system clock).
    Worse: Reading the temperature sensor requires a minimum sampling time of 30µs. Since the maximum sampling time is 64*ADC10CLK, ADC10CLK must not be above 2MHz. But the internal ADC10OSC is 3.5 to 6.3MHz. You need to use SMCLK or ACLK as ADC10CLK, with a maximum frequency of 2MHz.

    Also, after switching the reference on, it requires a certain settling time, so after setting REFON, you'll have to wait (30µs, according to the datasheet). Else your readings are using an instable reference.

    Now to yor formula: you are using the typical values for offset and gain. However, the temperature sensor values vary widely for each individual MSP. You may have a gain of 3.55mV/°C, but it can be significantly higher or lower. And the datasgeet doesn't even give a typical value for the offset.
    On some MSPs, there are calibration values available for 30°C and 85°C. With these, you can calculate offset and gain for each MSP individually (at runtime). But AFAIK the 2553 doesn't have them (calibraiton takes tiem and tiem is money and the 22553 is cheap). So you'll need to calibrate it yourself. One by one.

  • Thanks Jens for your reply.

    I modified my software according to your suggestion.

    Here is the updated code:

    #include <msp430g2553.h>
    unsigned int T_count;
    unsigned int emflag =0;
    unsigned int B_count, timeout;
    long ActualTemp;
    long IntDegC;
    void main(void)
    {

    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    // ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
    // ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;
    T_count =0;
    DCOCTL = 0;
    P1DIR |= BIT0+BIT6;
    BCSCTL1= CALBC1_8MHZ; // System Clock Settings
    DCOCTL = CALDCO_8MHZ; // use calibrated 8MHz settings
    P1DIR |= BIT0+BIT6; 
    _bis_SR_register(GIE);
    TA0CCR1 = 5000;
    TA0CCTL1 = CCIE; // CCR0 interrupt enabled
    TA0CTL = TASSEL_2 + MC_2 + TAIE; // SMCLK, contmode
    }
    void VarDelay(volatile unsigned long int time)
    {
    do (time--);
    while(time != 0);
    }
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer0_A1 (void)
    {
    switch (__even_in_range(TA0IV, 10)) // Efficient switch-implementation
    {
    case 0:
    break;
    case 2:
    TA0CCR1 += 50000; 
    break;
    case 10: 
    T_count++;
    if(T_count >= 1220)
    {
    T_count = 0;
    P1OUT ^= BIT0;
    ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;
    VarDelay(40); // Delay 10ms, 1 ms = 400
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    timeout = 1;
    while (!(ADC10CTL0 & ADC10IFG) && ++timeout);
    ActualTemp = ADC10MEM;
    ADC10CTL0 &= ~(ENC + ADC10SC); // Sampling and conversion stop
    IntDegC = ((ActualTemp - 673) * 423) / 1024;
    if(ActualTemp >= 697)
    P1OUT &= BIT6;
    if(ActualTemp < 692)
    P1OUT |= BIT6;
    __no_operation(); // break point here
    }
    break;
    }
    }

    Please look the code written in Red. i wait for approximatly 100 micro sec. after ref is turned on. then checking ADC10IFG bit before getting results. I am working on caliberation of MSP430G with know temperatures and adjusting formula.

    One question though: you mentioned using 2MHz clock, i am using 8MHz SMCLK in my application. do i really need to change it to 1MHz or 2 MHz?

  • Debasish,

    Cool down man. why are you getting so aggressive. I just want to make sure i am on right path or not.

    In my application, i use temeperature sensor just to differetiate 2 conditions, like

    if( temp >10C)

    { do this}

    if (temp <8C)

    {do this}

    i can do it just comparing ADC10MEM directly to evqivalent temperatures. so in that case correct my ADC10 register setting, btw i already made clk to run 1MHz

    ADC10CTL1 = INCH_10 + ADC10DIV_3; 
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;
    VarDelay(40); // Delay 0.5msec


    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    timeout = 1;
    while (!(ADC10CTL0 & ADC10IFG) && ++timeout);


    ActualTemp = ADC10MEM;
    ADC10CTL0 &= ~(ENC + ADC10SC); // Sampling and conversion stop

    Thanks,

    Abhishek

  • Thanks Debasish for your information. Just clarifying your statments:

    When i use  ADC10CTL0= ADC10ON + ADC10SHT_3+ADC10IE;  you said reference voltage of the internal temperature sensor is automatically used according to the datasheet. So, i need to caliberate ADC10MEM values for corresponding temperatures right?

  • Debasish,

    I ran experiment with your suggestions. I read 1C as 280, 5C=285, 11C= 292 etc. if i subtract 280 insted 273 i get approximate equivalent to degC   

  • Debasish,

    If you think its nonsense then just forget and don't answer. Its not compulsory to answer everything. But keep in mind that you are on social site.  

  • abhishek Sabnis said:
    I ran experiment with your suggestions. I read 1C as 280, 5C=285, 11C= 292 etc. if i subtract 280 insted 273 i get approximate equivalent to degC

    Hi abhishek,

    As Jens-Michael said earlier:

    Jens-Michael Gross said:
    However, the temperature sensor values vary widely for each individual MSP. You may have a gain of 3.55mV/°C, but it can be significantly higher or lower. And the datasgeet doesn't even give a typical value for the offset.
    On some MSPs, there are calibration values available for 30°C and 85°C. With these, you can calculate offset and gain for each MSP individually (at runtime).

    Although AFAIK this was not always the case, the msp430g2553 does now have temperature sensor calibration values. They're stored in the segment A TLV structure. Unfortunately msp430g2553.h doesn't define identifiers to allow easy access to the ADC calibrations. Also the value of TAG_ADC10_1 specified in the family user guide is incorrect - the value to use is in the 2553 datasheet. Still, the calibration data is available should you need it.

  • In case anyone's struggling to understand how this ADC10MEM - 273 = tempInCelsius method works (as I was last night) here's an explanation.

    As Debasish quoted from the 2553 datasheet earlier:

     VSensor,typ = TCSensor (273 + T [°C] ) + VOffset,sensor [mV]

    TCSensor is typically 3.55mV/°C and 273 + T [°C]  is approximately T[°K], so that's:

     VSensor,typ = 3.55 * T [°K] + VOffset,sensor [mV]

    Which means that the temperature sensor's output voltage increases by 3.55mV for each 1°K rise in temperature.

    The next step is to configure the ADC10 so that a 3.55mV increase in the input voltage corresponds to an increase of 1 in the output value. With that done, each increment of the ADC10 output will correspond to a 1°K rise in temperature. That makes it possible to simply subtract an offset from the ADC10 output to get a temperature in °C. The offset used would need to account for both the 273.15 difference between Kelvin and Celsius temperatures, as well as the offset of the temperature sensor (which might not output exactly 0V at 0°K).

    Debasish uses this to set up the ADC:

     ADC10CTL0 = ADC10ON + ADC10SHT_3 + ADC10IE

    That implicitly sets the ADC's reference to SREF_0 (VR+ = VCC and VR- = VSS). If VCC happens to be 3.6V, then the ADC increments are 3.6/1024 = 0.00352V. Ideally VCC would be 0.00355 * 1024 = 3.635V, but 3.6V is close enough.

    As an aside, it also configures the internal reference-generator voltage to 1.5V but leaves it switched off. Looking at the ADC10 block diagram you can see that the temperature sensor uses Ref_x, which is the reference-generator output. For this reason the reference-generator is automatically enabled when INCHx=0Ah, even if REFON is 0. Far from not needing a reference, the temperature sensor and ADC use two reference voltages (+ground) for this method.

    It's a clever technique that allows minimal code for reading the temperature, but the following points need to be considered before using it:

    1. VCC must be 3.6V and reference-generator gets enabled during conversion.
    2. Factory-supplied temperature sensor calibrations cannot be used, as they are only provided for 1.5V and 2.5V ADC reference voltages.
    3. It's possible to calibrate for the sensor offset of a specific chip, but not for variations in TCSensor (which may differ from the typical value).
    4. This method restricts output temperature to integer values, which may be desirable for user display but sacrifices some precision.
  • Robert,

    Thanks for thorough response. 

    One question though. If i am using 3.3V can i still use this scheme.?

  • You could try it, but it will be less accurate than at 3.6V. The ADC increments will be equivalent to 3.3/1024= 0.00322V instead of 0.00355V. In that case, to get a 1°C change in your measured value would take only a 0.907°C change in the actual temperature.

    This will also affect the offset value quite a bit. Instead of producing an ADC result of 273, 0°C would give 273/0.907 = 301 (typical)

  • Debasish Banerjee said:
    even 2553 datasheet recommends what i did .

    Where is that in the datasheet? I haven't seen it. Thanks, Rob.
  • Debasish Banerjee said:

    open page 40 see 10-Bit ADC, Temperature Sensor and Built-In VMID (MSP430G2x53 Only), can u find:

    The sensor current ISENSOR is consumed if (ADC10ON = 1 and REFON = 1) or (ADC10ON = 1 and INCH = 0Ah and sample signal is

    high). When REFON = 1, ISENSOR is included in IREF+. When REFON = 0, ISENSOR applies during conversion of the temperature sensor
    input (INCH = 0Ah).

    That isn't a recommendation to use the method you proposed. It just explains the conditions under which the temperature sensor current (ISENSOR) needs to be accounted for.

    Specifically, the temperature sensor uses the reference-generator, so if the ADC isn't using the reference-generator (ie if it uses VCC as VR+) then the extra sensor current needs to be accounted for. If the ADC is using SREF_1 then the reference generator is already enabled so there's no need to add ISENSOR when calculating the total current.

  • Yes, but it's not just offset that needs to be corrected when VCC is not 3.6 volts.

    If VCC is 3.3V then a 0.9°C change in real temperature is measured as a 1°C change. If VCC is 2.2V then a 0.61°C change is measured as 1°C. With that level of error you only have to move 5°C away from the offset calibration point to get a 1°C error in the reading.

    I'm not saying this is a bad method that should never be used; as I already stated I think it's a clever idea. That said, people should be aware of all the advantages and disadvantages so they can make an informed decision of whether it works in their particular application.

  • No, it would require a multiply or divide to correct for the slope error

  • Debasish Banerjee said:

    But voltage Tc sensor is 3.55mV/dc when vcc is 3v...as per the datasheet says, then it is just that VSensor,typ = TCSensor (273 + T [°C] ) + VOffset,sensor [mV], why cant one just deduct the digital values for the offset from (ADC10MEM-273)?

    For the case where VCC = 2.2V and SREF=0:

    The sensor output changes 3.55mV/°C, but if the ADC's VR+ is VCC(=2.2V) the ADC increments correspond to 2.2/1024=0.00215V. For each 1°C that the real temperature rises, the temp sensor output increases by 3.55mV (typical). The problem is that the sensor output voltage needs to be read by the ADC, and that counts in 2.15mV steps when VR+ is VCC(=2.2V).

    This mismatch between the sensor output voltage steps and the ADC input voltage steps is what needs to be calibrated out with a multiply. If VCC is 3.6V then the multiply is not needed because the ADC steps are 3.6/1024, which is close enough to 3.55mV to give good results.

    Edit: To give a concrete example, say the offset is chosen so that the measured temperature is correct at 0°C. If the temperature rises by 10°C then the sensor output voltage will rise by 35.5mV. The ADC is using VCC (=2.2V) as reference voltage VR+, so the ADC value increases by 1 for each 2.15mV increase in input voltage (as explained above). ADC10MEM value will rise by 35.5/2.15, which is 16 (ignoring the decimal places). The measurement is correct at 0°C, but at 10°C it measures 16°C.

  • abhishek Sabnis said:
    Please look the code written in Red.

    I just answered in private conversation, but I'll post it here for completeness...

    i wait for approximatly 100 micro sec. after ref is turned on.

    First, how did you implement the wait? Depending on its implementation and the compiler and the selected optimization level, the waiting loop might not wait as long as you believe. e.g. simple for loops to 'waste time' are usually removed, as they don't change the state of the system.
    Delays should either use a timer, or use the (MCLK dependent) _delay_cycles intrinsic.

    You don't need a timeout for the conversion. Since the ADC is an independent piece of hardware, it will even then complete its conversion if the CPU had crashed in the meantime :)
    And by the seatings you make, you can exactly determine how long it will take (with some tolerance when using the ADC10OSC as clock source).

    abhishek Sabnis said:
    i am using 8MHz SMCLK in my application. do i really need to change it to 1MHz or 2 MHz?

    You don't need to change your SMCLK. The ADC as an own clock divider (ADC10DIVx), which you can set to ADC10DIV_3 to divide your 8MHz SMCLK to 2MHz for the ADC use (requiring AD10SSELx set to SMCLK too) or you use the ADC10OSC (as you do now already) and set ADC10DIVx accordingly (see datasheet for ADC10OSC default frequency, pick the worst case = highest frequency)[/quote]

    Debasish Banerjee said:
    as datasheet says "When REFON = 0, ISENSOR applies during conversion of the temperature sensor input (INCH = 0Ah)

    That's right. However, for ISensor to become stable, the reference used to create it must have settled. if it was previously off, the settling time of the reference must be added to the sampling time required for the temperature sensor. Since the maximum sampling time of 64 ADC0CLK pulses is too low then, you must slow down ADC10CLK accordingly.
    Also, measuring the temperature sensor against Vcc as reference doesn't make much sense, as VCC is not precise.
    However, letting the reference go on automatically at start of sampling and off after could be a good idea for low power usage. If, and only if, the reference settling time is added to the total sampling time. Now I'm not sure whether the reference stays on until the conversion i complete or onyl during the samplign stage. if it is on until conversion compelte, it could be used as reference for the conversion too (even thouh not explicitely enabled). If it is only on during sampling, th eonly available reference would be Vcc with the problem of not knowing VCC (unless it has been measured against a reference shortly before doing the conversion). Also, using hte higher Vcc as referenc ewill reduce the resolution.
    The comments in the datasheet for ISENSOR, however, indicate that the reference is only on during sampling period and will become unstable right after (during the conversion). So it woul dbe better to enable the reference and start the conversion (with extended sampling time), and disable he reference again after the conversion is done, using the reference for the conversion as well.

    Debasish Banerjee said:
    .the internal temparature sensor of MSP430G2553IN20 is Kelvin calibrated

    No. It isn't calibrated at all. It is just some sort of circuit with a positive temperature coefficient that is more or less linear with temperature. You could use a metal film resistor, apply a constant current and get a similar result.

    The current into the sensor isn't calibrated, it is just ensured to be constant  for a constant (reference) supply voltage. So the voltage produced by the temperature sensor has a gain and an offset. It is not ensured that the output voltage will be 0V at 0°K. It may have its zero point at 10°K or 100°K. Also the gain per °K (or °C) is not calibrated. But can be considered the same for the same reference voltage on the same MSP.
    So a manual calibration is always required:

    Put the circuit into your oven, measure the temperature when the oven is off with a precision thermometer and write down the ADC output. Now turn the oven on on lowest possible temperature (50°C to 80°C). When it has settled, read the precision thermometer and the ADC output again. You now know the ADC value difference and the temperature difference and you can easily calculate the offset and the gain per degree (If you want in °F or °R or °C or °K, it doesn't matter).

    Debasish Banerjee said:
    VSensor,typ = TCSensor (273 + T [°C] ) + VOffset,sensor [mV]" which shows the temparature reading is Kelvin calibrated

    No. It shows that the formula is Kelvin-based.
    VOffset,sensor isn't given at all and TCSENSOR is just a typical value without mentioning any tolerance range. No sign of any calibration.
    Calibraiton is required as suggested above or with a similar method.

  • Robert Cowsill said:
    If the ADC is using SREF_1 then the reference generator is already enabled so there's no need to add ISENSOR when calculating the total current.

    That's right for msot MSPs until 5x family. If th ereference is on, it will power the temperature sensor, whether it is used or not.

    Th e5x family, however, has a specific bit in its REF module that disables the temperature sensor and removes ISENSOR from IREF if you don't need it. So when migrating to 5x family, this somethign to take in mind for low-power operation.

    Debasish Banerjee said:
    But voltage Tc sensor is 3.55mV/dc when vcc is 3v...

    No, it typically is 3.55mV/°C.
    I'm a typical male German. I have a beard, wear glasses and I'm 6'4" tall.But that doesn't mean that all Germans are 6'4" tall with beard and glasses.
    When you measure the real TCSENSOR of a large number of MSPs, you'll get a distribution that may even include 0V/°C and VCC at the far borders, but the peak is at 3.55mV/°C.
    Since the G series originally didn't have any calibration values, I guess it wasn't checked whether the temperatur esensor wasn't checked at all. And no tolerances or min/max borders for the TC were even collected/specified.
    Now, there apparently is a calibration value available. However, still no collection of statistical data was made an/or put into the datasheet.

    However, taking a 'typical' value as an exact factor for a calculation, or to use it to reverse-calculating teh offset, is at least naive.

**Attention** This is a public forum