Analog-Digital-Wandler (ADC) erklärt: Arduino, ESP32, Pico
Was ist ein ADC und wie funktioniert er? Analog vs. digital, 10- und 12-Bit-Auflösung, analogReference, Umrechnung in Volt, ESP32-ADC2 und weniger Rauschen.
Ein ADC (Analog-Digital-Wandler) ist die Schaltung, die eine sich stetig ändernde Spannung an einem Pin in eine Zahl umwandelt, mit der der Mikrocontroller arbeiten kann. Jedes Mal, wenn du am Arduino analogRead() aufrufst, arbeitet dieser Wandler im Hintergrund: Der 10-Bit-ADC des Arduino Uno macht aus einer Spannung zwischen 0 und 5 V eine Zahl von 0 bis 1023, die 12-Bit-ADCs von ESP32 und Raspberry Pi Pico machen aus etwa 0–3,3 V eine Zahl von 0 bis 4095. Der ADC ist der Schlüssel, um alles mit einem analogen Ausgang auszulesen: Potentiometer, LDRs, Bodenfeuchtesensoren, Joysticks und Temperatursensoren.
In dieser Anleitung lernst du den Unterschied zwischen analogen und digitalen Signalen kennen, wie ein ADC eine Spannung Schritt für Schritt in eine Zahl umwandelt und wie Auflösung und Referenzspannung deine Messung beeinflussen. Mit echten Zahlen gehen wir die Formel zur Umrechnung eines Messwerts in Volt durch, ändern den Messbereich mit analogReference und schauen uns die Abtastrate sowie praktische Wege gegen Rauschen an. Außerdem behandeln wir den an den Rändern nicht linearen ADC des ESP32, den Konflikt zwischen ADC2 und WLAN sowie die Dämpfung (Attenuation), die Nutzung des ADC am Raspberry Pi Pico mit MicroPython und zum Schluss eine kurze Einführung in den DAC, der genau das Gegenteil macht.

Was ist der Unterschied zwischen analogen und digitalen Signalen?
Ein analoges Signal ist eine Größe, die innerhalb eines Bereichs unendlich viele Werte annehmen kann und sich zeitlich stetig ändert. Wenn die Spannung am mittleren Pin eines Potentiometers von 0 V auf 5 V steigt, durchläuft sie jeden Wert dazwischen, etwa 1,2 V, 1,21 V und 1,215 V; auch die Schallwelle eines Mikrofons, die temperaturabhängige Spannung eines Thermistors oder die langsam sinkende Spannung einer Batterie sind analog. Ein digitales Signal kennt dagegen nur bestimmte Pegel. In der Logik-Welt des Arduino sind es zwei: LOW (0) und HIGH (1). Beim Uno wertet ein digitaler Eingang alles unter etwa 1,5 V als LOW und alles über 3,0 V als HIGH; der Bereich dazwischen ist undefiniert. Deshalb kann digitalRead() bei einem Akku 3,7 V nicht von 4,2 V unterscheiden und meldet beide Male HIGH. Die Stärke digitaler Signale ist ihre Störfestigkeit: 4,6 V und 5,0 V bedeuten dasselbe HIGH. Um einen analogen Wert zu messen, zu speichern oder damit zu rechnen, musst du ihn zuerst in eine Zahl, also einen digitalen Wert, umwandeln, und genau das erledigt der ADC.
Was ist ein ADC und wie funktioniert er?
Die Arbeit eines ADC lässt sich in zwei Schritten zusammenfassen. Der erste ist das Abtasten: Im Moment der Messung kopiert der Wandler die Eingangsspannung auf einen kleinen Kondensator (Sample-and-Hold-Schaltung) und hält sie konstant, bis die Wandlung fertig ist; beim ATmega328P hat dieser Kondensator etwa 14 pF. Der zweite ist die Quantisierung: Die gehaltene Spannung wird auf die nächstgelegene Stufe einer Skala gerundet, die die Referenzspannung in gleich große Stufen teilt, und die Nummer dieser Stufe wird als Ergebnis ausgegeben. Die ADCs in Arduino Uno, ESP32 und Pico arbeiten alle nach dem Verfahren der sukzessiven Approximation (SAR, Successive Approximation Register). Ein SAR-ADC funktioniert wie ein Zahlenratespiel: Zuerst probiert er die halbe Referenzspannung, setzt das höchstwertige Bit auf 1, wenn der Eingang größer ist, und lässt es auf 0, wenn er kleiner ist; dann probiert er die Hälfte des verbleibenden Bereichs und wiederholt das für jedes Bit. So findet ein 10-Bit-ADC mit nur 10 Vergleichen die richtige von 1024 möglichen Stufen. Der Einfachheit halber zeigt die Tabelle, wie ein 4-Bit-ADC mit 5 V Referenz einen Eingang von 3,2 V misst:
| Schritt | Geprüftes Bit | Vergleichsspannung | Ist der Eingang (3,2 V) größer? | Ergebnisbits |
|---|---|---|---|---|
| 1 | Bit 3 (Wert 8) | 8 / 16 × 5 = 2,500 V | Ja → 1 | 1000 |
| 2 | Bit 2 (Wert 4) | 12 / 16 × 5 = 3,750 V | Nein → 0 | 1000 |
| 3 | Bit 1 (Wert 2) | 10 / 16 × 5 = 3,125 V | Ja → 1 | 1010 |
| 4 | Bit 0 (Wert 1) | 11 / 16 × 5 = 3,4375 V | Nein → 0 | 1010 |
| Ergebnis | Alle Bits geprüft | 1010 = 10 → 10 × 5 / 16 = 3,125 V | Fehler 0,075 V (eine Stufe = 0,3125 V) | 1010 |
Die Abweichung von 0,075 V im Ergebnis ist der Quantisierungsfehler, und kein ADC kommt um ihn herum: Liegt die echte Spannung zwischen zwei Stufen, kann der ADC nur eine davon melden. Der Fehler bleibt unter einer Stufe (LSB); je kleiner die Stufe, desto feiner die Messung. Weil sich der Sample-and-Hold-Kondensator bei jeder Messung aufladen muss, spielt auch der Widerstand der Quelle eine Rolle, die den ADC speist: Das Datenblatt des ATmega328P empfiehlt eine Quellimpedanz von etwa 10 kΩ oder weniger; ein hochohmigerer Spannungsteiler kann den Kondensator nicht rechtzeitig laden, und die Messwerte driften. Neben dem SAR-Typ in Mikrocontrollern gibt es weitere ADC-Arten. Sigma-Delta-ADCs sind langsam, aber sehr genau: Der in Wägeprojekten verwendete HX711 bietet 24 Bit, das per I2C angeschlossene ADS1115-Modul 16 Bit. Flash-ADCs nutzen für jede Stufe einen eigenen Komparator; sie sind extrem schnell und stecken zum Beispiel in Oszilloskopen.
ADC-Auflösung: Was bedeuten 10 Bit und 12 Bit?
Die Auflösung gibt an, in wie viele Stufen der ADC seinen Messbereich teilt. Ein N-Bit-ADC erzeugt 2^N Stufen: 10 Bit sind 1024 Stufen (0–1023), 12 Bit 4096 Stufen (0–4095) und 16 Bit 65.536 Stufen. Die Spannung einer Stufe heißt LSB (Least Significant Bit) und ergibt sich aus LSB = Vref / 2^N. Beim Arduino Uno sind das 5 V / 1024 = 4,88 mV, bei ESP32 und Pico 3,3 V / 4096 = 0,81 mV. Der Uno sieht also keine Änderungen unter 4,88 mV; mit einem LM35, der 10 mV/°C liefert, entspricht das einer Stufe von etwa 0,5 °C. Auflösung und Genauigkeit sind aber nicht dasselbe. Rauschen, Nichtlinearität und Referenzfehler machen einen Teil der Bits auf dem Papier wertlos. Das Maß dafür ist die effektive Anzahl der Bits (ENOB): Der ADC des RP2040 im Raspberry Pi Pico liefert ein 12-Bit-Ergebnis, laut Datenblatt liegt die effektive Bitzahl aber bei 8,7. Hier die ADCs der drei Boards im Vergleich:
| Eigenschaft | Arduino Uno R3 | ESP32 (WROOM-32) | Raspberry Pi Pico |
|---|---|---|---|
| ADC-Auflösung | 10 Bit (0–1023) | 12 Bit (0–4095) | 12 Bit (in MicroPython auf 0–65535 skaliert) |
| Analoge Eingänge | 6 (A0–A5; beim Nano A0–A7) | 18 Kanäle: 8 an ADC1, 10 an ADC2 | 3 Pins (GP26–GP28) + VSYS/3 (GP29) + Temperatursensor |
| Standard-Messbereich | 0–5 V | Etwa 0–3,1 V (11 dB Dämpfung) | 0–3,3 V (ADC_VREF) |
| Eine Stufe (LSB) | 4,88 mV | Etwa 0,8 mV | 0,81 mV |
| Referenzoptionen | DEFAULT (5 V), INTERNAL (1,1 V), EXTERNAL (AREF) | Dämpfung: 0, 2,5, 6 und 11 dB | Externe Referenz am Pin ADC_VREF |
| Abtastrate | Etwa 10.000 Messungen/s | 20 kHz – 2 MHz im Continuous-Modus (DMA) | 500.000 Messungen/s in Hardware |
| Hinweis zur Genauigkeit | Absoluter Fehler ±2 LSB | An den Rändern nicht linear, Kalibrierung nötig | ENOB 8,7 Bit, etwa 30 mV Offset |
| Analoger Ausgang (DAC) | Keiner (PWM wird genutzt) | 2 Kanäle, 8 Bit (GPIO 25 und 26) | Keiner (PWM wird genutzt) |
Formel: ADC-Wert in Spannung umrechnen
Die Zahl, die der ADC liefert, sagt für sich allein nichts aus; um sie in eine Spannung umzurechnen, brauchst du die Referenzspannung und die Anzahl der Stufen: Spannung = ADC-Wert × Vref / 2^N. Beim Arduino Uno heißt das V = Wert × 5,0 / 1024; liefert analogRead() also 512, liegen am Pin 512 × 5 / 1024 = 2,50 V an. Umgekehrt findest du mit Wert = V × 1024 / Vref heraus, welcher Zahl eine bestimmte Spannung entspricht: 3,3 V liest der Uno als etwa 675. In vielen Beispielen wird statt durch 1024 durch 1023 geteilt. Das Datenblatt des ATmega328P nennt die Formel ADC = Vin × 1024 / Vref; der größte Wert 1023 steht für eine Stufe unterhalb von Vref. Teilst du durch 1023, zeigt der oberste Wert genau 5,00 V, dafür verschieben sich alle Werte um etwa 0,1 %. Dieser Unterschied ist kleiner als der eigene Fehler des ADC von ±2 LSB, beides funktioniert also; wichtig ist, im Projekt einheitlich zu bleiben. Die eigentlich große Fehlerquelle ist Vref selbst: Der 5V-Pin eines per USB versorgten Uno liegt oft irgendwo zwischen 4,7 und 5,1 V, und 5,0 in der Formel verursacht dann bis zu 5 % Fehler. Miss für genaue Messungen deshalb den 5V-Pin mit einem Multimeter und trage den echten Wert in den Code ein. Auch der einzige analoge Eingang des ESP8266 (A0) hat 10 Bit; der Chip selbst misst 0–1 V, und der eingebaute Spannungsteiler auf Boards wie NodeMCU und Wemos D1 Mini erweitert den Bereich auf etwa 0–3,2 V.
| Board und Einstellung | Wertebereich | Umrechnung in Volt | Beispiel |
|---|---|---|---|
| Arduino Uno / Nano (DEFAULT, 5 V) | 0–1023 | V = Wert × 5,0 / 1024 | 768 → 3,75 V |
| Uno, analogReference(INTERNAL) | 0–1023 | V = Wert × 1,1 / 1024 | 512 → 0,55 V |
| ESP32 (11 dB) | 0–4095 | Kalibriert: analogReadMilliVolts() / 1000; grob: Wert × 3,3 / 4095 | 1650 mV → 1,65 V |
| Raspberry Pi Pico (read_u16) | 0–65535 | V = Wert × 3,3 / 65535 | 32768 → 1,65 V |
| ESP8266 NodeMCU / Wemos D1 Mini (A0) | 0–1023 | V = Wert × 3,2 / 1024 | 512 → 1,60 V |
Potentiometer anschließen: Arduino, ESP32 und Pico
| Potentiometer-Pin | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| Äußerer Pin 1 | 5V | 3V3 | 3V3(OUT) (Pin 36) |
| Mittlerer Pin (Signal) | A0 | GPIO 34 (ADC1_CH6) | GP26 / ADC0 (Pin 31) |
| Äußerer Pin 2 | GND | GND | AGND (Pin 33) oder GND |
| Optionaler Entstörkondensator | 100 nF zwischen A0 und GND | 100 nF zwischen GPIO 34 und GND | 100 nF zwischen GP26 und AGND |
Schritt für Schritt: deine erste ADC-Messung mit dem Arduino
- Schaltung aufbauen: Verbinde die äußeren Pins eines 10-kΩ-Potentiometers mit 5V und GND und den mittleren Pin mit A0.
- 5V-Pin messen: Miss mit dem Multimeter die Spannung zwischen 5V und GND und trage sie in die Konstante VREF im Code ein (z. B. 4.93).
- Code hochladen: Öffne den Sketch unten in der Arduino IDE, wähle Board und Port und lade ihn hoch.
- Seriellen Monitor öffnen: Stelle 9600 Baud ein und beobachte, wie sich der ADC-Wert beim Drehen zwischen 0 und 1023 ändert (Details in der Anleitung zum seriellen Monitor).
- Prüfen: Miss mit dem Multimeter zwischen A0 und GND und vergleiche mit der angezeigten Spannung; die Abweichung sollte bei etwa 10–20 mV bleiben.
1// Potansiyometreyi ADC ile okuma / Reading a potentiometer with the ADC
2// Kenar bacaklar 5V ve GND'ye, orta bacak A0'a / Outer legs to 5V and GND, wiper to A0
3const int POT_PIN = A0;
4const float VREF = 5.0; // 5V pininde ölçtüğün gerilim / voltage you measured on the 5V pin
5
6void setup() {
7 Serial.begin(9600);
8}
9
10void loop() {
11 int raw = analogRead(POT_PIN); // 0-1023 arası sayı / number between 0-1023
12 float volts = raw * VREF / 1024.0; // sayıyı volta çevir / convert the number to volts
13 int percent = map(raw, 0, 1023, 0, 100); // yüzdeye ölçekle / scale to percent
14
15 Serial.print(F("ADC: "));
16 Serial.print(raw);
17 Serial.print(F(" Gerilim / Voltage: "));
18 Serial.print(volts, 3);
19 Serial.print(F(" V Yuzde / Percent: "));
20 Serial.println(percent);
21 delay(200);
22}analogRead() schließt eine Messung in etwa 100 µs ab und liefert eine ganze Zahl zwischen 0 und 1023. Der Code rechnet diese Zahl zuerst mit der Formel in Volt und dann mit map() in Prozent um. Da map() mit Ganzzahlen rechnet, fällt der Nachkommaanteil weg; brauchst du ein Ergebnis mit Nachkommastellen, rechne selbst mit float. Es handelt sich um eine ratiometrische Messung: Weil Potentiometer und ADC an denselben 5 V hängen, ändert sich die Knopfstellung, also der ADC-Wert, nicht, selbst wenn die Versorgung auf 4,9 V sinkt; nur die berechnete Spannung ändert sich. Dasselbe gilt für Sensoren, die über einen Teiler gelesen werden, etwa LDRs und NTCs. Misst du dagegen die Spannung einer Batterie oder einen Sensor mit festem mV-Ausgang wie den LM35, geht der tatsächliche Wert von Vref direkt ins Ergebnis ein.
Referenzspannung und analogReference
Die Referenzspannung (Vref) ist der obere Endpunkt der ADC-Skala: Erreicht oder übersteigt die Eingangsspannung Vref, bleibt das Ergebnis beim Maximalwert (1023) stehen. Eine kleinere Vref verengt den Messbereich, macht aber jede Stufe kleiner, sodass du kleine Signale feiner misst. Beim Arduino Uno wählst du die Referenz mit der Funktion analogReference(). Mit INTERNAL wird Vref zu 1,1 V und eine Stufe schrumpft auf 1,07 mV; einen LM35 (10 mV/°C) liest du dann in Schritten von etwa 0,1 °C, kannst dafür aber nichts über 1,1 V, also 110 °C, messen. Die interne 1,1-V-Referenz selbst schwankt von Chip zu Chip zwischen 1,0 und 1,2 V, deshalb lohnt sich bei genauen Projekten eine einmalige Kalibrierung mit dem Multimeter. Die ersten Messungen nach einem Referenzwechsel können ungenau sein, wie auch die Arduino-Dokumentation erwähnt; es ist also eine gute Gewohnheit, nach dem Umschalten ein paar Werte zu verwerfen. Außerdem wirkt die Einstellung auf alle analogen Pins des Boards gleichzeitig. Die Optionen unterscheiden sich je nach Board:
| Option | Referenz | Boards | Wann verwenden? |
|---|---|---|---|
| DEFAULT | 5 V (3,3 V bei 3,3-V-Boards) | Uno, Nano, Mega, Leonardo | Sensoren, die ratiometrisch zur Versorgung sind, z. B. Potentiometer, LDR, Joystick |
| INTERNAL | 1,1 V (ATmega328P); 2,56 V beim Leonardo | Uno, Nano, Leonardo (nicht beim Mega) | Sensoren mit kleiner Spannung wie der LM35 |
| INTERNAL1V1 / INTERNAL2V56 | 1,1 V / 2,56 V | Nur Mega | Kleine Signale am Mega |
| EXTERNAL | Spannung am AREF-Pin (0–5 V) | Uno, Nano, Mega | Eigene Präzisionsreferenz nutzen (z. B. 2,5 V oder 4,096 V) |
| AR_INTERNAL | Etwa 1,43 V (interne Referenz des Chips) | Uno R4 Minima und WiFi | Kleine Signale am Uno R4 |
Abtastrate: Wie viele Messungen schafft ein ADC pro Sekunde?
Die Abtastrate gibt an, wie viele Messungen der ADC pro Sekunde durchführen kann. Beim Arduino Uno wird der ADC-Takt durch Teilen von 16 MHz durch 128 auf 125 kHz eingestellt, und eine Wandlung dauert 13 Takte; deshalb braucht analogRead() etwa 100 µs, und es sind höchstens rund 10.000 Messungen pro Sekunde möglich. Für langsam veränderliche Größen wie Temperatur, Licht oder Batteriespannung ist das mehr als genug; oft reichen schon 10 Messungen pro Sekunde. Bei schnellen Signalen kommt das Nyquist-Kriterium ins Spiel: Um ein Signal verlustfrei zu erfassen, musst du mindestens doppelt so schnell abtasten wie seine höchste Frequenz, in der Praxis bevorzugt man das 5- bis 10-Fache. Für 50-Hz-Netzbrummen brauchst du mindestens 100 Messungen/s, für Sprache bis 4 kHz mindestens 8.000 Messungen/s. Brauchst du am Uno schnellere Messungen, kannst du den ADC-Vorteiler verkleinern: Mit ADCSRA = (ADCSRA & 0xF8) | 0x04; in setup() wird der Vorteiler 16, der ADC-Takt steigt auf 1 MHz und analogRead() sinkt auf etwa 16 µs, auf Kosten von etwas Genauigkeit. Beim ESP32 erlauben einzelne analogRead()-Aufrufe Zehntausende Messungen pro Sekunde, und im Continuous-Modus mit DMA (in Arduino analogContinuous()) lässt sich eine Rate zwischen 20 kHz und 2 MHz wählen; dieser Modus funktioniert nur mit ADC1-Pins. Der ADC des Raspberry Pi Pico läuft mit einem eigenen 48-MHz-Takt, braucht pro Wandlung 96 Takte, also 2 µs, und erreicht 500.000 Messungen pro Sekunde; eine MicroPython-Schleife kommt da nicht mit, für volle Geschwindigkeit brauchst du das C-SDK und DMA.
ESP32-ADC: Nichtlinearität, ADC2-WLAN-Konflikt und Attenuation
Auf dem Papier misst der 12-Bit-ADC des ESP32 viermal feiner als der Uno, in der Praxis musst du aber auf drei Dinge achten. Erstens die Nichtlinearität: Nahe 0 V liest der ESP32-ADC bis etwa 100–150 mV nur 0, und am oberen Ende geht er bei 4095 in die Sättigung, bevor der Eingang 3,3 V erreicht; auch die Kurve dazwischen ist keine perfekte Gerade. Zweitens die Streuung der Referenz: Die interne Referenz des ESP32 beträgt laut Design 1100 mV, schwankt laut Espressif aber von Chip zu Chip zwischen 1000 und 1200 mV, was bei unkalibrierten Messungen einen Fehler von etwa ±9 % bedeutet. Darum schreibt Espressif bei der Produktion Kalibrierdaten in die eFuses der Chips. Die Arduino-Funktion analogReadMilliVolts() nutzt diese Daten, rechnet den Rohwert direkt in kalibrierte Millivolt um und ist meist deutlich genauer als analogRead() × 3,3 / 4095. Drittens die Dämpfung (Attenuation): Der ADC-Kern misst nur bis etwa 1 V, höhere Spannungen werden von einem einstellbaren Dämpfungsglied am Eingang verkleinert. Standard in Arduino sind 11 dB, womit Messungen bis etwa 3,1 V möglich sind, der von Espressif für diese Einstellung empfohlene genaue Bereich liegt aber bei 150–2450 mV. Bei kleinen Signalen verbessert eine geringere Dämpfung sowohl Genauigkeit als auch Auflösung:
| Dämpfung | Arduino-Konstante | Genauer Messbereich | Einsatz |
|---|---|---|---|
| 0 dB | ADC_0db | 100–950 mV | Kleine Signale, feinste Messung |
| 2,5 dB | ADC_2_5db | 100–1250 mV | Sensorausgänge um 1 V |
| 6 dB | ADC_6db | 150–1750 mV | Mittlere Signalpegel |
| 11 dB (Standard) | ADC_11db | 150–2450 mV (Messwerte reichen bis etwa 3,1 V) | Potentiometer und 0–3,3-V-Sensoren |
1// ESP32 ADC: ham değer ve kalibre milivolt / ESP32 ADC: raw value and calibrated millivolts
2// Potansiyometre: 3V3, GND ve orta bacak GPIO 34 / Pot: 3V3, GND and wiper to GPIO 34
3const int POT_PIN = 34; // ADC1_CH6, Wi-Fi açıkken de çalışır / ADC1_CH6, works with Wi-Fi on
4
5void setup() {
6 Serial.begin(115200);
7 analogReadResolution(12); // 0-4095 (varsayılan / default)
8 analogSetPinAttenuation(POT_PIN, ADC_11db); // yaklaşık 3,1 V'a kadar / up to about 3.1 V
9}
10
11void loop() {
12 uint32_t rawSum = 0;
13 uint32_t mvSum = 0;
14 for (int i = 0; i < 16; i++) { // 16 ölçümün ortalaması / average of 16 readings
15 rawSum += analogRead(POT_PIN); // ham ADC değeri / raw ADC value
16 mvSum += analogReadMilliVolts(POT_PIN); // eFuse kalibrasyonlu mV / eFuse-calibrated mV
17 }
18 float raw = rawSum / 16.0;
19 float naiveV = raw * 3.3 / 4095.0; // basit formül / naive formula
20 float calibratedV = mvSum / 16.0 / 1000.0; // kalibre edilmiş / calibrated
21
22 Serial.printf("Ham / Raw: %4.0f Formul / Formula: %.3f V Kalibre / Calibrated: %.3f V\n",
23 raw, naiveV, calibratedV);
24 delay(500);
25}Der Code zeigt zwei Ergebnisse nebeneinander: den mit der einfachen Formel umgerechneten Rohwert und den von analogReadMilliVolts() kalibrierten Wert. Drehst du das Potentiometer Richtung Anschlag, wird der Unterschied größer, und ganz unten, wo die Formel 0,000 V anzeigt, misst das Multimeter noch etwa 0,1 V. analogSetPinAttenuation() ändert die Dämpfung nur für einen Pin, analogSetAttenuation() für alle Pins. Der ESP32 rauscht deutlich stärker als der Uno, besonders während WLAN sendet; Espressif selbst empfiehlt einen 100-nF-Kondensator am Eingang und das Mitteln mehrerer Messungen, genau das macht der Mittelwert über 16 Messungen im Code. Neuere Chips wie ESP32-S3 und ESP32-C3 nutzen eine fortgeschrittenere Kalibrierung per Kurvenanpassung, aber Pinnummern und ADC2-Regeln unterscheiden sich je nach Modell, also wirf immer einen Blick auf die Pinbelegung deines Boards (Pinout-Tool). Wie du einen Teiler für Spannungen über 3,3 V baust, erklären wir in der Anleitung zum Spannungsteiler.
ADC am Raspberry Pi Pico (MicroPython)
Der Raspberry Pi Pico hat drei von außen nutzbare analoge Eingänge: GP26 (ADC0), GP27 (ADC1) und GP28 (ADC2). GP29 (ADC3) misst auf dem Board ein Drittel der Versorgungsspannung VSYS, und ADC4 ist mit dem internen Temperatursensor des Chips verbunden. Die MicroPython-Funktion read_u16() skaliert das 12-Bit-Ergebnis auf den Bereich 0–65535, damit derselbe Code auf verschiedenen Boards läuft, die echte Auflösung bleibt aber bei 4096 Stufen. Der RP2040 hat keine eigene Referenzspannung, er nutzt seine ADC-Versorgung als Referenz. Beim Pico wird diese Versorgung (ADC_VREF, Pin 35) aus dem Ausgang des 3,3-V-Schaltreglers (SMPS) gewonnen und über einen Widerstand von etwa 200 Ω gefiltert. Das Board-Datenblatt von Raspberry Pi nennt drei Folgen ganz offen: Die Genauigkeit der 3,3 V ist begrenzt, die Versorgung ist etwas verrauscht, und der Strom, den der ADC zieht, erzeugt einen Offset von etwa 30 mV. Die Abhilfen stehen im selben Dokument: GP23 auf HIGH setzen, um den Regler in den welligkeitsärmeren PWM-Modus zu schalten, einen ungenutzten ADC-Kanal mit AGND verbinden und dessen Messwert als Offset abziehen, und für deutlich bessere Genauigkeit eine 3,0-V-Referenz wie den LM4040 zwischen ADC_VREF und AGND schalten (der Messbereich wird dann 0–3,0 V). Außerdem hat der ADC des RP2040 bekanntermaßen kleine Sprünge (DNL-Fehler) bei den Werten 512, 1536, 2560 und 3584; das Mitteln mehrerer Messungen verringert ihre Wirkung. Beim Pico W ist GP23 für den Funkchip reserviert, dort wird der Reglermodus über WL_GPIO1 gesteuert; lösche auf einem Pico W also die GP23-Zeilen im folgenden Code.
1from machine import ADC, Pin
2import time
3
4pot = ADC(26) # GP26 = ADC0 (pin 31)
5chip_temp = ADC(4) # dahili sıcaklık sensörü / internal temperature sensor
6VREF = 3.3 # ADC_VREF; multimetreyle ölçüp düzelt / measure and correct with a multimeter
7
8# Yalnız Pico ve Pico 2 (W değil): SMPS PWM moduna, daha az gürültü / Plain Pico and Pico 2 only (not W): SMPS to PWM mode, less noise
9smps_mode = Pin(23, Pin.OUT)
10smps_mode.value(1)
11
12
13def read_average(adc, samples=16):
14 total = 0
15 for _ in range(samples):
16 total += adc.read_u16() # 0-65535 (12 bit ölçeklenmiş / 12-bit scaled)
17 return total / samples
18
19
20while True:
21 raw = read_average(pot)
22 volts = raw * VREF / 65535 # sayıyı volta çevir / convert the number to volts
23 t_volts = read_average(chip_temp) * VREF / 65535
24 temp_c = 27 - (t_volts - 0.706) / 0.001721 # RP2040 veri sayfası formülü / RP2040 datasheet formula
25 print("ADC: {:5d} {:.3f} V Yonga / Chip: {:.1f} C".format(int(raw), volts, temp_c))
26 time.sleep(0.5)Methoden gegen ADC-Rauschen
Selbst beim Messen einer konstanten Spannung ist es normal, dass der ADC-Wert um ein, zwei Stufen schwankt; Quantisierung, Welligkeit der Versorgung, Störungen über lange Leitungen und Motoren oder WLAN-Sendungen in der Nähe tragen dazu bei. Am Uno gilt ein Zappeln von ±1–2 Stufen als gesund; deutlich mehr deutet meist auf ein Problem in der Schaltung hin. Gegen Rauschen kannst du in Hardware und Software vorgehen:
- Kondensator ergänzen: Ein keramischer Kondensator mit 100 nF zwischen Analogpin und GND filtert schnelle Störungen und stellt bei hochohmigen Quellen Ladung für den Sample-and-Hold-Kondensator bereit.
- Leitungen kurz halten: Ist das Sensorkabel lang, verdrille Signal- und GND-Leitung; führe Motor- und Relaisleitungen weg von analogen Leitungen.
- Sauber erden: Der Rückstrom von Lasten mit hohem Strom wie Motoren, Relais und LED-Streifen darf nicht über die GND-Leitung des Sensors fließen; führe die Massen an einem Punkt zusammen (sternförmige Masseführung).
- Saubere Referenz nutzen: Die USB-Versorgung ist verrauscht; bei absoluten Spannungsmessungen liefert die interne Referenz oder ein externer Referenz-IC stabilere Ergebnisse.
- Nach Kanalwechsel erste Messung verwerfen: Der Multiplexer am ADC-Eingang kann Ladung vom vorherigen Kanal mitschleppen; liest du mehrere Pins nacheinander, verwirf an jedem Pin eine Messung.
- Mitteln: Der Mittelwert aus N Messungen verringert zufälliges Rauschen etwa um den Faktor √N; 16 Messungen senken das Rauschen auf ein Viertel.
- Oversampling: Summierst du 4^n Messungen und schiebst das Ergebnis um n Bit nach rechts, gewinnst du n zusätzliche Bit Auflösung; die Summe von 16 Messungen um 2 Bit verschoben macht aus den 10 Bit des Uno 12 Bit. Damit das klappt, braucht das Signal mindestens eine Stufe natürliches Rauschen.
- Median- und Exponentialfilter: Ein Medianfilter entfernt plötzliche Ausreißer durch Motoren, ein exponentieller gleitender Mittelwert (EMA) liefert mit sehr wenig Speicher eine glatte Kurve.
1// Ham, ortalama ve EMA filtreli ADC değerleri / Raw, averaged and EMA-filtered ADC values
2// Serial Plotter ile izle / Watch with the Serial Plotter
3const int SENSOR_PIN = A0;
4const float ALPHA = 0.1; // EMA katsayısı (0-1) / EMA coefficient (0-1)
5float ema = 0;
6
7void setup() {
8 Serial.begin(115200);
9 analogRead(SENSOR_PIN); // ilk okumayı at / discard the first reading
10 ema = analogRead(SENSOR_PIN); // filtreyi başlat / seed the filter
11}
12
13void loop() {
14 int raw = analogRead(SENSOR_PIN); // ham değer / raw value
15
16 long sum = 0;
17 for (int i = 0; i < 16; i++) { // 16 ölçüm topla / sum 16 readings
18 sum += analogRead(SENSOR_PIN);
19 }
20 float average = sum / 16.0; // ortalama (0-1023) / average (0-1023)
21
22 ema += ALPHA * (raw - ema); // üstel hareketli ortalama / exponential moving average
23
24 Serial.print(F("ham:"));
25 Serial.print(raw);
26 Serial.print(F(" ortalama:"));
27 Serial.print(average);
28 Serial.print(F(" ema:"));
29 Serial.println(ema);
30 delay(20);
31}Lädst du den Code hoch und öffnest den seriellen Plotter der Arduino IDE, siehst du drei Linien: Der Rohwert zittert, der Mittelwert aus 16 Messungen ist deutlich ruhiger, und der EMA ist die glatteste Kurve, reagiert aber etwas verzögert auf Änderungen. Der Koeffizient ALPHA liegt zwischen 0 und 1: 0,1 bedeutet, dass jede neue Messung mit 10 % ins Ergebnis eingeht und grob die letzten 10 Messungen wirken; erhöhst du ihn, reagiert der Filter schneller, rauscht aber stärker. Welcher Filter passt, hängt vom Signal ab; für eine langsam veränderliche Temperatur eignet sich ein kräftiger EMA, für einen Joystick, der schnell reagieren soll, ein kurzer Mittelwert. Gleitenden Mittelwert, Medianfilter und Hysterese vergleichen wir mit echten Sensorbeispielen in der Anleitung zum Filtern von Sensordaten.
Kurze Einführung in den DAC: von digital zu analog
Ein DAC (Digital-Analog-Wandler) macht das Gegenteil eines ADC: Er nimmt eine Zahl und erzeugt eine dazu proportionale Spannung. Schreibst du 0 in einen 8-Bit-DAC, bekommst du 0 V, bei 255 fast die Versorgungsspannung und bei 128 etwa die Hälfte. Die einfachsten DACs bestehen aus einem Widerstandsnetzwerk namens R-2R. Ein häufiges Missverständnis gleich vorweg: analogWrite() am Arduino Uno ist kein DAC, sondern erzeugt PWM; der Pin schaltet in Wahrheit schnell zwischen 0 V und 5 V hin und her. Für LED-Helligkeit und Motordrehzahl reicht das, brauchst du aber wirklich eine konstante Spannung, musst du den PWM-Ausgang mit einem RC-Tiefpass glätten; die Zeitkonstante des Filters berechnest du mit dem RC-Zeitkonstanten-Rechner. Und Boards mit echtem DAC: Der ESP32 hat an GPIO 25 und GPIO 26 zwei 8-Bit-DACs, die du mit dacWrite(pin, wert) ansprichst; ESP32-S3 und ESP32-C3 haben dagegen keinen DAC. Der Arduino Uno R4 besitzt an Pin A0 einen 12-Bit-DAC. Für Uno R3, Nano und Pico ist das per I2C angeschlossene 12-Bit-Modul MCP4725 der einfachste Weg. Mit einem DAC kannst du Töne erzeugen, Sinus- oder Dreiecksspannungen ausgeben und sogar den DAC-Ausgang mit einem ADC-Eingang verbinden, um den ADC mit bekannten Spannungen zu testen:
1// ESP32 DAC ile sinüs dalgası / Sine wave with the ESP32 DAC
2// Çıkış GPIO 25'te, osiloskopla izle / Output on GPIO 25, watch it with an oscilloscope
3const int DAC_PIN = 25; // DAC1 = GPIO 25 (DAC2 = GPIO 26)
4const int STEPS = 64; // bir periyottaki nokta sayısı / points per period
5uint8_t sineTable[STEPS];
6
7void setup() {
8 for (int i = 0; i < STEPS; i++) {
9 sineTable[i] = 128 + 127 * sin(2 * PI * i / STEPS); // 1-255 arası tablo / table between 1-255
10 }
11}
12
13void loop() {
14 for (int i = 0; i < STEPS; i++) {
15 dacWrite(DAC_PIN, sineTable[i]); // 0 → 0 V, 255 → yaklaşık 3,3 V / 0 → 0 V, 255 → about 3.3 V
16 delayMicroseconds(150); // yaklaşık 100 Hz / roughly 100 Hz
17 }
18}Projektideen mit dem ADC
- Digitales Voltmeter: Miss mit einem Spannungsteiler 0–25 V und zeige das Ergebnis auf einem LCD; die Schritte findest du in der Anleitung Arduino-Voltmeter bauen.
- Automatisches Nachtlicht: Lies die Spannung eines LDR und schalte die LEDs ein, wenn es dunkel wird.
- Intelligenter Blumentopf: Starte mit dem analogen Ausgang eines Bodenfeuchtesensors eine Pumpe, sobald die Erde trocken ist.
- Joystick-gesteuerter Roboter: Die zwei Achsen eines Joysticks sind zwei getrennte analoge Eingänge; wandle ihre Werte in Motordrehzahl und Richtung um.
- Strommesser: Lies die stromproportionale Spannung eines ACS712 und sieh, wie viel Strom ein Gerät zieht.
- Lautstärkeanzeige: Taste den analogen Ausgang eines KY-038-Schallsensors schnell ab und lass je nach Spitzenwert eine LED-Leiste leuchten.
- Akkuanzeige: Miss in einem batteriebetriebenen Projekt die Spannung und zeige die Restladung in Prozent auf einem Display.
Häufige Fehler und ihre Lösungen
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| Der Wert springt zufällig, obwohl nichts angeschlossen ist | Der Pin ist offen (floating) | Sensor anschließen; unbenutzte Pins nicht lesen oder auf GND ziehen |
| Der Wert bleibt bei 1023 (beim ESP32 bei 4095) hängen | Eingang liegt über der Referenz, oder INTERNAL ist gewählt | Referenz bzw. Dämpfung anpassen, hohe Spannung mit einem Teiler herunterteilen |
| Beim ESP32 liefert analogRead() mit aktivem WLAN 0 | Der Sensor hängt an einem ADC2-Pin | ADC1-Pins GPIO 32–39 verwenden |
| Der ESP32 zeigt bei kleinen Spannungen 0 und bei großen 4095 | Der ADC ist an den Rändern nicht linear | analogReadMilliVolts() nutzen, Signal im Bereich 150–2450 mV halten |
| Die berechnete Spannung weicht 3–5 % vom Multimeter ab | Vref ist nicht 5,00 V (USB-Versorgung) | 5V-Pin messen und in VREF eintragen oder einen Kalibrierfaktor ergänzen |
| Beim abwechselnden Lesen zweier Pins beeinflussen sich die Werte | Multiplexer und hohe Quellimpedanz | Erste Messung nach dem Wechsel verwerfen, Quelle unter 10 kΩ halten, 100 nF ergänzen |
| Die Werte springen, wenn ein Motor oder Relais läuft | Störungen auf der gemeinsamen GND-Leitung, Versorgung bricht ein | Lasten über eine eigene GND-Leitung führen, Kondensatoren und Medianfilter nutzen |
| Nach Anlegen einer Spannung an AREF stimmen die Messungen nicht mehr | AREF wurde ohne analogReference(EXTERNAL) benutzt | Zuerst EXTERNAL wählen oder AREF über einen 5-kΩ-Widerstand anschließen |
| Nach Wahl von INTERNAL steht das Potentiometer schon auf halbem Weg bei 1023 | Die 1,1-V-Referenz gilt für alle analogen Pins | Vor dem Lesen ratiometrischer Sensoren zurück auf DEFAULT und ein paar Werte verwerfen |
| Beim Pico ist der Wert selbst mit Eingang an GND größer als 0 | ADC-Offset und Rauschen auf ADC_VREF | Einen Kanal an AGND legen, Offset messen und abziehen; GP23 auf HIGH setzen |
Der ADC ist die Brücke zwischen der physischen Welt und deinem Code: Kennst du Auflösung, Referenzspannung und Abtastrate, weißt du auch, was jede Zahl auf dem Bildschirm bedeutet und wie sehr du ihr trauen kannst. Miss am Uno die Referenz sauber, nutze am ESP32 die ADC1-Pins und analogReadMilliVolts(), berücksichtige am Pico Offset und Rauschen und beruhige das Ergebnis anschließend mit Mittelwerten und Filtern. In der BlueGrays-App findest du Projekte, die auf analogen Messungen aufbauen, etwa Lichtstärke mit einem LDR messen, ein digitales Voltmeter mit LCD, Temperaturmessung mit einem NTC sowie Servo- und LED-Helligkeitssteuerung mit einem Potentiometer, jeweils Schritt für Schritt mit Schaltplänen und Code.
Häufige Fragen
Was ist ein ADC und wofür braucht man ihn?
Ein ADC (Analog-Digital-Wandler) ist die Schaltung, die die Spannung an einem Pin in eine Zahl umwandelt, die der Mikrocontroller verarbeiten kann. Man braucht ihn, um Bauteile mit analogem Ausgang wie Potentiometer, LDRs sowie Temperatur- und Feuchtesensoren auszulesen. Beim Arduino startet der Befehl analogRead() diesen Wandler.
Was ist der Unterschied zwischen analogen und digitalen Signalen?
Ein analoges Signal kann jeden Wert innerhalb eines Bereichs annehmen und ändert sich stetig, ein digitales Signal besteht nur aus bestimmten Pegeln, beim Arduino LOW und HIGH. digitalRead() sagt dir nur, ob ein Pin 0 oder 1 ist, analogRead() dagegen als Zahl, wie hoch die Spannung ist.
Warum liefert analogRead beim Arduino Werte von 0 bis 1023?
Der ADC des Arduino Uno hat 10 Bit und erzeugt 2^10 = 1024 verschiedene Stufen, die von 0 bis 1023 nummeriert sind. Der Wert 0 steht für 0 V, 1023 für eine Stufe unterhalb der Referenzspannung (meist 5 V). Die 12-Bit-ADCs von ESP32 und Pico liefern Werte von 0 bis 4095.
Wie rechnet man einen ADC-Wert in Volt um?
Nutze die Formel Spannung = ADC-Wert × Referenzspannung / Anzahl der Stufen. Beim Arduino Uno ist das V = Wert × 5,0 / 1024; beim ESP32 liefert analogReadMilliVolts() direkt kalibrierte Millivolt. Beim Pico gilt für den read_u16()-Wert aus MicroPython V = Wert × 3,3 / 65535.
Funktionieren die ADC2-Pins des ESP32 mit WLAN?
Nein. Beim ESP32 nutzt auch der WLAN-Treiber die ADC2-Einheit, deshalb lassen sich die ADC2-Pins (GPIO 0, 2, 4, 12–15, 25–27) bei aktivem WLAN nicht lesen. Schließe analoge Sensoren in WLAN-Projekten an die ADC1-Pins (GPIO 32–39) an.
Was ist ein DAC und worin unterscheidet er sich vom ADC?
Ein DAC (Digital-Analog-Wandler) macht das Gegenteil eines ADC: Er wandelt eine Zahl in eine Spannung um. Mit einem ADC misst man die Spannung eines Sensors, mit einem DAC erzeugt man eine Spannung, etwa für Töne oder Signale. Der Arduino Uno hat keinen DAC, analogWrite() erzeugt PWM; der ESP32 hat zwei 8-Bit-DACs an GPIO 25 und 26, der Uno R4 einen 12-Bit-DAC an A0.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Lichtstärke messen mit LDR
Willst du sehen, wie hell dein Zimmer ist, und zwar als Zahl? Der LDR, ein kleines lichtempfindliches Bauteil, misst das Umgebungslicht, und der Arduino schreibt den Wert jede halbe Sekunde auf deinen

Digitales Voltmeter mit LCD-Anzeige
Finde mit einem selbstgebauten Messgerät heraus, wie viel Spannung eine Batterie oder ein Netzteil liefert. Ein Teiler aus zwei Widerständen senkt hohe Spannungen auf ein Niveau, das die Platine lesen

Messung der Lichtintensität mit dem ESP32-LDR-Modul
Echtzeit-Anzeige des ADC-Rohwerts des LDR-Moduls und des anhand von Dunkel- und Hellreferenzwerten berechneten relativen Lichtwerts in Prozent im Serial Monitor. Dieser Prozentwert ist keine Lux-Messung. Vermittelt die Kalibrierungslogik des Moduls. Sollte idealerweise vor Projekt 10 durchgeführt werden, da es zur Festlegung des Schwellenwerts dient.

ESP32: LED-Helligkeit mit Potentiometer (Analog → PWM)
In diesem Projekt steuern wir die Helligkeit einer LED analog über ein Potentiometer. Der ADC-Pin des ESP32 liest die vom Potentiometer kommende Spannung von 0-3,3 V aus, woraufhin dieser Wert in ein PWM-Signal (Pulsweitenmodulation) umgewandelt und an die LED gesendet wird. So leuchtet die LED beim Drehen des Potentiometers stufenweise auf und erlischt wieder. Mit Arduino Core 3.0+ kann analogWrite() direkt verwendet werden; bei ESP32-S2/S3 ist die ADC-Auflösung auf 12 Bit festgelegt.

Temperaturmessung mit NTC und 2x16 Lcd Display
Miss die Umgebungstemperatur mit einem Sensor, der aussieht wie eine kleine Perle. Dieses Bauteil namens NTC lässt Strom umso leichter durch, je wärmer es wird; der Arduino liest diese Änderung, rechn

Servomotorbetrieb mit Potentiometer
Während du am Knopf des Potentiometers drehst, dreht sich der Arm des Servomotors einfach mit: Das eine Ende des Knopfes bedeutet null Grad, das andere eine halbe Umdrehung. Der Arduino liest die Stel

Led-Steuerung mit Joystick
Drück den kleinen Hebel des Joysticks ganz in eine Richtung, und die LED für diese Richtung leuchtet: Für rechts, links, oben und unten gibt es vier verschiedene Farben. Lässt du den Hebel los, spring

ESP32-Farbmischerlampe (3 Potentiometer + RGB-LED + OLED)
Eine intelligente Farbmischer-Lampe mit ESP32, die durch Drehen von drei Potentiometern die gewünschte Farbe mischt! Wenn Sie die Potentiometer für Rot, Grün und Blau drehen, ändert die RGB-LED mit gemeinsamer Kathode sofort ihre Farbe. Auf dem SSD1306-OLED-Display werden für jede Farbe Werte im Bereich von 0 bis 255, visuelle Füllbalken und der HEX-Webfarbcode (z. B. #FF8040) in Echtzeit angezeigt. Ein professionelles Mini-Farbstudio – vermittelt in einem einzigen Projekt Kenntnisse über die RG
Weitere Artikel
BlueGrays-App
Diese Schaltung Schritt für Schritt auf dem Handy nachbauen
Schaltplan, Code und Teileliste auf einem Bildschirm. Über 200 Arduino-, ESP32- und Pico-Projekte zum Nachbauen.
Mit dem Handy scannen
Richte die Kamera auf den Code, dann öffnet sich der App-Store deines Handys.
oder im Store öffnen

