Wie voll ist der Akku im Wohnmobil? Läuft die Solaranlage? Ist das Netzteil eingebrochen? Fragen dieser Art beantwortet der AD-Wandler im Mikrocontroller. Er verwandelt eine Spannung am Pin in eine Zahl. Allerdings misst er höchstens bis zu seiner Referenzspannung, beim Arduino Uno also 5 V oder weniger, beim ESP32 rund 2,5 V. Für größere Spannungen schaltest du einen Spannungsteiler davor.
Hier baust du eine Messung für einen 12-V-Bleiakku, der beim Laden bis knapp 15 V erreicht. Das Ergebnis soll auf etwa 0,1 V genau sein, unabhängig davon, ob der Arduino gerade am USB-Kabel hängt oder an einem schwachen Netzteil.
Schaltplan
- R1, 150 kΩ, und R2, 10 kΩ: der Spannungsteiler. Er teilt die Akkuspannung durch 16.
- C1, 100 nF: ein Keramikkondensator direkt am ADC-Pin. Er glättet Störungen und liefert dem Wandler beim Abtasten die Ladung.
- IC1, ATmega328P: ADC0 ist Pin 23, auf dem Uno als A0 beschriftet.
- C2, 100 nF an AREF: stabilisiert die interne Referenzspannung, die der Chip an diesem Pin ausgibt.
- Masse: Der Minuspol des Akkus und GND des Arduino sind verbunden.
So funktioniert die Schaltung
Der Wandler des ATmega328P vergleicht die Spannung am Pin mit einer Referenz und liefert eine Zahl von 0 bis 1023:
Als Referenz kann er AVCC nehmen, also die Versorgung, oder eine interne Bandgap-Referenz von 1,1 V. Die Versorgung ist bequem, aber ungenau: Am USB-Anschluss liegen je nach Kabel und Rechner 4,75 bis 5,25 V. Misst du gegen sie, wandert dein Ergebnis um bis zu 5 % mit, ohne dass sich am Akku etwas ändert. Die interne Referenz hängt nicht von der Versorgung ab. Sie ist von Exemplar zu Exemplar verschieden (1,0 bis 1,2 V laut Datenblatt), bleibt aber für ein Exemplar sehr stabil. Einmal kalibriert, misst du damit genauer als gegen die Versorgung.
Der Teiler bringt die Akkuspannung in diesen kleinen Bereich. Wie er arbeitet, steht unter Spannungsteiler. Ein Nebeneffekt ist praktisch: Weil R1 so groß ist, schützt er den Pin. Selbst 60 V am Eingang ergeben am Pin nur 3,75 V.
Dimensionierung
1. Teilerverhältnis. Die höchste zu messende Spannung, hier 15 V, soll knapp unter 1,1 V landen, mit etwas Reserve:
15 V ergeben am Pin 0,94 V; das Ende des Messbereichs liegt bei 1,1 V · 16 = 17,6 V.
2. Innenwiderstand. Das Datenblatt empfiehlt höchstens 10 kΩ Quellwiderstand am ADC-Pin. Der Teiler wirkt wie eine Quelle mit R1 ∥ R2 = 150 kΩ · 10 kΩ / 160 kΩ ≈ 9,4 kΩ – passt. Größere Widerstände würden weniger Strom ziehen, aber dann muss C1 allein die Abtastladung liefern, und Leckströme verfälschen die Messung. Mit C1 ergibt sich eine Zeitkonstante von 9,4 kΩ · 100 nF ≈ 0,94 ms; für einen Akku ist das beliebig schnell.
3. Auflösung. Ein Schritt des Wandlers entspricht am Pin 1,1 V / 1024 ≈ 1,07 mV und am Akku dem 16-Fachen, also 17 mV.
ADC-Auflösung und Messbereich
- ADC-Wert
- 1.489
- Hexadezimal
- 0x5D1
- 1 LSB
- 806 µV
- Stufe beginnt bei
- 1,1996 V
- Rest in der Stufe
- 366 µV
- Stufen
- 4.096
1 LSB = Uref / 2n, Code = ⌊U / LSB⌋ – so rechnen die meisten Datenblätter (z. B. AVR, STM32). Der größte Code 4.095 steht schon bei Uref − 1 LSB; Uref selbst wird nie erreicht. Wer durch 2n − 1 teilt, liegt um weniger als 1 LSB daneben. Ideale Kennlinie ohne Offset-, Verstärkungs- und Linearitätsfehler; wie genau die Referenz ist, bestimmt die Genauigkeit meist stärker als die Bitzahl.
4. Ruhestrom. Der Teiler belastet den Akku dauerhaft mit 15 V / 160 kΩ ≈ 94 µA, rund 2,3 mAh am Tag. Bei einem 60-Ah-Akku spielt das keine Rolle; bei kleinen Akkus schaltest du den Teiler mit einem Transistor ab.
5. Genauigkeit. Widerstände mit 1 % Toleranz verschieben das Teilerverhältnis um höchstens etwa 1,9 %, die Referenz streut um ±9 %. Beides zusammen ist ein fester Faktor, den du einmal mit einem Multimeter bestimmst: Akkuspannung messen, Anzeige des Arduino ablesen, Verhältnis als Korrekturfaktor ins Programm schreiben. Danach bleiben Rauschen und Temperaturdrift, zusammen typisch unter 1 %. Wie sich solche Fehler addieren, erklärt Messfehler.
Code
const float TEILER = 16.0; // (R1 + R2) / R2
const float KAL = 1.000; // nach Abgleich mit dem Multimeter anpassen
void setup() {
analogReference(INTERNAL); // 1,1-V-Referenz
analogRead(A0); // erste Messung nach dem Umschalten verwerfen
delay(10);
Serial.begin(9600);
}
void loop() {
long summe = 0;
for (int i = 0; i < 16; i++) summe += analogRead(A0); // 16-fach mitteln
float u = summe / 16.0 * 1.1 / 1024.0 * TEILER * KAL;
Serial.print(u, 2);
Serial.println(" V");
delay(1000);
}
Das Mitteln über 16 Messungen glättet das Rauschen; die Auflösung von 17 mV bleibt, aber die letzte Stelle springt nicht mehr.
Bauteilliste
| Bezeichner | Wert/Typ | Hinweis |
|---|---|---|
| R1 | 150 kΩ, 1 %, Metallschicht | ESP32: 56 kΩ |
| R2 | 10 kΩ, 1 %, Metallschicht | |
| C1 | 100 nF, X7R | direkt an Pin 23 |
| C2 | 100 nF, X7R | an AREF (Pin 21) |
| IC1 | ATmega328P (Arduino Uno) | A0 = ADC0 = Pin 23 |
Varianten
ESP32. Der Wandler hat nominell 12 Bit, aber drei Eigenheiten. Erstens misst er mit der Dämpfung 11 dB (Vorgabe in Arduino) nur zwischen etwa 0,15 und 2,45 V zuverlässig; darunter zeigt er 0, darüber wird er stark nichtlinear. Zweitens streut seine Referenz von Chip zu Chip zwischen 1,0 und 1,2 V. Die Funktion analogReadMilliVolts() rechnet mit Kalibrierwerten, die im Chip gespeichert sind, und liefert gleich Millivolt. Drittens ist der zweite Wandler (ADC2, etwa an GPIO 4, 12 bis 15 und 25 bis 27) nicht nutzbar, solange WLAN läuft. Nimm Pins von ADC1, GPIO 32 bis 39. Für 15 V passt ein Teiler aus 56 kΩ und 10 kΩ: Er setzt 15 V auf 2,27 V herab, ein Pin verträgt höchstens 3,3 V.
Messung gegen die Versorgung. Wenn der Arduino aus einem guten 5-V-Regler läuft, kannst du DEFAULT als Referenz nehmen und das Teilerverhältnis 1:4 wählen, etwa 30 kΩ und 10 kΩ. Dann wird jede Schwankung der Versorgung zum Messfehler.
Genauer messen. Für Strom und Spannung mit 0,1 % gibt es eigene Messwandler wie den INA219 oder INA226 am I²C-Bus (High-Side-Strommessung). Ein externer ADC mit 16 Bit und eigener Spannungsreferenz hilft bei kleinen Signalen. Schnelle Störungen fängst du mit einem RC-Tiefpass vor dem Pin ab.
Akkuwächter. Willst du nur wissen, ob die Spannung eine Schwelle unterschreitet, genügt ein Komparator: Unterspannungswächter.
Typische Fehler
- Messwert schwankt mit der USB-Versorgung: Gemessen wird gegen AVCC. Auf die interne Referenz umstellen und kalibrieren.
- AREF an 5 V gelegt: Mit
analogReference(INTERNAL)gibt der Chip die Referenz an AREF aus. Eine externe Spannung dort schließt die interne Referenz kurz. An AREF gehört nur der Kondensator. - Erste Werte nach dem Start falsch: Nach dem Umschalten der Referenz braucht C2 einige Millisekunden, bis er geladen ist. Erste Messungen verwerfen.
- Teiler zu hochohmig: Mit 1 MΩ und 68 kΩ ändert sich der Messwert, wenn du einen anderen Kanal davor abfragst. Ohne C1 erreicht der Abtastkondensator nicht die volle Spannung.
- ESP32 zeigt 0 bei kleinen Spannungen: Unter 0,15 V misst er nicht. Teiler so wählen, dass der interessante Bereich zwischen 0,15 und 2,45 V liegt.
- Masse vergessen: Ohne Verbindung zwischen Akku-Minus und GND hängt der Pin in der Luft.
Selbsttest
Warum ist die interne 1,1-V-Referenz oft besser als die 5-V-Versorgung?
Sie hängt nicht von der Versorgung ab. Ihr Exemplarfehler ist konstant und lässt sich einmal wegkalibrieren.
Welchen Wert liefert analogRead bei 12,6 V Akkuspannung mit dem Teiler 1:16 und exakt 1,1 V Referenz?
Am Pin liegen 0,7875 V; 0,7875 V / 1,1 V · 1024 ≈ 733.
Warum darf der Teiler nicht beliebig hochohmig sein?
Der ADC braucht beim Abtasten Ladung; über 10 kΩ Quellwiderstand wird er ungenau, wenn kein Kondensator am Pin sitzt, und Leckströme erzeugen Fehler.
Welche Pins nimmst du beim ESP32 für Analogmessungen mit WLAN?
Pins von ADC1, also GPIO 32 bis 39; ADC2 ist bei aktivem WLAN belegt.
Wie groß ist ein ADC-Schritt am Akku, wenn du 0 bis 20 V mit 10 Bit gegen 5 V misst?
Teiler 1:4, ein Schritt am Pin 4,9 mV, am Akku das Vierfache: rund 20 mV.