ATtiny202 temperature measurement settings ?

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the ATtiny202-402-DataSheet-DS40001969B is mentioned on the pdf page 416:
 

29.3.2.6 Temperature Measurement
The temperature measurement is based on an on-chip temperature sensor. For a temperature measurement, follow these steps:

 

  1. Configure the internal voltage reference to 1.1V by configuring the in VREF peripheral.
  2. Select the internal voltage reference by writing the REFSEL bits in ADCn.CTRLC to 0x0.
  3. Select the ADC temperature sensor channel by configuring the MUXPOS register
  4. (ADCn.MUXPOS). This enables the temperature sensor.
  5. In ADCn.CTRLD Select INITDLY ≥ 32 μs × fCLK_ADC
  6. In ADCn.SAMPCTRL Select SAMPLEN ≥ 32 μs × fCLK_ADC
  7. In ADCn.CTRLC Select SAMPCAP = 5 pF
  8. Acquire the temperature sensor output voltage by starting a conversion.
  9. Process the measurement result as described below.

 

I am using ADC/4 prescaler (i.e. 3,333,333 Hz / 4). What parameters I should use for

ADC0.CTRLD = ADC_INITDLY_DLY32_gc;
ADC0.SAMPCTRL = ADC_SAMPLEN2_bm;

 

I do not understand the expression ≥ 32 μs × fCLK_ADC

 

#include <avr/io.h>

uint16_t temperature;

// measure internal temperature of ATtiny202 in °C
int16_t measure_internal_temperature() {
    // setup ADC to measure temperature
    VREF.CTRLA = VREF_ADC0REFSEL_1V1_gc;
    ADC0.CTRLC = ADC_PRESC_DIV4_gc | ADC_REFSEL_INTREF_gc | ADC_SAMPCAP_bm;
    ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;
    ADC0.CTRLD = ADC_INITDLY_DLY32_gc;
    ADC0.SAMPCTRL = ADC_SAMPLEN2_bm;
    ADC0.CTRLA = ADC_ENABLE_bm;
    ADC0.COMMAND = ADC_STCONV_bm;
    while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
    // calculate T in °C
    int8_t sigrow_offset = SIGROW.TEMPSENSE1;
    uint8_t sigrow_gain = SIGROW.TEMPSENSE0;
    int32_t tmp = ADC0.RES - sigrow_offset;
    tmp *= sigrow_gain;
    tmp += 0x80;
    tmp >>= 8;
    tmp -= 273; // °K to °C
    ADC0.CTRLA = 0; // disable ADC
    return ((int16_t) tmp);
}

int main(void) {
    /* Replace with your application code */

    temperature = measure_internal_temperature();
    asm ("nop");

    while (1) {
    }
}

 

This topic has a solution.
Last Edited: Fri. Feb 12, 2021 - 11:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do not understand the expression ≥ 32 μs × fCLK_ADC

Take the freq and mult by 32E-6....so (example) 5 MHz would require at least 160 delay counts 

 

You have time*Hz, which is time*(1/time) = dimensionless number 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Feb 12, 2021 - 01:42 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have selected ADC_PRESC_DIV4_gc.

fCLK_ADC is 3.33MHz / 4 = 0.833MHz.

 

The setting must be greater than or equal to fCLK_ADC (MHz) * 32 for ADC_INITDLY to achieve 32uS.

In this case, it is 26.7 or higher, so ADC_INITDLY_DLY32_gc is fine.

 

ADC_SAMPLEN is this 26.7 clock minus 2. That is 25 or more.

Set ADC0.SAMPCTRL = 25 ;.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, for ADC0.SAMPCTRL = 25 ;

I got the right temperature 25°C (77°F) smiley.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevil wrote:
I do not understand the expression ≥ 32 μs × fCLK_ADC

 

'' means "greater than or equal to" - or, in other words, "not less than"

 

So it's telling you that your value for  INITDLY needs to be not less than 32 μs × fCLK_ADC

 

Kevil wrote:
I got the right temperature

If that's resolved the issue, please mark the solution - see Tip #5 in my signature, below:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Feb 12, 2021 - 09:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem was not '≥' but how to calculate 32µs * 0.833MHz which is = 32E-6 *0.833E6 = 26.66

 

Why to subtract 2 from 26.66 ? The conversion takes 2 CLK_ADC cycles?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please read the data sheet.

Sampling has 2 clocks by default and SAMPLEN is an additional clock.

Since it is sufficient to satisfy 32us in total, subtract 2.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is is possible to modify the code (how ?) to get the temperature value with accuracy of tenths of degree?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevil wrote:

Is is possible to modify the code (how ?) to get the temperature value with accuracy of tenths of degree?

Unlikely from a MCU sensor.

 

eg From an AVR data sheet (ATtiny1614)

 

TRES Conversion resolution 10 bits - 0.55 - °C

 

that means the LSB is 0.55°C, so 0.1°C is well outside what is possible.

 

You are better finding a dedicated i2c temperature sensor, if you chase fractions of a degree.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevil wrote:
Is is possible to modify the code (how ?) to get the temperature value with accuracy of tenths of degree?

So, let's say you DO such a modification.

 

What does the temperature inside the AVR chip to such a precision and accuracy tell you?  Chances are, the AVR's internal temperature inside its enclosure is quite a bit different from e.g. the ambient outside the enclosure.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am going to put ATtiny202 on my PCB into the original THN132N sensor casing fixed on the outside window. I will be fine with the resolution of one degree.
 

The original THN132N sensor has a thermistor just a little elevated above the PCB.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevil wrote:

Is is possible to modify the code (how ?) to get the temperature value with accuracy of tenths of degree?

Search for the App Note on Oversampling and Decimalization

 

Jim

IIRC AVR121 enhancing_ADC_resolution_by_oversampling

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

Last Edited: Wed. Mar 24, 2021 - 01:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your advice, I will have a look on it.
 

To get additional digit after the decimal point I need 4 bits which means 4^4 = 256 samples. The ATtiny202 ADC has accumulation up to 64 Samples per Conversion which are only 3 bits (4^3 = 64). I'm not sure if I can solve this by adding four 64 samples.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can do however many you want- 10*64, 100*64, 1000*64, or any other combinations you want, all in one go, or done over some time period. Simply adjust your formula to account for the additional readings accumulated, and in the case of 10,100 etc. your final adjustment will be to /64 to get to tenths, hundredths, etc. Your extra resolution may have little meaning since it is buried inside your accuracy (lack of), but you can test to see what you get and at the very least it is a way to fake getting tenths and send it out.

 

u32 k = 0;

for( u8 i = 0; i < 10; i++ ) k += readAdcAcc64();

k -= toffset*640;

k = (k*tgain + 128) / 256;

//now we have k *640

i16 C = (k - 273*640) / 64;

//C = C x10, 253 = 25.3C

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's great, it really works. Thank you. I got values in °C * 10: 249, 251, 251, 251 and 252 for five runs.

Real ATtiny202 MPLAB X IDE code:

 

#include <avr/io.h>

int16_t temperature;

// measure internal temperature of ATtiny202 in °C

int16_t measure_internal_temperature() {
    // setup ADC to measure temperature
    VREF.CTRLA = VREF_ADC0REFSEL_1V1_gc;
    ADC0.CTRLC = ADC_PRESC_DIV4_gc | ADC_REFSEL_INTREF_gc | ADC_SAMPCAP_bm;
    ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;
    ADC0.CTRLD = ADC_INITDLY_DLY32_gc;
    ADC0.SAMPCTRL = 27; // 32E-6 / (1/(3333333/4)) - 2
    ADC0.CTRLA = ADC_ENABLE_bm;
    ADC0.COMMAND = ADC_STCONV_bm;
    while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
    // calculate T in °C
    int8_t sigrow_offset = SIGROW.TEMPSENSE1;
    uint8_t sigrow_gain = SIGROW.TEMPSENSE0;
    int32_t tmp = ADC0.RES - sigrow_offset;
    tmp *= sigrow_gain;
    tmp += 0x80;
    tmp >>= 8;
    tmp -= 273; // °K to °C
    ADC0.CTRLA = 0; // disable ADC
    return ((int16_t) tmp);
}

int16_t measure_tenths_of_degrees() {
    // setup ADC to measure temperature
    VREF.CTRLA = VREF_ADC0REFSEL_1V1_gc;
    ADC0.CTRLC = ADC_PRESC_DIV4_gc | ADC_REFSEL_INTREF_gc | ADC_SAMPCAP_bm;
    ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;
    ADC0.CTRLD = ADC_INITDLY_DLY32_gc;
    ADC0.SAMPCTRL = 27; // 32E-6 / (1/(3333333/4)) - 2
    ADC0.CTRLB = ADC_SAMPNUM_ACC64_gc;  // 64 Samples
    ADC0.CTRLA = ADC_ENABLE_bm;

    uint32_t k = 0;
    for (uint8_t i = 0; i < 10; i++) {
        ADC0.COMMAND = ADC_STCONV_bm;
        while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
        k += ADC0.RES;
    }

    int8_t sigrow_offset = SIGROW.TEMPSENSE1;
    uint8_t sigrow_gain = SIGROW.TEMPSENSE0;

    k -= sigrow_offset * 640;
    k = (k * sigrow_gain + 128) / 256;

    int16_t C = (k - (uint32_t) 273 * 640) / 64;
    ADC0.CTRLA = 0; // disable ADC
    return (C);
}

int main(void) {
    /* Replace with your application code */

//    temperature = measure_internal_temperature();
    temperature = measure_tenths_of_degrees();
    asm("nop");

    while (1) {
    }
}

 

Last Edited: Wed. Mar 24, 2021 - 08:35 PM