Hi All,
I am trying to use On chip temperature sensor of Atmega1608, I am getting a value of 160Kelvin even though my MCU is sitting on table and ambient temperature is approx 300Kelvin. I am attaching my temp sense code below please take a look at it. My CLK_PER is 10Mhz, CLK_ADC =(10Mhz/8) =1.25Mhz. I did use the reference code mentioned in datasheet.
unsigned int internal_temp()
{
unsigned int sigrow_offset = SIGROW.TEMPSENSE1; // Read signed value from signature row
unsigned int sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned value from signature row
unsigned int adc_reading = 0; // ADC conversion result with 1.1 V internal reference
VREF.CTRLA= VREF_ADC0REFSEL_1V1_gc;
VREF.CTRLB = VREF_ADC0REFEN_bm;
ADC0.CTRLC= ADC_PRESC_DIV8_gc | ADC_SAMPCAP_bm | ADC_REFSEL_INTREF_gc; // f_per =10mhz. adc_clk= 10mhz/8= 1.25mhz
ADC0.MUXPOS= ADC_MUXPOS_TEMPSENSE_gc;
ADC0.CTRLD= ADC_INITDLY_DLY64_gc; // should be atleast 40
ADC0.SAMPCTRL= 40; // should be atleast 40
ADC0.CTRLB = ADC_SAMPNUM_ACC64_gc;
ADC0.CTRLA= ADC_ENABLE_bm;
ADC0.COMMAND= ADC_STCONV_bm;
while(!(ADC0.INTFLAGS & ADC_RESRDY_bm));
adc_reading = (ADC0.RES/64);
unsigned int temp = adc_reading - sigrow_offset;
temp *= sigrow_gain; // Result might overflow 16 bit variable (10bit+8bit)
temp += 0x80; // Add 1/2 to get correct rounding on division below
temp >>= 8; // Divide result to get Kelvin
return temp;
}
Use the stdint.h typedefs instead of 'int', it will make life easier when you can see what size types you are using. I would also be aware that an 'int' overflows at 65536 on the avr so watch multiplications even if you think there will be no overflow.
The datasheet gives an example, and uses the correct types-
int8_t sigrow_offset = SIGROW.TEMPSENSE1; // Read signed value from signature row
uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned value from signature row
uint16_t adc_reading = 0; // ADC conversion result with 1.1 V internal reference
uint32_t temp = adc_reading - sigrow_offset;
temp *= sigrow_gain; // Result might overflow 16 bit variable (10bit+8bit)
temp += 0x80; // Add 1/2 to get correct rounding on division below
temp >>= 8; // Divide result to get Kelvin
uint16_t temperature_in_K = temp;
With the adc_reading line obviously incomplete, so replace to get ADC0.RES/64.