Forum: Mikrocontroller und Digitale Elektronik ATMega328p Onchip Temperatur Sensor


von Aa B. (aaab)


Lesenswert?

Ich habe versucht den On-chip Temperatur sensor von Atmega328 in Betrieb 
zu nehmen. Die Werte wird per USART ausgegeben, die Werte werden aber 
nicht aktualisiert, ich muss jedes mal den RESET drucken damit ich die 
aktualisierte Werte sehe. External Capacitor ist auch mit Aref 
angeschlossen.

Die ADC Werte (0-1023) erhöhen sich schon wenn ich mein Finger auf den 
Chip lege oder puste, aber erst nur beim Resetten. Ich weiß nicht was 
ich falsch mache.

Hier ist mein code:
1
char value_buf[5]={0};
2
volatile uint16_t U16_adc_val=0;
3
volatile uint16_t U16_adcl=0;
4
volatile uint16_t U16_adch=0;
5
volatile char flag=0;
6
7
void init_adc()
8
{
9
  ADCSRA = ((1<<ADEN)  |          /*Enable ADC */
10
            (1<<ADSC)  |          /*Start ADC conversion*/
11
            (1<<ADIE)  |          /*Enable Interrupt on ADC conversion Complete*/
12
            (1<<ADATE) |          /*Enable Auto-Trigger*/
13
            (1<<ADPS2) |          /*Prescaler 64-->ADC_clk=16M/64*/
14
            (1<<ADPS1));
15
  ADMUX = ( (1<<REFS1) | (1<<REFS0)  | /* Internal Vref with external Capacitor. */
16
            (1<<MUX3));                /* Enable On chip Temperature Sensor */
17
}
18
19
20
int main()
21
{
22
    init_adc();
23
    usart_init(BAUD_VAL);
24
    sei();   
25
26
    while(1){
27
             sprintf(value_buf,"%d", U16_adc_val);
28
             USART_Tx_string(value_buf);
29
            _delay_ms(500);
30
    }
31
    return 0;
32
}
33
34
35
ISR(ADC_vect)
36
{
37
    cli();
38
    U16_adc_val = (uint16_t)(ADCH<<8);
39
    U16_adc_val |= (uint16_t)ADCL;
40
    sei();
41
}

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

In der ISR die beiden Zeilen
>    U16_adc_val = (uint16_t)(ADCH<<8);
>    U16_adc_val |= (uint16_t)ADCL;
vertauschen.

Nur am Rande:
- warum überhaupt die Trennung, kann man in C nicht gleich ADC oder ADCW 
oder so ähnlich nehmen?
- in der ISR sind cli und sei unnötig.

von Jürgen K. (Gast)


Lesenswert?


von Aa B. (aaab)


Lesenswert?

S. Landolt schrieb:
> In der ISR die beiden Zeilen
>>    U16_adc_val = (uint16_t)(ADCH<<8);
>>    U16_adc_val |= (uint16_t)ADCL;
> vertauschen.
Habe ich schonmal ausprobiert, aber da haben sich die Werte nicht 
geändert/erhöht.

> Nur am Rande:
> - warum überhaupt die Trennung, kann man in C nicht gleich ADC oder ADCW
> oder so ähnlich nehmen?
ADCW gibt es nicht, deshalb erst ADCH lesen und dann ADCL oder 
umgekehrt.
> - in der ISR sind cli und sei unnötig.
kann man schon weglassen. Wäre sinnvoll wenn ich noch eine ISR hätte, 
oder ein riesen function innerhalb der ISR.

von Aa B. (aaab)


Lesenswert?

Jürgen K. schrieb:
> Schau mal was im DB dazu steht:
> 
http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf#_OPENTOPIC_TOC_PROCESSING_d94e47538
>
> Versuchs demnach mal im Single Shot Mode. ;)
Ich habe schonmal die ADATE (free running mode) weggelassen und ADSC bit 
immer in ISR gesetzt (single shot), hat sich nichts geändert.

> Ausserdem sollte REF und MUX gesetzt sein bevor du die Wandlung
> startest:
> 
http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf#_OPENTOPIC_TOC_PROCESSING_d94e47271

Die Reihenfolge werde ich noch ändern und ausprobieren. liegt es 
wahrscheinlich daran.

von Äxl (geloescht) (Gast)


Lesenswert?

>> Nur am Rande:
>> - warum überhaupt die Trennung, kann man in C nicht gleich ADC oder ADCW
>> oder so ähnlich nehmen?
>ADCW gibt es nicht, deshalb erst ADCH lesen und dann ADCL oder
>umgekehrt.

http://www.avrfreaks.net/forum/adc-vs-adcw-read-acd-result-word

oder in deutsch, hier aus:
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
1
In beiden Fällen – also sowohl bei den Timern als auch beim ADC – werden vom C-Compiler 16-Bit Pseudo-Register zur Verfügung gestellt (z. B. TCNT1H/TCNT1L → TCNT1, ADCH/ADCL → =>ADC<= bzw. =>ADCW<= ), bei deren Verwendung der Compiler automatisch die richtige Zugriffsreihenfolge regelt. In C-Programmen sollten grundsätzlich diese 16-Bit-Register verwendet werden! Sollte trotzdem ein Zugriff auf ein Teilregister erforderlich sein, sind obige Angaben zu berücksichtigen.
2
...
3
ADC und ADCW sind unterschiedliche Bezeichner für das selbe Registerpaar. Üblicherweise kann man in C-Programmen ADC verwenden, was analog zu den anderen 16-Bit-Registern benannt ist. =>ADCW<= (ADC Word) existiert nur deshalb, weil die Headerdateien auch für Assembler vorgesehen sind und es bereits einen Assembler-Befehl namens adc gibt.


Äxl

von Aa B. (aaab)


Lesenswert?

Äxl (geloescht) schrieb:

> http://www.avrfreaks.net/forum/adc-vs-adcw-read-acd-result-word
>
> oder in deutsch, hier aus:
> https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
>
> [pre]

Ah cool Danke: :), dass wusste ich nicht. werde ich auf jeden fall 
ausprobieren.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

>> - in der ISR sind cli und sei unnötig.
> kann man schon weglassen. Wäre sinnvoll wenn ich noch eine
> ISR hätte, oder ein riesen function innerhalb der ISR.

cli wird implizit von der Hardware vor Eintritt in die ISR ausgeführt; 
sei erfolgt implizit durch den Befehl reti am Ende der ISR.

von M. K. (sylaina)


Lesenswert?

S. Landolt schrieb:
> cli wird implizit von der Hardware vor Eintritt in die ISR ausgeführt;
> sei erfolgt implizit durch den Befehl reti am Ende der ISR.

Seit wann denn das?

von S. Landolt (Gast)


Lesenswert?

Zwar hatte ich heute erst einen Kaffee, aber ...   Was ist an der 
Aussage falsch?

von Stefan F. (Gast)


Lesenswert?

> Seit wann denn das?

Vermutlich schon immer.

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Vermutlich schon immer.

Ganz sicher schon immer. Eine Freigabe der globalen Interrupts vor 
Verlassen der ISR kann zu unerwarteten Ergebnissen führen, wenn ein 
weiterer Interrupt genau auf diese Freigabe wartet. Dann wird die gerade 
laufende ISR nämlich an dieser Stelle unterbrochen. Natürlich kann das 
in Ausnahmefällen auch Sinn machen. Aber dann entweder gleich am Anfang 
der ISR oder auch mittendrin. Aber am Ende direkt vor den Pops ist das 
absoluter Blödsinn.

von batman (Gast)


Lesenswert?

Aa B. schrieb:
> S. Landolt schrieb:
>> In der ISR die beiden Zeilen
>>>    U16_adc_val = (uint16_t)(ADCH<<8);
>>>    U16_adc_val |= (uint16_t)ADCL;
>> vertauschen.
> Habe ich schonmal ausprobiert, aber da haben sich die Werte nicht
> geändert/erhöht.

Logisch, dann überschreibst du mit der 16 Bit-Zuweisung am Schluß wieder 
die vorher gesetzten unteren 8 Bit mit Null.

Einfach U16_adc_val = ADC und den Compiler machen lassen.

von Aa B. (aaab)


Lesenswert?

Vielen Dank für euer Hinweise, mein Programm war richtig, bis auf die 
Darstellung, also
1
U16_adc_val = ADCW;
 oder
1
 U16_adc_val = (uint16_t)ADCL;
2
U16_adc_val |= (uint16_t)(ADCH<<8);
. Was mich bisschen wundert ist, Raumtemperatur ist laut Thermometer 21 
C, aber ich sehe 334 immer in der Terminal Software (gtkterm), das 
heißt( (331/1024) *1,1V) = 358.7mV.

Jetzt, im DB steht 25 C entspricht 314mV
http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf#_OPENTOPIC_TOC_PROCESSING_d94e47538

Das heißt der Chip ist eigentlich heißer als Raum-Temperatur?

von Stefan F. (Gast)


Lesenswert?

> Das heißt der Chip ist eigentlich heißer als Raum-Temperatur?

Ja sicher doch. Er nimmt schließlich mehr elektrische Energie auf, als 
er wieder ab gibt. Die Differenz dazwischen ist Wärme.

von M. K. (sylaina)


Lesenswert?

Aa B. schrieb:
> Das heißt der Chip ist eigentlich heißer als Raum-Temperatur?

Pack den Taschenrechner aus und mach die Fehlerrechnung: Durch die 
einzelnen Messfehler kann hinten in der Tat ein Messfehler von über 30 
Grad rauskommen. Um zumindest einen Einpunkt-, besser Zweipunkt-, 
Kalibrierung kommt man bei der Nutzung des internen Sensors nicht drum 
rum meiner Meinung nach.

von Aa B. (aaab)


Lesenswert?

Stefan U. schrieb:
>> Das heißt der Chip ist eigentlich heißer als Raum-Temperatur?
>
> Ja sicher doch. Er nimmt schließlich mehr elektrische Energie auf, als
> er wieder ab gibt. Die Differenz dazwischen ist Wärme.

Ja stimmt, cool, dann macht das alles Sinn. :D

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Aa B. schrieb:
> Das heißt der Chip ist eigentlich heißer als Raum-Temperatur?

Ich setze den Sensor auch gerne ein.

Nach einer 2 Punkt Kalibrierung zeigt sich, bei meinen Arduinos, dass 
der Chip meist zwischen 3° und 10° wärmer ist, als die Umgebung.

Die Formeln und Werte aus dem Datenblatt kannste als Richtwert nehmen, 
aber die besten Ergebnisse bringt die 2 Punkt Kalibrierung.

von Jim M. (turboj)


Lesenswert?

Arduino F. schrieb:
> Nach einer 2 Punkt Kalibrierung zeigt sich, bei meinen Arduinos, dass
> der Chip meist zwischen 3° und 10° wärmer ist, als die Umgebung.

Das wäre der Erwartungswert bei Dauerbetrieb.

Man kann nahe an die Umgebung rankommen, wenn man den Chip lange tief 
schlafen lässt und nur so 1x pro Sekunde misst.

Allerdings müsste man auch den Oszillator runter fahren - und z.B. mit 
'nem Uhrenquarz arbeiten.

von Manfred (Gast)


Lesenswert?

Arduino F. schrieb:
> Ich setze den Sensor auch gerne ein.

Hast Du ein Stück Arduino-Code dazu oder kann man den gar mit AnalogRead 
abfragen? Ist mir noch nirgendwo begegnet, ich habe aber auch nicht 
danach gesucht.

von Einer K. (Gast)


Angehängte Dateien:

Lesenswert?

Manfred schrieb:
> oder kann man den gar mit AnalogRead
Leider nein.

Hier, im Anhang, findest meine Adc Lib mit ein paar Beispielen.
Unter anderem mit dem internen Sensor.

von Manfred (Gast)


Lesenswert?

Arduino F. schrieb:
>> oder kann man den gar mit AnalogRead
> Leider nein.
Schade.

> Hier, im Anhang, findest meine Adc Lib mit ein paar Beispielen.
> Unter anderem mit dem internen Sensor.

Danke! Sieht recht gewaltig aus, das alles für die Temperaturmessung 
einbinden zu müssen - kommt erstmal in die Sammlung.

von Einer K. (Gast)


Lesenswert?

Ach, das sieht nur so fett aus...
U.A. weil ich da versuche alle AVR Arduinos zu unterstützen.
Und ein paar Tinys gleich auch noch.

In der Praxis dampft der Kompiler/Optimizer das weitgehend ein.
z.B. die Methodenverkettung...
Die sieht im Quellcode fett aus.
Aber im Kompilat, so, als wären es Inline Funktionen.

Natürlich kannst du auch ohne die Lib, die Register direkt manipulieren.
Ist dann aber eben nicht so portabel/komfortabel.
Und du solltest dann wissen, was du tust. Also das Datenblatt an der 
Stelle auswändig gelernt haben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.