328p internal temperature

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

I am looking to read the internal temperature off the ADC and I am reading a constant value of 384 not matter what. The code for arduino works perfect but I cannot port it over into atmel studio.

Here is my code

/*
 * Internal_temperature.c
 *
 * Created: 2/6/2013 2:11:08 PM
 *  Author: 478
 */ 


#include 

int main(void)
{
	
	unsigned int adc_value;
	DDRD  |= (1<<PD6);
	ADMUX= 0xC8;              //select 1.1 vref + channel 8	
	
    while(1)
    {
		
		ADCSRA |=(1<<ADEN);           //enable adc
		ADCSRA |=(1<<ADSC);           //init conversion
		while(ADCSRA & (1<<ADSC));    //wait for conv complete
		
		adc_value = ADCW;
		//adc_value = ADC;
		
		if(adc_value == 384)
			PORTD  |= (1<<PD6); // this is always 384 no matter what temperature
		else
			PORTD  &= ~(1<<PD6);
    }
}

This code works when compiled in arduino, i get a changing number on ADC

// Internal Temperature Sensor
// Example sketch for ATmega328 types.
// 
// April 2012, Arduino 1.0

void setup()
{
  Serial.begin(9600);

  Serial.println(F("Internal Temperature Sensor"));
}

void loop()
{
  // Show the temperature in degrees Celcius.
  Serial.println(GetTemp(),1);
  delay(1000);
}

double GetTemp(void)
{
  unsigned int wADC;
  double t;

  // The internal temperature has to be used
  // with the internal reference of 1.1V.
  // Channel 8 can not be selected with
  // the analogRead function yet.

  // Set the internal reference and mux.
  ADMUX = 0xC8;
  ADCSRA |= (1<<ADEN);  // enable the ADC

  delay(20);            // wait for voltages to become stable.

  ADCSRA |= (1<<ADSC);  // Start the ADC

  // Detect end-of-conversion
  	while (ADCSRA & (1<<ADSC));

  // Reading register "ADCW" takes care of how to read ADCL and ADCH.
  wADC = ADCW;
  Serial.println( wADC);
  // The offset of 324.31 could be wrong. It is just an indication.
  t = (wADC - 324.31 ) / 1.22;

  // The returned temperature is in degrees Celcius.
  return (t);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, first of all, are you positive that you have the LED connected active high?

What speed is your AVR running at? With no prescaler bits set, the ADC would be running with a clock that is much too fast.

Interesting that 384 is exactly 256+128.

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

What's the problem? The internal temp sensor works but is not particularly accurate.

It is easy enough to port the Arduino sketch to a regular C program. You only need to swap the Serial.xxx() functions for regular printf().

David.

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

theusch wrote:
Well, first of all, are you positive that you have the LED connected active high?

What speed is your AVR running at? With no prescaler bits set, the ADC would be running with a clock that is much too fast.

Interesting that 384 is exactly 256+128.

I was using a serial library to print 384. I was unsure if other code was affecting the value so I basically stripped out everything and I have hooked a multimeter into the port. I am using an 8Mhz ext crystal with fuses set to 8 Mhz. Its wierd how it works on the arduino code but not on mine.

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

Quote:

Its wierd how it works on the arduino code but not on mine.

Are you building for the correct AVR model?

As you have a small complete test program, post the generated code especially around the = ADCW; line. Examination will tell whether the correct I/O address is being read.

And >>do<< read up on setting the prescaler properly. For an 8MHz clock it should be about /64.

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 will definitely take a look at the prescalers. When you said output, did you mean the assembly?

Internal_temperature.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000e2  00000000  00000000  00000054  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .stab         000006cc  00000000  00000000  00000138  2**2
                  CONTENTS, READONLY, DEBUGGING
  2 .stabstr      00000085  00000000  00000000  00000804  2**0
                  CONTENTS, READONLY, DEBUGGING
  3 .debug_aranges 00000080  00000000  00000000  00000890  2**3
                  CONTENTS, READONLY, DEBUGGING
  4 .debug_info   00000337  00000000  00000000  00000910  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .debug_abbrev 00000099  00000000  00000000  00000c47  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_line   00000297  00000000  00000000  00000ce0  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_frame  00000024  00000000  00000000  00000f78  2**2
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_str    000000cf  00000000  00000000  00000f9c  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
   8:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
   c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  10:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  14:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  18:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  1c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  20:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  24:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  28:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  2c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  30:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  34:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  38:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  3c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  40:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  44:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  48:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  4c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  50:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  54:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  58:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  5c:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  60:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>
  64:	0c 94 51 00 	jmp	0xa2	; 0xa2 <__bad_interrupt>

00000068 <__ctors_end>:
  68:	11 24       	eor	r1, r1
  6a:	1f be       	out	0x3f, r1	; 63
  6c:	cf ef       	ldi	r28, 0xFF	; 255
  6e:	d8 e0       	ldi	r29, 0x08	; 8
  70:	de bf       	out	0x3e, r29	; 62
  72:	cd bf       	out	0x3d, r28	; 61

00000074 <__do_copy_data>:
  74:	11 e0       	ldi	r17, 0x01	; 1
  76:	a0 e0       	ldi	r26, 0x00	; 0
  78:	b1 e0       	ldi	r27, 0x01	; 1
  7a:	e2 ee       	ldi	r30, 0xE2	; 226
  7c:	f0 e0       	ldi	r31, 0x00	; 0
  7e:	02 c0       	rjmp	.+4      	; 0x84 <__do_copy_data+0x10>
  80:	05 90       	lpm	r0, Z+
  82:	0d 92       	st	X+, r0
  84:	a0 30       	cpi	r26, 0x00	; 0
  86:	b1 07       	cpc	r27, r17
  88:	d9 f7       	brne	.-10     	; 0x80 <__do_copy_data+0xc>

0000008a <__do_clear_bss>:
  8a:	11 e0       	ldi	r17, 0x01	; 1
  8c:	a0 e0       	ldi	r26, 0x00	; 0
  8e:	b1 e0       	ldi	r27, 0x01	; 1
  90:	01 c0       	rjmp	.+2      	; 0x94 <.do_clear_bss_start>

00000092 <.do_clear_bss_loop>:
  92:	1d 92       	st	X+, r1

00000094 <.do_clear_bss_start>:
  94:	a0 30       	cpi	r26, 0x00	; 0
  96:	b1 07       	cpc	r27, r17
  98:	e1 f7       	brne	.-8      	; 0x92 <.do_clear_bss_loop>
  9a:	0e 94 53 00 	call	0xa6	; 0xa6 
9e: 0c 94 6f 00 jmp 0xde ; 0xde <_exit> 000000a2 <__bad_interrupt>: a2: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 000000a6
: #include int main(void) { unsigned int adc_value; DDRD |= (1<<PD6); a6: 56 9a sbi 0x0a, 6 ; 10 ADMUX= 0xC8; //select 1.1 vref + channel 8 a8: 88 ec ldi r24, 0xC8 ; 200 aa: 80 93 7c 00 sts 0x007C, r24 while(1) { ADCSRA |=(1<<ADEN);//enable adc ae: ea e7 ldi r30, 0x7A ; 122 b0: f0 e0 ldi r31, 0x00 ; 0 ADCSRA |=(1<<ADSC);//init conversion while(ADCSRA & (1<<ADSC)); //wait for conv complete adc_value = ADCW; b2: a8 e7 ldi r26, 0x78 ; 120 b4: b0 e0 ldi r27, 0x00 ; 0 DDRD |= (1<<PD6); ADMUX= 0xC8; //select 1.1 vref + channel 8 while(1) { ADCSRA |=(1<<ADEN);//enable adc b6: 80 81 ld r24, Z b8: 80 68 ori r24, 0x80 ; 128 ba: 80 83 st Z, r24 ADCSRA |=(1<<ADSC);//init conversion bc: 80 81 ld r24, Z be: 80 64 ori r24, 0x40 ; 64 c0: 80 83 st Z, r24 while(ADCSRA & (1<<ADSC)); //wait for conv complete c2: 80 81 ld r24, Z c4: 86 fd sbrc r24, 6 c6: fd cf rjmp .-6 ; 0xc2 adc_value = ADCW; c8: 8d 91 ld r24, X+ ca: 9c 91 ld r25, X cc: 11 97 sbiw r26, 0x01 ; 1 if(adc_value == 384) ce: 21 e0 ldi r18, 0x01 ; 1 d0: 80 38 cpi r24, 0x80 ; 128 d2: 92 07 cpc r25, r18 d4: 11 f4 brne .+4 ; 0xda PORTD |= (1<<PD6); d6: 5e 9a sbi 0x0b, 6 ; 11 d8: ee cf rjmp .-36 ; 0xb6 else PORTD &= ~(1<<PD6); da: 5e 98 cbi 0x0b, 6 ; 11 dc: ec cf rjmp .-40 ; 0xb6 000000de <_exit>: de: f8 94 cli 000000e0 <__stop_program>: e0: ff cf rjmp .-2 ; 0xe0 <__stop_program>
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That all looks OK to me. Have you tried heating or cooling the chip to see if the value changes?

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
#include 
extern void initstdio(void);
#include "portab_mcu.h"
#define delay(ms) DELAY_MS(ms)

double GetTemp(void)
{
    ADMUX = (3 << REFS0) | (8 << MUX0); // 1.1V REF, channel#8 is temperature
    ADCSRA |= (1 << ADEN) | (6 << ADPS0);       // enable the ADC div64
    delay(20);                  // wait for voltages to become stable.
    ADCSRA |= (1 << ADSC);      // Start the ADC

    while (ADCSRA & (1 << ADSC));       // Detect end-of-conversion
    // The offset of 324.31 could be wrong. It is just an indication.
    // The returned temperature is in degrees Celcius.
    return (ADCW - 324.31) / 1.22;
}

void main(void)
{
    volatile double a;
    double c;
    initstdio();
    printf("Internal Temperature Sensor\r\n");
    while (1) {
        printf("Temp is: %f\r\n", GetTemp());
        delay(1000);
    }
}

This works reasonably well on my Arduino hardware. It varies between 22.69C and 23.51C. I guess that my living room is about 19C. So you need to do some 'calibration'.

David.

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

theusch wrote:
That all looks OK to me. Have you tried heating or cooling the chip to see if the value changes?

Yeah, its constant 384

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

Try changing the line...

ADCSRA |=(1<<ADEN);           //enable adc 

to...

ADCSRA =(1<<ADEN) | 0x07;           //enable adc, with  divide by 128 prescaling

If I remember correctly, the Arduino 'runtime' sets the prescaler 'invisibly'. Without prescaling, the ADC will (very likely) be running WAY too fast.

Also, though not as likely an issue, there are two versions of the '328'. The Pico Power version includes the temperature sensor on channel 8... the other version does not.

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

it is indeed prescaling, thanks for all the effort everyone!!!

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

hi
help
example code internal temperatur atmeg328p for codevision ?

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

What is wrong with the code and its corrections above?

 

Ross McKenzie ValuSoft Melbourne Australia

Last Edited: Thu. Apr 30, 2015 - 08:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sinaset wrote:

example code internal temperatur atmeg328p for codevision ?

 

Have you tried the code in post #8? The relevant function compiles without change in CVAVR.

'This forum helps those who help themselves.'

 

pragmatic  adjective dealing with things sensibly and realistically in a way that is based on practical rather than theoretical consideration.

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

... and then consider post #10

 

Ross McKenzie ValuSoft Melbourne Australia

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

Thanks for reply

no.The problem is not solved

 

here code me:

Function

#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (1<<MUX3))

READ ADC

unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
delay_us(10);
ADCSRA|=(1<<ADSC);
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}

and ...

    a=read_adc(8);
    b=a- 324.31;  
    b=b / 1.22;
    c=b/100;
    d=(b-(c*100))/10;
    e=b-((c*100)+(d*10));   

erro proteus!!!

 

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

How do you expect Proteus to know what the temperature is?

 

I suggest that you try reading the regular ADC channels.   You can connect a 'Proteus voltage generator' to the regular ADC pins.   (I think)

 

Your current default value should be:

#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0))

because you OR in the channel# in :

    ADMUX = adc_input | ADC_VREF_TYPE;

e.g. if you want to read channel#3,   you connect 0.5V to ADC3 pin in Proteus.   and get the result = read_adc(3)

 

David.

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

Does the simulator correctly handle the 'other' ADC inputs?

'This forum helps those who help themselves.'

 

pragmatic  adjective dealing with things sensibly and realistically in a way that is based on practical rather than theoretical consideration.

Last Edited: Thu. Apr 30, 2015 - 11:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi

tanks you mr valusoft and Brian Fairchild and david.prentice

Problem solvedyes

 

here code me

#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (1<<MUX3))
{
ADMUX=adc_input | ADC_VREF_TYPE;
delay_us(10);
ADCSRA|=(1<<ADSC);
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}

Calculation and Calibration

    
    a=read_adc(8); 
    if(a>314)
    {
    b=a-314;
    } 
     else if (a==314)
    {
    b=0;
     }
    else if (a<314)
    {
    b=314-a;
     }
     
    c=b/100;
    d=(b-(c*100))/10;
    e=b-((c*100)+(d*10));     

Code 7Segment Multiplex

    for (i = 0; i < 1000; i++)
    {
    PORTB=1;

    if(a<=317) PORTD=~0x40;  
    else PORTD=0xff;
    delay_us(300);
        
    PORTB=2;
    if(d>=1) PORTD=~s[d];
    else PORTD=0xff;
    delay_us(300);
                       
    PORTB=4;
    PORTD=~s[e];
    delay_us(300); 
    
    PORTB=4;
    PORTD.7=0;
    delay_us(300);

    PORTB=8;
    PORTD=~0x39;
    delay_us(300); 
    }

 

The simulation test (ADC(0) Instead ADC(8))

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

change

<

while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);

>

to

<

while ((ADCSRA & (1<<ADSC))==0);
>

Imagecraft compiler user

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

to

<

while ((ADCSRA & (1<<ADSC))==0);
>

he really means:

 

to

<

while (ADCSRA & (1<<ADSC));
>

wink

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

hi

Thanks for reply

change to(The problem occurs)

while ((ADCSRA & (1<<ADSC))==0);

-----

why change

while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);

 

to

while ((ADCSRA & (1<<ADSC))==0);

and

while (ADCSRA & (1<<ADSC));

?

 

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

Clearing the ADIF flag requires an instruction. Waiting for ADSC to go to zero doesnt need the extra instruction. Sometimes the flash is almost full and you need space for a couple more instructions.

 

Imagecraft compiler user

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

tanks you clawson and bobgardner 

good job

---

you can help،sleep mod atmega328p ?

go micro to mod "powerdown" or "powersave" wakeup by "interrupt timer0"and"input volt PIN"...

(help by codevisionor c)

tanks