Hallo,
ich habe an den ADC-Eingang eines AtMega8 (AVR-P28 von Olimex) mit einen
Spannungsteiler einen Transitor als Temperatursensor angeschlossen
(siehe
http://de.wikipedia.org/w/index.php?title=Datei:NPN_Thermometer_Schaltung.svg&filetimestamp=20090330185439)
das auslesen funktioniert ganz gut, man sieht auch wie sich der Messwert
ändert, wenn man den Transistor erwärmt.
Allerdings liefert der ADC immer abwechslend einen plausiblen Messwert
(hier 42) und einmal 0. Dazwischen springt er immer hin und her. Lese
den ADC per Interrupt 5 mal pro Sekunde aus, Mittelung mache ich keine.
Liegt das an schlechter Verdrahtung am ADC-Pin (kann gut sein) oder hab
ich irgendwo den ADC falsch eingestellt? Orientiert habe ich mich am
Assembler-Tutorial
Viele Grüße,
Ludwig
Achtung zuerst ADCL dann ADCH lesen!
Beim Auslesen der ADC-Register ist zu beachten: Immer zuerst ADCL und
erst dann ADCH auslesen. Beim Zugriff auf ADCL wird das ADCH Register
gegenüber Veränderungen vom ADC gesperrt. Erst beim nächsten Auslesen
des ADCH-Registers wird diese Sperre wieder aufgehoben. Dadurch ist
sichergestellt, daß die Inhalte von ADCL und ADCH immer aus demselben
Wandlungsergebnis stammen, selbst wenn der ADC im Hintergrund
selbsttätig weiterwandelt. Das ADCH Register muss ausgelesen werden!
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC#Die_Ergebnisregister_ADCL_und_ADCH
Wenn ich ADCL zuerst auslese, und dann gleich verwerfe, ändert das
leider gar nichts. Sollte meiner Meinung auch keinen Unterschied machen,
da ich die Wandlung ja mit
1
sbi ADCSRA, ADSC
anstoße, dann mit
1
wait_adc:
2
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
3
rjmp wait_adc
warte, bis das Ergebnis da ist (also bis ADSC wieder gecleared ist) und
dann erst das Ergebnis mit
1
in temp2, adch
auslese.
Zur Erklärung: Ich möchte nur 8 Bit ausgeben. Deshalb ist auch ADLAR
gesetzt, und ADCL wird nicht ausgwertet, und wurde deshalb auch nicht
ausgelesen
Hi
>Danke, habe ich auch korrigiert! Leider wieder ohne das Problem zu lösen
Hat auch keinen Einfluss, da die Register nicht im 'loop' verwendet
werden.
Vielleicht solltest du doch mal deine Hardware überprüfen. Was sagt das
Multimeter am ADC-Pin?
MfG Spess
Mh, das hüpft recht munter zwischen 4,2V und 4,9V umher. Was mich aber
sehr wundert, ist das wenn ich den Pin offenlasse, der Wert auch hin und
her springt
Noch so ein Freak der unbedingt Assembler schreibt wo es nur wirklich
nicht sein muss.
Fällt doch schon fast unter Sado/Maso.
Naja es gibt auch Leute die von Hamburg nach München zu Fuß gehen, nur
weil es geht statt zu fahren......
Ludwig P. schrieb:> Problem gefunden! Wenn ich die LED nicht blinken lasse, springt auch der> ADC-Wert nicht.
Nicht das Problem, nur ein Symptom......
Die Ursache kennst du noch nicht. ==> weitersuchen
Es gibt ein Race Condition zwischen dem timer und dem ADC + LCD init.
Wenn der timer reinkommt bevor die initialisierung abgeschlossen ist,
kracht es.
Ein Fix könnte sein das "sei" direkt vor die (leere) mainloop zu
verschieben.
Ich denke, das auf den Olimex Board die Referenzspannung nicht
ausreichend stabilisiert ist (z.B. fehlt die Induktivität völlig). Und
da ich immer genau dann den ADC auslese, wenn ich die LED schalte nehme
ich an, dass das auch die Referenzspannung in Mitleidenschaft zieht. Auf
jeden Fall funktionierts jetzt einwandfrei
smoerre schrieb:> Es gibt ein Race Condition zwischen dem timer und dem ADC + LCD init.> Wenn der timer reinkommt bevor die initialisierung abgeschlossen ist,> kracht es.> Ein Fix könnte sein das "sei" direkt vor die (leere) mainloop zu> verschieben.
Woran man doch alles nicht denkt, ihr seit echt gut :-D
Ludwig P. schrieb:
...
> Und> da ich immer genau dann den ADC auslese, wenn ich die LED schalte nehme> ich an, dass das auch die Referenzspannung in Mitleidenschaft zieht. Auf> jeden Fall funktionierts jetzt einwandfrei>
Das sich das so stark auswirkt, hätte ich nicht gedacht. Siehe Seite 196
Punkt 4 im Datenblatt.
Analog Noise
Canceling Techniques
...
4. If any ADC [3..0] port pins are used as digital outputs, it is
essential that these do not switch while a conversion is in progress.
However, using the Two-wire Interface (ADC4 and ADC5) will only affect
the conversion on ADC4 and ADC5 and not the other ADC channels
Bernd_Stein
Ludwig P. schrieb:> out PORTC, led ;LED blinken lassen> com led
Damit invertierst Du alle Bits des PortC, was zur Folge hat, dass Du den
PullUp-Widerstand des ADC-Eingangs ein/ausschaltest. Dieser sorgt dann
für falsche Werte.
Bernd Stein schrieb:> Das sich das so stark auswirkt, hätte ich nicht gedacht.
Ich auch nicht. Aber das wirkt sich ja nicht so aus, die Ursache ist ja
der toggelnde interne PullUp.
...
Hannes Lux schrieb:> Ludwig P. schrieb:>> out PORTC, led ;LED blinken lassen>> com led>> Damit invertierst Du alle Bits des PortC, was zur Folge hat, dass Du den> PullUp-Widerstand des ADC-Eingangs ein/ausschaltest. Dieser sorgt dann> für falsche Werte.> ...>
Vielleicht habe ich es ja übersehen, irre mich oder versteh wieder mal
etwas nicht richtig. Aber um überhaupt einen ADC-Kanal nutzen zu können
muß dieser doch als Eingang geschaltet sein bzw. um den Pull-Up
einschalten zu können muß ich doch den Portpin als Eingang schalten
( DDRCx = 0 ) und dann den Portpin setzten ( PortCx = 1 ).
Wo geschieht dies im Programm ?
Habe nur gefunden, das der komplette PortC als Ausgang geschaltet wird.
main:
...
ldi temp1, 0xFF
out DDRC, temp1 ; Port C = Ausgang
Bernd_Stein
Bernd Stein schrieb:> Wo geschieht dies im Programm ?
out PORTC, led ;LED blinken lassen
com led ;invertiert das ganze Byte und damit beim nächsten mal
;den ganzen Port, also auch den ADC-Eingang...
>> Habe nur gefunden, das der komplette PortC als Ausgang geschaltet wird.
Das habe ich nun wieder übersehen, da ich nicht weiter gesucht hatte,
nachdem ich Obiges gesehen hatte. Aber das ist ja noch schlimmer, damit
hat der Sensor ja gar keine Chance, seine Analogspannung messen zu
lassen. Das Programm tut also genau das, was sein Autor programmiert
hat, auch wenn der Autor eigentlich was ganz Anderes programmieren
wollte.
Das Verwenden der Aliasnamen Temp1 bis Temp4 suggeriert mir, dass hier
unverstanden Teile des Tutorials kopiert wurden und diese dann mit
"Anfänger-Naivität" mit eigenem Code ergänzt wurden. Das ist ansich
nichts Falsches. Trotzdem wäre es sinnvoll, sich erstmal zum Thema "Bits
& Bytes" Gedanken zu machen. Ein Anlaufpunkt könnte Bitmanipulation
sein.
...
Hi
>Das habe ich nun wieder übersehen, da ich nicht weiter gesucht hatte,>nachdem ich Obiges gesehen hatte.
Nein, du hast schon Recht. Bei eingeschalteten ADC wird der ausgewählte
Kanal zum Eingang. Und dann greift der Pull-Up.
MfG Spess
spess53 schrieb:> Hi
...
>> Nein, du hast schon Recht. Bei eingeschalteten ADC wird der ausgewählte> Kanal zum Eingang. Und dann greift der Pull-Up.>
Ich habe vor kurzem aus dem Datenblatt des ADC des ATtiny26 eine
" Übersetzung " gemacht. Entweder habe ich dies überlesen, nicht richtig
verstanden, es steht dort nicht oder ich habe es schlicht weg wieder
vergessen. Könntest Du hier schreiben, auf welcher Seite dies beim
ATmega8 im Datenblatt steht ?
Nach dieser " Übersetzung " habe ich erstmal keine Lust alles im DB des
ATmega8 noch selber abzusuchen.
Wäre nett von Dir.
Bernd_Stein
Hi
>Nein, du hast schon Recht. Bei eingeschalteten ADC wird der ausgewählte>Kanal zum Eingang. Und dann greift der Pull-Up.
Also ich habe mir das noch mal genau angesehen und kurz getestet. Und
ich hatte Unrecht. Es wird nur der Analogeingang zugeschaltet.
Portausgang und Pull-Up bleiben je nach DDRx erhalten und verfälschen
das Ergebnis.
Passt auch zu seinen Ergebnissen. Bei der Schaltung aus dem Ausganspost
sollte die gemessene Spannung irgendwo zwischen 0,6 und 0,7V liegen und
nicht bei 4,xxV.
MfG Spess
spess53 schrieb:> Hi>> Diese Abhängigkeiten findet man unter I/O-Ports->Alternate Port> Funktions.>> MfG Spess>
Danke,
dort ist im Bild 25. Alternate Port Functions deutlich zu sehen das das
AIOxn-Signal direkt von den Eingangspin abgenommen wird und die andere
Seite wahrscheinlich direkt auf den Input MUX des ADCs geht ( Bild 90 ).
Somit erklärt sich ja auch sein Problem, da er ja den kompletten PortC
als Ausgang konfiguriert hat und diesen auch noch regelmäßig invertiert,
liest er natürlich das PINC0 immer mit ein, und dies ist ja mal High und
mal Low.
Bernd_Stein
Hi
>dort ist im Bild 25. Alternate Port Functions deutlich zu sehen das das>AIOxn-Signal direkt von den Eingangspin abgenommen wird und die andere>Seite wahrscheinlich direkt auf den Input MUX des ADCs geht ( Bild 90 ).
War mir schon klar. Ich war allerdings der (falschen) Meinung, das noch
andere Steuerungen des Ports überschrieben werden, wie es z.B. UART,TWI
... machen.
MfG Spess
Danke für die vielen Antworten.
ja ich habe Teile des Sourcecodes einfach aus dem Tutorial übernommen,
und obwohl ich dachte, dass ich ihn schon verstanden habe, habe ich ihn
dennoch nicht selbst geschrieben, und das rächt sich jetzt. Man muss
halt schon schaun, wie verschiedene Programmteile sich gegenseitig
beinflussen, vorallem in Assembler
Ludwig P. schrieb:> Man muss> halt schon schaun, wie verschiedene Programmteile sich gegenseitig> beinflussen, vorallem in Assembler
Dazu kommt noch, dass jeder ASM-Programmierer einen etwas anderen Stil
hat. Kopiert man nun die Routinen von verschiedenen Quellen oder Autoren
zusammen, dann wird es richtig haarig, dann gibt es Stilbruch...
Daher ist es meist besser, nur die Algorithmen zu verstehen und zu
übernehmen und seinen eigenen Code im eigenen Stil zu schreiben.
Zumindest bin ich damit bisher immer ganz gut zurechtgekommen. Die
Lernkurve ist zwar flacher, das erworbene Wissen aber solider.
Bit- & Bytebruch,
Hannes...