Ich habe folgendes Problem. Ich wollte über den ADC einen
Temperatursensor auslesen. Mein ATMega habe ich so beschaltet, dass ich
über einen Spannungsteiler entweder VCC oder VCC/2 an AREF anliegen habe
(per Jumper einstellbar). Warum ich das gemacht habe ist erstmal
unerheblich.
An Kanal 7 des ADC habe ich ebenfalls einen Spannungsteiler worüber ich
feststellen kann ob die Referenzspannung VCC oder VCC/2 ist. Jenachdem
wie ich das eingestellt habe Berechne ich dann eben die Temperatur.
Nun zum Phänomen. Die Funktion zum auslesen der Temp. sieht so aus:
1
intget_temp(){
2
intvalue;
3
4
if(read_adc(7)<500){//REF = 5V
5
value=read_adc(6);
6
value-=265;// 0°C
7
return(value*30)/5;
8
}
9
else{//REF = 2,5V
10
value=read_adc(6);
11
value-=536;// 0°C
12
return(value*190)/64;
13
}
14
}
Für 21,7°C wird also 217 zurückgegeben damit ich eine Dezimalstelle
behalte.
Wenn ich nun die Referenzspannung auf 5V stelle gibt er mir z.B. 20,3°C
zurück. Stelle ich die Spannung auf 2,5V (also VCC/2) bekomme ich
24,1°C.
Gut habe ich gedacht, ist bestimmt die Ungenauigkeit vom ADC oder
Spannungsteiler, aber als ich dann die Funktion mit einem Delay versehen
habe gehts perfekt:
1
intget_temp(){
2
intvalue;
3
4
if(read_adc(7)<500){//REF = 5V
5
value=read_adc(6);
6
value-=265;// 0°C
7
return(value*30)/5;
8
}
9
else{//REF = 2,5V
10
_delay_ms(15);
11
_delay_ms(15);
12
_delay_ms(15);
13
_delay_ms(15);
14
value=read_adc(6);
15
value-=536;// 0°C
16
return(value*190)/64;
17
}
18
}
Das witzige ist, dass es nur bei VCC/2 auftritt nicht aber bei AREF=VCC.
Meine read_adc-Funktion sieht so aus
1
unsignedintread_adc(unsignedcharchannel)
2
{
3
unsignedchari;
4
unsignedintresult=0;//Initialisieren wichtig, da lokale Variablen
5
//nicht automatisch initialisiert werden und
6
//zufällige Werte haben. Sonst kann Quatsch rauskommen
Ok, kann ich mal machen, aber wieso verhält es sich dann unterschiedlich
bei 5V und 2,5V? Der ADC dürfte davon ja gar nichts merken. Zudem warte
ich ja auch immer brav bis er fertig ist. An Aref liegt dann auch
definitiv VCC/2 an.
Oder ist er mit nem Teiler von 128 zu langsam? Wohl kaum oder?
Achja hab gerade nur einmal geenabled und das ADC "aus" rausgeschmissen.
Nun sind die Werte noch schlimmer (noch höher). Bei 5V alles in Butter
sehr seltsam....
Hab bisher noch keine Probleme mit der Referenzspg gehabt, mir hat
bisher nur der Multiplexer Probleme bereitet. Also die DummyMessung
jedenfalls drinnen lassen. Ich initialisiere den ADC vor der Mailoop und
dreh ihn in den meisten Applikationen nicht ab. Zum Abfragen verwend'
ich dann dieses Macro:
Timmo H. wrote:
> ADMUX = channel; // Kanal waehlen> ADMUX |= (0<<REFS0); // externe Referenz nutzen
Mit Nullen verodern bringt nicht so furchtbar viel - Du wolltest
wahrscheinlich eher sowas schreiben:
ADMUX = channel & ~(1<<REFS0); // Kanalwahl und externe Referenz
Nur mal so am Rande...
Nach dem Umschalten der Kanäle muss man etwas warten, damit sich die
Eingangsschaltung des ADCs auf den neuen Wert einschwingen kann.
Dies gilt speziell, wenn man (bei den neueren Megas) den internen PGA
nutzt und/oder differenzielle Messungen macht. Aus dem Datenblatt:
"Special care should be taken when changing differential channels. Once
a differential channel has been selected, the gain stage may take as
much as 125 µs to stabilize to the new value."
Also ich habe das bei jeder Messung ADC an/aus wieder reingemacht und
das delay auch. Zusätzlich habe ich den Teiler auf 4 gestellt, doch nun
liegen die Werte bei 5V auch zu hoch (eine einzelne Messung hingegen
gibt gute Werte aus). Es scheint also an den schnell aufeinander
folgenden Messungen zweier Kanäle zu liegen:
1
intget_temp(){
2
intvalue;
3
4
if(read_adc(7)<500){//REF = 5V
5
value=read_adc(6);
6
value-=265;// 0°C
7
return(value*30)/5;
8
}
9
else{//REF = 2,5V
10
value=read_adc(6);
11
value-=536;// 0°C
12
return(value*190)/64;
13
}
14
}
Also erst Channel 7 und gleich darauf 6. Mit Delay wie gesagt kein
Problem.
>Mit Nullen verodern bringt nicht so furchtbar viel - Du wolltest>wahrscheinlich eher sowas schreiben:
...
Nee, ich hatte da vorher was anderes stehen. Das es nichts bringt weiß
ich. Ist aber schneller ne 1 gegen eine 0 zu tauschen...
>Nach einer Kanalumschaltung ist eine Dummymessung sinnvoll. Also einmal>messen, Wert verwerfen und richtige Messung starten.
Ja das mache ich doch jedes mal! Darum habe ich doch extra die
Kommentare dahinter
1
ADCSRA|=(1<<ADSC);// Dummy-ADC-Wandlung
2
while(ADCSRA&(1<<ADSC));// auf Abschluss der Konvertierung warten
3
4
5
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
6
for(i=0;i<4;i++)
7
{
8
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
9
while(ADCSRA&(1<<ADSC));// auf Abschluss der Konvertierung warten
> Mein ATMega habe ich so beschaltet, dass ich über einen> Spannungsteiler entweder VCC oder VCC/2 an AREF anliegen habe.
Wie hochohmig ist denn der Spannungsteiler?
Und wie sieht es mit einen Kondensator von 100nF von Aref nach GND aus?
>Wie hochohmig ist denn der Spannungsteiler?
Besteht aus zwei 10 kOhm Widerständen.
>Und wie sieht es mit einen Kondensator von 100nF von Aref nach GND aus?
Bei externer Referenz scheint der C auf VCC zu gehen. Zumindest haben
die das beim RN-Control auch gemacht und ich habe mir gedacht, dass die
schon wissen was sie tun (siehe C18 unten links)
http://www.roboternetz.de/wissen/images/c/c6/Rncontrol1.4schaltplan.gif
Mmh, kann es irgendwie am S&H liegen? Das beim Umschalten des Muxers der
Kondensator nicht so schnell entladen ist? Im Datenblatt konnte ich
nichts entsprechendes finden und wenn mal auf FreeRun stellt gehts doch
auch oder?
Wäre cool wenn jemand das bei sich mal testen könnte. Also erst einen
Kanal auslesen und direkt danach einen anderen und gucken ob die Werte
identisch mit denen sind, die man bekommt wenn man ihn "getrennt"
abfragt.
Beim Umschalten der AREF können Wartezeiten entstehen da der Kondensator
an AREF erstmal auf die gewählte Spannung umgeladen werden muß. Versuche
mal die AREF umzuschalten und gleich danach par µs Wartezeit einzulegen.
Dann sampelst du aber dieses mal ohne Wartezeiten.
Oder du entfernst mal zu Testzwecken den Kondensator an AREF
vollständig.
Gruß Hagen
So gesehen schalte ich AREF ja nie um. Das ding bleibt immer auf "0".
Die 2,5V liegen ja schon zig Minuten an AREF an. Von daher kann ich es
mir nicht vorstellen.
Das mit dem C-Entfernen wäre mal ne Idee.
Aber ich habe es ja auch nur zu Testzwecken auf meinem ATMega32. Später
mache ich ne neue Platine mit einem ATMega48 bzw. ATMega88. Da werde ich
den C von AREF auf GND legen, ich verstehe auch nicht ganz warum die das
beim RN-Control nicht so gemacht haben. Ich habs damals einfach ohne
überlegen nachgebaut.
So ich habe jetzt den Kondensator auf GND gesetzt anstatt auf VCC
gesetzt. Auf jeden Fall sind die Unterschiede nicht mehr so extrem. Aber
wenn ich bei AREF 5V einstelle messe ich einen Wert von 299. Stelle ich
ihn auf 2,5V messe ich 608. Also 2% mehr. Ist das normal? Laut
Multimeter macht der Spannungsteiler ziemlich genau VCC/2.
Vorher lagen die Werte (mit delay) ja viel näher aneinander. Wars also
beim RN-Control doch richtig, AREF mit nem 100nF auf VCC zu setzen?
Hi
>wenn ich bei AREF 5V einstelle messe ich einen Wert von 299. Stelle ich>ihn auf 2,5V messe ich 608. Also 2% mehr.
Da hat wohl jemand nicht so richtig in Mathe aufgepasst!
MfG Spess
Findst?
(5V/1024)*299 = 1,46V
(2,5V/1024)*608 = 1,484V
0,029V sind 2% von 1,46V. Daher habe ich fast 2% mehr.
Wer hatte jetzt in Mathe nicht aufgepasst?
Hi
Dann hättest du deine Rechnung gleich beifügen müssen. Deine Zahlen
waren 299 und 608. Und da lassen sich nun wirklich keine 2% erkennen.
Wenn du wirklich eine genaue Messung machen willst, dann sind
Betriebsspannung und Spannungsteiler nicht unbedingt die geeignete Wahl
für die Referenzspannung. Genauer sind auf jeden Fall die interne(n)
Referenzspannungen des AVR oder eine externe Referenzspannungsquelle.
MfG Spess
Ich nehme mal an, dass Deine 2,5V Referenz zu hochohmig ist. Wenn die
Referenz vor oder während der Messung einbricht, dann hat das einen zu
hohen (!) Meßwert zur Folge.
Dass Du mit dem Multimeter den "richtigen" Wert misst, muss nichts
bedeuten, ev. bricht die Spannung nur vor oder während der ADC-Messung
geringfügig ein.
Ändere zum Testen mal den Spannungsteiler von 10k/10k auf 1k/1k.
Im Datenblatt ist übrigens ein RREF (Reference Input Resistance) von
typisch 32kOhm angegeben. Was immer dieser Wert genau aussagen soll:
anscheinend kannst Du denADC-Ref-Eingang als nicht beliebig hochohmig
annehmen.
Viele Grüße, Stefan
Das es sich nicht um eine Spannung bei 608 handeln kann ist ja wohl
logisch. Naja Mitdenken ist wohl nicht deine Stärke...Warum sollte ich
hier einfachste Prozentrechnung vorrechnen? Weißt nicht wie das geht?
Es geht hier nunmal um ADC...
>Betriebsspannung und Spannungsteiler nicht unbedingt die geeignete Wahl>für die Referenzspannung. Genauer sind auf jeden Fall die interne(n)
Dann habe ich das Problem, dass meine Berechnung von der
Batteriespannung abhängt wenn ich eine feste Referenz nehme. Wenn ich
die tatsächliche Betriebsspannung als Referenz nehme wird die Temperatur
immer gleich bestimmt, da sich glücklicher Weise nicht die
Spannungsverhältnisse ändern.
Da alles am Ende mit Batterien laufen soll wird sich die Spannung im
Laufe mehrerer Monate schon erheblich ändern.
>Dann hättest du deine Rechnung gleich beifügen müssen. Deine Zahlen>waren 299 und 608. Und da lassen sich nun wirklich keine 2% erkennen.>Wenn du wirklich eine genaue Messung machen willst, dann sind>Betriebsspannung und Spannungsteiler nicht unbedingt die geeignete Wahl>für die Referenzspannung. Genauer sind auf jeden Fall die interne(n)>Referenzspannungen des AVR oder eine externe Referenzspannungsquelle.
Für eine Temperaturmessung ist eine exakte Referenzspannung überflüssig,
da nur die Differenzen des Spannungsteilers (Thermistor/Festwiderstand)
gemessen werden, die Referenzspannung kürzt sich in der Rechnung heraus.
Wichtig ist nur, dass der Temperatur-Spannungsteiler aus derselben
Spannungsquelle gespeist wird wie die Referenz des ADC.
Stefan
>Wichtig ist nur, dass der Temperatur-Spannungsteiler aus derselben>Spannungsquelle gespeist wird wie die Referenz des ADC.
Eben und genau das ist ja der Fall. Wenigstens einer versteht mich :-D
Wenn Du das Ganze per Batterie betreiben willst, dann würde ich von dem
Spannungsteiler an der Referenz komplett absehen. Zu hochohmig bereitet
Dir mehr Messfehler als Du damit gewinnst, zu niederohmig braucht zuviel
Strom.
Besser:
Messe die Temperatur mehrmals und bilde den Mittelwert.
Viele Grüße, Stefan
>Wenn Du das Ganze per Batterie betreiben willst, dann würde ich von dem>Spannungsteiler an der Referenz komplett absehen. Zu hochohmig bereitet>Dir mehr Messfehler als Du damit gewinnst, zu niederohmig braucht zuviel>Strom.
Problem ist, das ich dann an Genauigkeit verliere (Spannung zwischen 1,2
und 1,9V => -20°C-70°C). Wenn ich nen OPV vorschalte habe ich wieder
einen Verbraucher mehr.
>Messe die Temperatur mehrmals und bilde den Mittelwert.
Ich messe ja schon 4 mal in meiner read_adc (siehe erster Beitrag)
Oh sorry, Deine Mittelwertbildung habe ich übersehen (war ja auch ganz
unten im Posting ...).
Probier mal, den Mittelwert aus wesentlich mehr Messwerten zu bilden.
Die anschliessende Division durch die Anzahl der Messwerte ist übrigens
nicht unbedingt notwendig - wenn Du 64 mal misst, kannst Du die
Ergebnis-Addition auch als 16-Bit-Messwert interpretieren (zugegeben,
von einem sehr schlechten 16-Bit-Wandler).
Um die Genauigkeit zu steigern, halte ich die REF-Halbierung für
ungeeignet. Ev. ist es sinnvoller, den Festwiderstand im Spss-Teiler an
den interessierenden Temperaturbereich anzupassen: Wenn Dich der Bereich
-20 bis -70 Grad interessiert, dann lege den Spgs.Teiler dafür aus,
dafür bist du dann bei hohen Temperaturen nicht so genau.
Das dürfte mathematisch auf dasselbe herauslaufen wie die
REF-Halbierung.
Ggf. sind auch 2 Thermistoren eine Alternative - einer für niedrige und
einer für hohe Temperaturen - Nachteil: doppelter Abgleichaufwand.
Viele Grüße, Stefan
Eigentlich war das gar nicht das Problem. Am Anfang als der C noch gegen
VCC geschaltet war hatte ich nur ungenauigkeiten wenn ich bei AREF=2,5V
zwei verschiedene Kanäle schnell hintereinander auslese. Mit Pause waren
die Werte von AREF=5 und AREF=2,5 praktisch identisch. Dann habe ich mal
den C von AREF nach GND geschaltet und nun habe ich einen Offset drin.
Ich muss das eh noch alles neu machen, da ich jetzt nur auf meinem Board
mit dem ATMega32 Teste, später wirds ein ATMega48 oder wenn 4KB nicht
reichen ein 88er. Dennoch fand ich das Verhalten des ADC doch sehr
seltsam.
Ich werde mir deine Tipps auf jeden Fall mal zu Herzen nehmen.
Wahrscheinlich muss ich eh ein OPV verwenden, da ich noch nen Ducksensor
habe und ich ja nur den wichtigen Spannungsbereich (für 950 hPa-1150
hPa) messen will. Da muss ich mir wohl nen Subtrahierer basteln.
Ein weiteres Problem ist, das die Spannung des Ducksensors auch von der
VCC abhängig ist (MPX4115A). Daher bräuchte ich da wieder eine Konstante
Referenz, ggf. hol ich mir doch nen LM336 dazu. Das werde ich dann noch
sehen.
Der Ablauf meiner Wetterstation wollte ich so machen, dass ich so wenig
Strom wie möglich verbrauche. Ich habe an den Timer dafür einen
Uhrenquarz angeschlossen der die Echtzeituhr steuert. Jede Sekunde wird
ein Interrupt ausgelöst und weckt den AVR aus dem Sleep Modus und
aktualisiert die Zeit. Alle 5 Minuten werden die Sensoren abgefragt und
jede Stunde werden über das RFM12 die Daten an die Innenstation
übertragen und auf einer SD-Karte gespeichert. Bin ja gepannt ob das
alles so passt. Den Temperatursensor tausche ich ggf. auch noch gegen
einen LM335, dann spare ich mir den Kram mit der externen
Referenzspannung.