Raspberry Pi Pico: ADC richtig initialisieren
In der Einsteiger-Dokumentation für den Raspberry Pi Pico mit MicroPython wird ein ADC mit dem ADC-Kanal initialisiert:
# Variante mit der ADC-Kanal-Nummer 0 adc = machine.ADC(0)
Es gibt noch eine zweite Variante, wie sich ein ADC initialisieren lässt:
# Variante mit der GPIO-Nummer 26 adc = machine.ADC(26)
Der Unterschied ob die ADC-Instanz mit der ADC-Kanal-Nummer oder der GPIO-Nummer initialisiert wird, ergibt sich aus den unterschiedlichen Messwerten. Die Frage ist, was ist falsch und was ist richtig, und warum ist das so.
Die kurze Antwort ist, die Initialisierung über die ADC-Kanal-Nummern 0, 1, 2 und 3 führen zu falschen Messwerten.
Initialisierung mit ADC-Kanalnummer oder GPIO-Nummer?
Beim Mikrocontroller RP2040 des Raspberry Pi Pico besitzen die GPIOs nach einem Reset zunächst einen internen Pull-Down-Widerstand. Dieser liegt typischerweise im Bereich von 50 bis 80 kOhm.
Bei einer ADC-Messung würde dieser Pull-Down-Widerstand parallel zur angeschlossenen Messschaltung liegen. Bei einer hochohmigen Signalquelle würde das den Messwert beeinflussen. Das gilt es zu vermeiden.
- Bei der Initialisierung mit machine.ADC(0) wird die GPIO-Konfiguration unverändert übernommen und je nach vorheriger Konfiguration irgendein Ausgangszustand herrschen.
- Bei der Initialisierung mit machine.ADC(machine.Pin(26)) wird der GPIO in den für die ADC-Messung geeigneten High-Z-Zustand versetzt. Der interne Pull-Down-Widerstand beeinflusst die Messung dadurch nicht.
Empfehlung: Die ADC-Initialisierung sollte mit der GPIO-Nummer erfolgen und nicht mit der ADC-Kanal-Nummer.
Hinweis: Es gibt in der Praxis eigentlich nur einen Fall, wo man einen ADC mit der ADC-Kanal-Nummer initialisieren muss. Das ist beim internen Temperatursensor, der die ADC-Kanal-Nummer 4 hat.
ADC richtig initialisieren
Im Prinzip ist es sinnvoll, immer die GPIO-Nummer beim Initialisieren zu verwenden, um grobfalsche Messwerte zu vermeiden.
Folgende Initialisierungen verhalten sich identisch:
adc = machine.ADC(26)
adc = machine.ADC(machine.Pin(26))
adc = machine.ADC("GP26")
Weil gute Programmierung immer eindeutig ist, empfiehlt sich folgende Initialisierung:
adc = machine.ADC(machine.Pin(26, machine.Pin.IN, pull=None))
Bei dieser Initialisierung sieht man auf einen Blick, dass der GPIO als Eingang und ohne Pull-Down- oder Pull-Up-Widerstand als ADC initialisiert wird. Diese Zeile ist sozusagen unmissverständlich. Auf diese Weise wird der GPIO so eingestellt, wie er für den ADC sein muss.
Programmcode zum Experimentieren
Wer das ausprobieren möchte kann folgenden Programmcode verwenden. Damit man die ADC-Messungen nachvollziehen kann, wird hier mit dem ADC-Kanal 3 (GPIO 29) gemessen, weil der mit VSYS (Pin 39) über einen Spannungsteiler fest verdrahtet ist und man mit einem Messgerät nachmessen kann.
Für das Experiment braucht man nur einen Raspberry Pi Pico (ohne WLAN-Chip) ohne weitere Beschaltung.
import machine
import time
# Variante mit der ADC-Kanal-Nummer 3 (falsch)
adc_vsys = machine.ADC(3)
# Variante mit der GPIO 29 (richtig)
#adc_vsys = machine.ADC(29)
#adc_vsys = machine.ADC("GP29")
#adc_vsys = machine.ADC(machine.Pin(29))
# Variante mit definierter Abschaltung des Pull-Down-Widerstands
#adc_vsys = machine.ADC(machine.Pin(29, machine.Pin.IN, pull=None))
# ADC: VSYS messen
time.sleep(.1) # Wartezeit
raw_vsys = adc_vsys.read_u16()
# Spannung an 3V3 (Referenzspannung)
voltage_3v3 = 3.3
# Umrechnungsfaktor für VSYS
conversion_factor = voltage_3v3 / 65535 * 3
# Umrechnen
voltage_vsys = raw_vsys * conversion_factor
# Formatiert ausgeben
print('Spannung an VSYS (Pin 39 / GPIO 29):', "{:.2f}".format(voltage_vsys), 'Volt')
Warum ist nach der Initialisierung und damit vor der Messung eine Wartezeit?
Die Wartezeit hat nichts mit der Messung zu tun, sondern mit der ADC-Initialisierung. Die kann unter Umständen noch nicht vollständig abgeschlossen sein, wenn am ADC gemessen wird. Um falsche Werte zu vermeiden, ist nach der Initialsierung eine Wartezeit eingebaut, damit die vollständige abgeschlossen ist, wenn gemessen wird.
Was gibt es zu beachten!
Das Ergebnis der Berechnung von VSYS sollte so ungefähr mit dem Messergebnis übereinstimmen. Der Wert der Berechnung wird minimal größer sein, weil der interne ADC eine kürzere Leitung zu VSYS hat (im Vergleich zum Messgerät) und dadurch die Leitungsverluste geringer ausfallen.
Wenn die berechneten und gemessenen Werte stark abweichen?
Wenn an VBUS (USB) eine Spannung von 5,1 Volt anliegt, dann sollte die gemessene Spannung an VSYS bei ca. 4,8 bis 4,9 Volt liegen.
Je nach Stromversorgung, verwendeten Bauteilen und dem Aufbau können die berechneten und gemessenen Werte voneinander stark abweichen. Woran liegt das und was ist dann zu tun?
Der hier verwendete Programmcode hat einen Makel. Er geht nämlich davon aus, dass der Spannungsregler auf dem Board eine exakte Spannung von 3,3 Volt an 3V3 (Pin 36) liefert. Diese 3,3 Volt ist auch die Referenzspannung für den ADC und dieser Wert wird auch bei der Umrechnung im Programmcode verwendet.
Aber was, wenn die Spannung an 3V3 (Pin 36) nicht 3,3 Volt ist?
Dann errechnet der Programmcode eine falsche Spannung für VSYS.
Kann man das korrigieren?
Wie kann man das vermeiden. Ganz einfach. Man muss mindestens einmal die Spannung im laufenden Betrieb an 3V3 (Pin 36) messen und diesen Wert (z. B. 2.26) in de Programmcode eintragen, damit die gemessene Spannung an VSYS mit der berechneten Spannung ungefähr übereinstimmt.
Die Frage ist nur, ob sich der Wert nicht irgendwann verändert und die Umrechnung dann wieder falsch ist.
An der Stelle muss man berücksichtigen, dass die Ermittlung von VSYS Ungenauigkeiten aufweisen kann.
Weitere verwandte Themen:
- Raspberry Pi Pico: Grundlagen zu ADC (Analog-Digital-Converter)
- Raspberry Pi Pico: Experimente mit ADC
- Raspberry Pi Pico: VSYS mit ADC messen
- Raspberry Pi Pico W: VSYS mit ADC messen
- Raspberry Pi Pico: GPIO-Grundlagen
Elektronik-Sets für das Hardware-nahe Programmieren
Der Elektronik-Kompendium Club ist ein Online-Treffpunkt für Hobby-Elektroniker und Maker.
Wir wollen:
- Anregungen und Lösungen von echten Menschen bekommen
- Menschen zusammenbringen und gemeinsam wachsen
- Erfahrungen machen und teilen



