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
charvalue_buf[5]={0};
2
volatileuint16_tU16_adc_val=0;
3
volatileuint16_tU16_adcl=0;
4
volatileuint16_tU16_adch=0;
5
volatilecharflag=0;
6
7
voidinit_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 */
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.
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.
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.
>> - 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.
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?
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.
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.
> 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.
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.
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
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.
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.
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.
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.
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.
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.