|
|
AVR-Tutorial: ADC
[Bearbeiten] Was macht der ADC?Wenn es darum geht, Spannungen zu messen, wird der Analog-/Digital-Wandler (kurz: A/D-Wandler) oder englisch Analog Digital Converter (ADC) benutzt. Er konvertiert eine elektrische Spannung in eine Digitalzahl. Prinzipiell wird dabei die Messspannung mit einer Referenzspannung verglichen. Die Zahl drückt daher das Verhältnis der Messspannung zu dieser Referenzspannung aus. Sie kann in gewohnter Weise von einem Mikrocontroller weiterverarbeitet werden. [Bearbeiten] Elektronische GrundlagenDie ADC-Versorgungsspannung (AVCC) darf maximal um +/-0,3V von der Versorgung des Digitalteils (VCC) abweichen, jedoch nicht 5,5V überschreiten. Die externe Referenzspannung VREF darf nicht kleiner als die im Datenblatt unter ADC Characteristics als VREFmin angegebene Spannung (z. B. ATmega8: 2V, ATmega644P: 1V) und nicht größer als AVCC sein. Die Spannungen an den Wandlereingängen müssen im Intervall GND ≤ VIN ≤ VREF liegen. Im Extremfall bedeutet dies: Sei VCC = 5,5V, folgt AVCC_max = VREF_max = VIN_max = 5,5V. Der Eingangswiderstand des ADC liegt in der Größenordnung von einigen Megaohm, so dass der ADC die Signalquelle praktisch nicht belastet. Desweiteren enthält der Mikrocontroller eine sog. Sample&Hold Schaltung. Dies ist wichtig, wenn sich während des Wandlungsvorgangs die Eingangsspannung verändert, da die AD-Wandlung eine bestimmte Zeit dauert. Die Sample&Hold-Stufe speichert zum Beginn der Wandlung die anliegende Spannung und hält sie während des Wandlungsvorgangs konstant. [Bearbeiten] Beschaltung des ADC-EingangsUm den ADC im Folgenden zu testen wird eine einfache Schaltung an den PC0-Pin des ATmega8 angeschlossen. Dies ist der ADC-Kanal 0. Bei anderen AVR-Typen liegt der entsprechende Eingang auf einem andern Pin, hier ist ein Blick ins Datenblatt angesagt. Der Wert des Potentiometers ist Dank des hohen Eingangswiderstandes des ADC ziemlich unkritisch. Es kann jedes Potentiometer von 1kΩ bis 1MΩ benutzt werden. Wenn andere Messgrößen gemessen werden sollen, so bedient man sich oft und gern des Prinzips des Spannungsteilers. Der Sensor ist ein veränderlicher Widerstand. Zusammen mit einem zweiten, konstanten Widerstand bekannter Größe wird ein Spannungsteiler aufgebaut. Aus der Variation der durch den variablen Spannungsteiler entstehenden Spannung kann auf den Messwert zurückgerechnet werden. Vcc ----------+ Vcc ---------+
| |
--- Sensor,
| | der seinen Widerstand
| | in Abhängigkeit der
--- Messgröße ändert
| |
+------- PC0 +-------- PC0
| |
Sensor, ---
der seinen Widerstand | |
in Abhängigkeit der | |
Messgröße ändert ---
| |
GND ---------+ GND --------+
Die Größe des zweiten Widerstandes im Spannungsteiler richtet sich nach dem Wertebereich, in welchem der Sensor seinen Wert ändert. Als Daumenregel kann man sagen, dass der Widerstand so gross sein sollte wie der Widerstand des Sensors in der Mitte des Messbereichs. Beispiel: Wenn ein Temperatursensor seinen Widerstand von 0..100 Grad von 2kΩ auf 5kΩ ändert, sollte der zweite Widerstand eine Grösse von etwa (2+5)/2 = 3,5kΩ haben. Aber egal wie immer man das auch macht, der entscheidende Punkt besteht darin, dass man seine Messgröße in eine veränderliche Spannung 'übersetzt' und mit dem ADC des Mega8 die Höhe dieser Spannung misst. Aus der Höhe der Spannung kann dann wieder in der Umkehrung auf die Messgröße zurückgerechnet werden. [Bearbeiten] Referenzspannung AREFDer ADC benötigt für seine Arbeit eine Referenzspannung. Dabei gibt es 2 Möglichkeiten:
Bei der Umstellung der Referenzspannung sind Wartezeiten zu beachten, bis die ADC-Hardware einsatzfähig ist (Datenblatt und [1]). [Bearbeiten] Interne ReferenzspannungMittels Konfigurationsregister können beim ATmega8 verschiedene Referenzspannungen eingestellt werden. Dies umfasst die Versorgungsspannung AVcc sowie eine vom AVR bereitgestellte Spannung von 2,56V (bzw. bei den neueren AVRs 1,1V, wie z. B. beim ATtiny13, ATmega48, 88, 168, ...). In beiden Fällen wird an den AREF-Pin des Prozessors ein Kondensator von 100nF als Minimalbeschaltung nach Masse angeschlossen, um die Spannung zu puffern/glätten. Es ist jedoch zu beachten, dass die interne Referenzspannung ca. +/-10% vom Nominalwert abweichen kann, vgl. dazu das Datenblatt Abschnitt ADC Characteristics VINT (z. B. ATmega8: 2,3-2,9V, ATmega324P: 2,33-2,79V bzw. 1,0-1,2V "Values are guidelines only."). Die typische Abweichung der internen Referenzspannung vom Sollwert bei einigen AVR-Controllern wird in dieser Testschaltung exemplarisch untersucht. [Bearbeiten] Externe ReferenzspannungWird eine externe Referenz verwendet, so wird diese an AREF angeschlossen. Aber aufgepasst! Wenn eine Referenz in Höhe der Versorgungsspannung benutzt werden soll, so ist es besser, dies über die interne Referenz zu tun. Außer bei anderen Spannungen als 5V bzw. 2,56V gibt es eigentlich keinen Grund, an AREF eine Spannungsquelle anzuschließen. In Standardanwendungen fährt man immer besser, wenn die interne Referenzspannung mit einem Kondensator an AREF benutzt wird. Die 10µH-Spule L1 kann man meist auch durch einen 47Ω-Widerstand ersetzen. [Bearbeiten] Ein paar ADC-GrundlagenDer ADC ist ein 10-Bit ADC, d.h. er liefert Messwerte im Bereich 0 bis 1023. Liegt am Eingangskanal 0V an, so liefert der ADC einen Wert von 0. Hat die Spannung am Eingangskanal die Referenzspannung erreicht (stimmt nicht ganz), so liefert der ADC einen Wert von 1023. Unterschreitet oder überschreitet die zu messende Spannung diese Grenzen, so liefert der ADC 0 bzw. 1023. Wird die Auflösung von 10 Bit nicht benötigt, so ist es möglich die Ausgabe durch ein Konfigurationsregister so einzuschränken, dass ein leichter Zugriff auf die 8 höchstwertigen Bits möglich ist. Wie bei vielen analogen Schaltungen, unterliegt auch der ADC einem Rauschen. Das bedeutet, dass man nicht davon ausgehen sollte, dass der ADC bei konstanter Eingangsspannung auch immer denselben konstanten Wert ausgibt. Ein "Zittern" der niederwertigsten 2 Bits ist durchaus nicht ungewöhnlich. Besonders hervorgehoben werden soll an dieser Stelle nochmals die Qualität der Referenzspannung. Diese Qualität geht in erheblichem Maße in die Qualität der Wandlergebnisse ein. Die Beschaltung von AREF mit einem Kondensator ist die absolut notwendige Mindestbeschaltung, um eine einigermaßen akzeptable Referenzspannung zu erhalten. Reicht dies nicht aus, so kann die Qualität einer Messung durch Oversampling erhöht werden. Dazu werden mehrere Messungen gemacht und deren Mittelwert gebildet. Oft interessiert auch der absolute Spannungspegel nicht. Im Beschaltungsbeispiel oben ist man normalerweise nicht direkt an der am Poti entstehenden Spannung interessiert. Viel mehr ist diese Spannung nur ein notwendiges Übel, um die Stellung des Potis zu bestimmen. In solchen Fällen kann die Poti-Beschaltung wie folgt abgewandelt werden: Hier wird AREF (bei interner Referenz) als vom µC gelieferte Spannung benutzt und vom Spannungsteiler bearbeitet wieder an den µC zur Messung zurückgegeben. Dies hat den Vorteil, dass der Spannungsteiler automatisch Spannungen bis zur Höhe der Referenzspannung ausgibt, ohne dass eine externe Spannung mit AREF abgeglichen werden müsste. Selbst Schwankungen in AREF wirken sich hier nicht mehr aus, da ja das Verhältnis der Spannungsteilerspannung zu AREF immer konstant bleibt (ratiometrische Messung). Und im Grunde bestimmt der ADC ja nur dieses Verhältnis. Wird diese Variante gewählt, so muss berücksichtigt werden, dass die Ausgangsspannung an AREF nicht allzusehr belastet wird. Der Spannungsteiler muss einen Gesamtwiderstand von deutlich über 10kΩ besitzen. Werte von 100kΩ oder höher sind anzustreben. Verwendet man anstatt AREF AVCC und schaltet auch die Referenzspannung auf AVCC um, ist die Belastung durch den Poti unkritisch, weil hier die Stromversorgung direkt zur Speisung verwendet wird. Ist hingegen die absolute Spannung von Interesse, so muss man darauf achten, dass ein ADC in digitalen Bereichen arbeitet (Quantisierung). An einem einfacheren Beispiel soll demonstriert werden was damit gemeint ist. Angenommen der ADC würde nur 5 Stufen auflösen können und AREF sei 5V: Volt Wert vom ADC 0 -+
| 0
1 -+
| 1
2 -+
| 2
3 -+
| 3
4 -+
| 4
5 -+
Ein ADC Wert von 0 bedeutet also keineswegs, dass die zu messende Spannung exakt den Wert 0 hat. Es bedeutet lediglich, dass die Messspannung irgendwo im Bereich von 0V bis 1V liegt. Sinngemäß bedeutet daher auch das Auftreten des Maximalwertes nicht, dass die Spannung exakt AREF beträgt, sondern lediglich, dass die Messspannung sich irgendwo im Bereich der letzten Stufe (also von 4V bis 5V) bewegt. [Bearbeiten] Umrechnung des ADC Wertes in eine SpannungDie Größe eines "Bereiches" bestimmt sich also zu
Der Messwert vom ADC rechnet sich dann wie folgt in eine Spannung um:
Wird der ADC also mit 10 Bit an 5 V betrieben, so lauten die Umrechnungen:
Wenn man genau hinsieht stellt man fest, dass sowohl die Referenzspannung als auch der Maximalwert Konstanten sind. D.h. der Quotient aus Referenzspannung und Maximalwert ist konstant. Somit muss nicht immer eine Addition und Division ausgeführt werden, sondern nur eine Multiplikation! Das spart viel Aufwand und Rechenzeit! Dabei kann sinnvollerweise Festkommaarithmetik zum Einsatz kommen. [Bearbeiten] KalibrierungHat man eine externe, genaue Referenzspannung zur Hand, dann kann ein Korrekturfaktor berechnet werden, mit dem die Werte des ADCs im Nachhinein korrigiert werden können. Dies geschieht normalerweise über eine sogenannte gain offset Korrektur an einer Geraden oder einer Parabel. In erster Näherung kann man auch die interne Referenzspannung um das Inverse des ermittelten Korrekturwertes verstellen, um einen genaueren bereits digitalisierten Wert zu bekommen. [Bearbeiten] Die Steuerregister des ADC[Bearbeiten] ADMUX
(*) Bei Atmega8 nur in der Gehäusebauform TQFP und MLF verfügbar, nicht in PDIP [Bearbeiten] ADCSRA
[Bearbeiten] Die Ergebnisregister ADCL und ADCHDa das Ergebnis des ADC ein 10 Bit Wert ist, passt dieser Wert naturgemäß nicht in ein einzelnes Register, das ja bekanntlich nur 8 Bit breit ist. Daher wird das Ergebnis in 2 Register ADCL und ADCH abgelegt. Von den 10 Ergebnisbits sind die niederwertigsten 8 im Register ADCL abgelegt und die noch fehlenden 2 Bits werden im Register ADCH an den niederwertigsten Bitpositionen gespeichert. ADCH ADCL
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
9 8 7 6 5 4 3 2 1 0
Diese Zuordnung kann aber auch geändert werden: Durch setzen des ADLAR Bits im ADMUX Register wird die Ausgabe geändert zu: ADCH ADCL
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
9 8 7 6 5 4 3 2 1 0
Dies ist besonders dann interessant, wenn das ADC Ergebnis als 8 Bit Zahl weiterverarbeitet werden soll. In diesem Fall stehen die 8 höchstwertigen Bits bereits verarbeitungsfertig im Register ADCH zur Verfügung. 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! [Bearbeiten] Beispiele[Bearbeiten] Ausgabe als ADC-WertDas folgende Programm liest in einer Schleife ständig den ADC aus und verschickt das Ergebnis im Klartext (ASCII) über die UART. Zur Verringerung des unvermeidlichen Rauschens werden 256 Messwerte herangezogen und deren Mittelwert als endgültiges Messergebnis gewertet. Dazu werden die einzelnen Messungen in den Registern temp2, temp3, temp4 als 24 Bit Zahl aufaddiert. Die Division durch 256 erfolgt dann ganz einfach dadurch, dass das Register temp2 verworfen wird und die Register temp3 und temp4 als 16 Bit Zahl aufgefasst werden. Eine Besonderheit ist noch, dass je nach dem Wert in temp2 die 16 Bit Zahl in temp3 und temp4 noch aufgerundet wird: Enthält temp2 einen Wert größer als 128, dann wird zur 16 Bit Zahl in temp3/temp4 noch 1 dazu addiert. In diesem Programm findet man oft die Konstruktion
Dabei handelt es sich um einen kleinen Trick. Um eine Konstante zu einem Register direkt addieren zu können bräuchte man einen Befehl ala addi (Add Immediate, Addiere Konstante), den der AVR aber nicht hat. Ebenso gibt es kein adci (Add with carry Immediate, Addiere Konstante mit Carry Flag). Man müsste also erst eine Konstante in ein Register laden und addieren. Das kostet aber Programmspeicher, Rechenzeit und man muss ein Register zusätzlich frei haben.
Hier greift man einfach zu dem Trick, dass eine Addition gleich der Subtraktion der negativen Werts ist. Also "addiere +1" ist gleich "subtrahiere -1". Dafür hat der AVR zwei Befehle, subi (Substract Immediate, Subtrahiere Konstante) und sbci (Substract Immediate with carry, Subtrahiere Konstante mit Carry Flag). Das folgende Programm ist für den ATmega8 geschrieben. Für moderne Nachfolgetypen wie den ATmega88 muss der Code angepasst werden ([2], AVR094: Replacing ATmega8 by ATmega88 (PDF)).
[Bearbeiten] Ausgabe als SpannungswertDas zweite Beispiel ist schon um einiges größer. Hier wird der gemittelte ADC-Wert in eine Spannung umgerechnet. Dazu wird Festkommaarithmetik verwendet. Die Daten sind in diesem Fall
-> Faktor = 4,8828125mV / 1mV = 4,8828125 Der Faktor wird dreimal mit 10 multipliziert und das Ergebnis auf 4883 gerundet. Die neue Auflösung wird dreimal durch 10 dividiert und beträgt 1μV. Der relative Fehler beträgt Dieser Fehler ist absolut vernachlässigbar. Nach der Multiplikation des ADC-Wertes mit 4883 liegt die gemessene Spannung in der Einheit μV vor. Vorsicht! Das ist nicht die reale Auflösung und Genauigkeit, nur rein mathematisch bedingt. Für maximale Genauigkeit sollte man die Versorgungsspannung AVCC, welche hier gleichzeitig als Referenzspannung dient, exakt messen, die Rechnung nachvollziehen und den Wert im Quelltext eintragen. Damit führt man eine einfach Einpunktkalibrierung durch. Da das Programm schon um einiges größer und komplexer ist, wurde es im Vergleich zur Vorgängerversion geändert. Die Multiplikation sowie die Umwandung der Zahl in einen ASCII-String sind als Unterprogramme geschrieben, dadurch erhält man wesentlich mehr Überblick im Hauptprogramm und die Wiederverwendung in anderen Programmen vereinfacht sich. Ausserdem wird der String im RAM gespeichert und nicht mehr in CPU-Registern. Die Berechung der einzelnen Ziffern erfolgt über ein Schleife, das ist kompakter und übersichtlicher.
Für alle, die es besonders eilig haben gibt es hier eine geschwindigkeitsoptimierte Version der Integer in ASCII Umwandlung. Zunächst wird keine Schleife verwendet sondern alle Stufen der Schleife direkt hingeschrieben. Das braucht zwar mehr Programmspeicher, ist aber schneller. Ausserdem wird abwechselnd subtrahiert und addiert, dadurch entfällt das immer wieder notwendige addieren nach dem Unterlauf. Zu guter Letzt werden die Berechnungen nur mit der minimal notwenigen Wortbreite durchgeführt. Am Anfang mit 32 Bit, dann nur noch mit 16 bzw. 8 Bit.
|