AD-Wandler, Vermeidung von Messfehlern
Wie hochohmig sind die ADC-Eingänge eines ATmega-Controllers?
Im Datenblatt des Mega32 kann man im Kapitel zum AD-Wandler lesen, dass
der Innenwiderstand eines Messobjekts nicht größer als 10
kΩ sein sollte. Tatsächlich hat ein AD-Eingang zwar einen
fast unendlichen Innenwiderstand. Man muss aber bedenken, dass beim
Sampeln eines Messwerts ein kleiner Kondensator von einigen Picofarad
geladen wird. Wenn immer wieder derselbe AD-Eingang gemessen wird und
die Spannung sich kaum ändert, gibt es keine Probleme mit einer
größeren Impedanz der Signalquelle. Anders sieht es aber
aus, wenn mehrere Kanäle mit unterschiedlichen Spannungen gemessen
werden sollen. Der Sampel-Kondensator muss dann jedesmal neu geladen
werden, was nur an niederohmigen Quellen vollständig gelingt.
Eine
typische Anwendung ist die Verwendung von Spannungsteilern. An den
AD-Eingängen könnten mehrere hochohmige Spannungsteiler
liegen. Die Software kann dann eine Bereichsumschaltung vornehmen.
Hochohmige Messquelle
Welcher Messfehler kann an einer zu hochohmigen Quelle entstehen? Dazu
wurde ein Testaufbau mit dem ES-M32 verwendet. ADC0 liegt über einen
Jumper an einem Poti auf dem Board. An ADC1 wurde ein hochohmiger
Spannungsteiler mit zweimal 1 MOhm angeschlossen. Die Spannung an ADC1
ist also 2,5 V, die an AC0 ist einstellbar.
Das
Testprogramm untersucht den Extremfall, dass beide Kanäle
abwechselnd in schneller Folge gemessen werden. Es kommt dann zu einem
Ladungstransport zwischen den Eingängen. Der Eingang ADC0
mit seinem 10-kΩ-Poti kat kein Problem damit, aber ADC1 mit dem
Innenwiderstand 500 kΩ des Spannungsteilers kann eine
Spannungsänderung erfahren.
'ATmega32, AD-Wandler
$regfile = "m32def.dat"
$crystal = 11059200
$hwstack = 16
$swstack = 32
$framesize = 32
Baud = 9600
Dim N As Integer
Dim U1 As Integer
Dim U2 As Integer
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcd = 16 * 2
Initlcd
Cls
Locate 1 , 1
Lcd "AD"
Config Adc = Single , Prescaler = 64 , Reference = Off
Start Adc
Waitms 1000
Do
For N = 1 To 1000
U1 = Getadc(0)
U2 = Getadc(1)
Next N
Cls
Locate 1 , 1
Lcd "ADC0"
Locate 1 , 8
Lcd "ADC1"
Locate 2 , 1
Lcd U1
Locate 2 , 8
Lcd U2
Waitms 1000
Loop
End
Messergebnisse:
1.
Der Jumper an ADC0 wird geöffnet. ADC1 zeigt konstant den Messwert
509. Der offene Eingang ADC0 wird mitgezogen und zeigt einen Messwert
von 505. Der Unterschied 509 zu theoretischen 512 ist auf die Toleranz
der Widerstände zurückzuführen. Das zeigt ein
Vertauschen der beiden Widerstände mit dem neuen Messwert 513.
2.
Der Jumper wird geschlossen, an ADC0 liegt also das 10-kΩ-Poti.
Stellt man 0 V ein, sinkt der Messwert an ADC1 auf 495. Bei 5 V an ADC0
wird ADC1 auf 524 gezogen. Der Messfehler beträgt bis zu 2,5 %.
3.
Der AD-Wandler wird mit einem Vorteiler von 128 langsamer
betrieben. Der Sample-Kondensator hat damit mehr Zeit, sich auf die
volle Spannung aufzuladen. ADC1 zeigt zwischen 506 und 512. Der
Messfehler ist nur noch 0,6 %.
Config Adc = Single , Prescaler = 128 , Reference = Off
4.
Jeder Kanal wird zweimal hintereinander gemessen. Der Messwert an ADC1
wird nun nur noch zwischen 508 und 509 verändert. Der Messfehler
sinkt auf unter 0,1 %.
For N = 1 To 1000
U1 = Getadc(0)
U1 = Getadc(0)
U2 = Getadc(1)
U2 = Getadc(1)
Next N
Strom über die Schutzdioden
Bei
älteren AD-Wandlern musste man unbedingt vermeiden, dass einer der
nicht benutzten Nachbarkanäle außerhalb der erlaubten
Messspannung lag. Wenn eine der Eingangs-Schutzdioden in den leitenden
Zustand ging, kam es zu einer Ladungsübertragung auf den Messkanal
und damit zu einer starken Verfälschung. Trifft dieses Verhalten
auch auf den AD-Wandler im Mega32 zu? Dazu wurde der Kanal ADC2
gequält.
Ergebnis:
Es tritt keine Beeinflussung durch den Nachbarkanal auf. Der
Fehlerstrom wurde bis auf 50 mA erhöht, ohne dass sich der Messwer
am hochohmigen Spannungsteiler änderte.
Siehe auch: Tipps zum AD-Wandler in ELEXS
Hinweise zum AD-Wandler von Andre Bryx
Es
ist für die effiziente Berechnung der AD-Ergebnisse nicht sehr vorteilhaft,
diese direkt in einer Single-Variable zu berechnen.
Fließkommaoperationen behindern die Ausführungsgeschwindigkeit und
verbrauchen zu viele Ressourcen.
Ich persönlich rechne immer in
Milllivolt und NUR wen ich auch wirklich Bildschirm oder
Display-Ausgaben benutze, kann ich den Wert noch in eine entsprechende
Variable übergeben. Die korrekte Berechnungsformel lautet
WERT
= AD * VREF / 2^10
Wenn VREF angenommen 2,56 Volt sind, erhält man einen
Fixwert von VREF/1024 (eine Fließkomma-Rechenoperation gespart) = 0,0025.
Da ich in mV rechnen will, nehme ich als als VREF Fixwert 2,5mV, woraus
sich dann eine ganz einfache Operation in Ganzzahlen ergibt:
WERT = AD*250
um den Wert in mV zu erhalten.
Der Code
wird verschlankt, die Ressourcen geschont und das Programm wird sich
bedanken.
Genauer wird die Ausgabe, wenn man den AD-Wandler im Free-Mode
betreibt, welchen BASCOM aber nicht unterstützt (Außer bei Config ADC)!!
Hierzu muss man den ADC-Interrupt einsetzen und die AD-Ergebnisse direkt
aus den Registern lesen.
Zu den
Ausführungen zur VREF-Quelle muss ich noch sagen, das die interne
Bandgap-Referenz zwar nicht immer hypergenau ist, dafür aber extrem stabil
und rauschfrei ist (wenn man an AREF einen Keramik-C gegen Masse und ein
L in die Versorgung AVCC legt). Die Versorgung von VREF über einen 7805
bringt viel zu viel Rauschen ins System, dann lieber einen LTC 1021 als
Superreferenz. Aber das ist eine ganz andere Geschichte :-)
Elektronik-Labor Projekte AVR