Ratgeber · 13 Min. Lesezeit

Arduino Voltmeter bauen: 0–25 V messen, LCD und Kalibrierung

Arduino Voltmeter bauen: 0–25 V mit Spannungsteiler messen, Widerstände wählen, Z-Diode als Schutz, kalibrieren, LCD, INA219-Wattmeter und Akkutester.

Ein Arduino Voltmeter ist ein Messgerät, das du an einem Abend baust: Zwei Widerstände, ein Analogeingang und ein paar Zeilen Code reichen, um 0–25 V genau zu messen und auf einem Display anzuzeigen. Die Analogeingänge des Arduino vertragen höchstens 5 V. Eine höhere Spannung teilst du deshalb zuerst mit einem Spannungsteiler herunter und rechnest sie im Code mit demselben Verhältnis wieder hoch. Akkuwächter, Netzteilanzeigen, Solarpanel-Logger und Akkutester beruhen alle auf genau dieser Idee.

In dieser Anleitung lernst du Schritt für Schritt, wie du die Widerstände passend zum Messbereich wählst, wie Z-Diode und Vorwiderstand den Analogeingang vor Überspannung schützen, wie das fertige 0–25-V-Spannungssensormodul funktioniert und wie Referenzspannung und Kalibrierung deine Messung nah an ein Multimeter bringen. Danach zeigst du den Wert auf einem I2C-LCD an, baust dasselbe Voltmeter mit ESP32 und Raspberry Pi Pico, ergänzt mit dem INA219 die Strommessung zum Wattmeter und baust zum Schluss einen Tester, der die echte Kapazität eines Akkus in mAh misst.

Digitales Voltmeter
Dein Arduino-Voltmeter kann die Spannung wie diese Einbauanzeigen mit zwei Nachkommastellen anzeigen.

Wie funktioniert ein Arduino Voltmeter?

Der Arduino kennt Spannung nicht direkt: Sein ADC (Analog-Digital-Wandler) vergleicht die Spannung am Analogeingang mit einer Referenzspannung und liefert das Ergebnis als ganze Zahl. Der ADC des Arduino Uno hat 10 Bit: Bei 0 V liest er 0, bei der Referenzspannung (standardmäßig 5 V) 1023. Die Spannung am Pin ist Vpin = Messwert × Vref / 1024. Sitzt ein Spannungsteiler davor, ist die eigentlich gemessene Spannung Vein = Vpin × (R1 + R2) / R2. Die Genauigkeit des ganzen Voltmeters hängt also von drei Dingen ab: dem echten Wert von Vref, dem Verhältnis der beiden Widerstände und dem Fehler des ADC selbst.

BoardADCReferenz1 Stufe am Pin1 Stufe mit 0–25-V-Teiler
Arduino Uno, Nano, Pro Mini10 Bit (0–1023)5 V (AVcc)4,88 mV24,4 mV (30 kΩ + 7,5 kΩ)
ESP3212 Bit (0–4095)Etwa 3,3 V (11 dB Dämpfung)Etwa 0,8 mVEtwa 9 mV (100 kΩ + 10 kΩ)
Raspberry Pi Pico12 Bit (0–65535 über read_u16)3,3 V (ADC_VREF)0,81 mV8,9 mV (100 kΩ + 10 kΩ)

Spannungsteiler und Widerstandswahl für 0–25 V

Die zu messende Spannung kommt über den oberen Widerstand R1 herein, der Mittelpunkt zwischen beiden Widerständen geht an den Analogpin, und der untere Widerstand R2 liegt an GND. Bei der Wahl legst du zuerst die höchste Spannung fest und wählst dann ein Verhältnis, bei dem am Pin knapp unter der Referenz bleibt, beim Uno also etwa 4,5 V. Das Paar aus 30 kΩ und 7,5 kΩ in fertigen Modulen teilt genau durch 5: 25 V am Eingang ergeben 5,00 V am Pin. Wähle die Werte auch nicht beliebig: Ist der Gesamtwiderstand zu klein, zieht der Teiler unnötig Strom aus der Quelle, ist er zu groß, kann sich der Abtastkondensator im ADC nicht aufladen und der Messwert wandert. Das Datenblatt des ATmega328P empfiehlt, dass die Quelle am Analogeingang höchstens 10 kΩ Innenwiderstand hat; bei einem Teiler ist das die Parallelschaltung von R1 und R2 (6 kΩ bei 30 kΩ und 7,5 kΩ). Die Formel im Detail und den Belastungseffekt findest du im Artikel zum Spannungsteiler.

MessbereichArduino Uno (5 V): R1 + R2Pin bei EndwertESP32 / Pico (3,3 V): R1 + R2Pin bei Endwert
0–10 V12 kΩ + 10 kΩ4,55 V33 kΩ + 10 kΩ2,33 V
0–25 V30 kΩ + 7,5 kΩ (fertiges Modul)5,00 V100 kΩ + 10 kΩ2,27 V
0–30 V56 kΩ + 10 kΩ4,55 V120 kΩ + 10 kΩ2,31 V
0–50 V100 kΩ + 10 kΩ4,55 V220 kΩ + 10 kΩ2,17 V
Statt das Verhältnis für deinen Bereich von Hand auszurechnen, kannst du den Spannungsteiler-Rechner verwenden. In den Spalten für ESP32 und Pico haben wir die Pinspannung bewusst unter 2,5 V gehalten, weil der ADC des ESP32 am oberen Ende nicht mehr linear ist. Nimm Metallschichtwiderstände mit 1 % Toleranz; zwei 5-%-Widerstände können das Verhältnis im ungünstigsten Fall um rund 10 % verschieben.

Schutz: Z-Diode, Vorwiderstand und Kondensator

Auch bei korrekt berechnetem Teiler können eine falsche Messspitze, eine Spitze im Netzteil oder versehentlich 48 V statt 25 V den Pin über 5 V treiben. Die Pins des ATmega328P vertragen höchstens Versorgung plus 0,5 V. Im Pin sitzen zwar Schutzdioden nach 5 V und GND, aber sie halten nur kleine Ströme aus. Die gute Nachricht: Der obere Widerstand des Teilers begrenzt den Strom bereits. Mit 30 kΩ als R1 fließen selbst bei 50 V höchstens etwa 1,5 mA in den Pin. Um diesen Strom weiter zu senken und die Überspannung sicher abzufangen, kannst du folgende Stufen ergänzen.

  • Vorwiderstand: Setze 4,7–10 kΩ zwischen den Mittelpunkt des Teilers und den Analogpin. Bei Überspannung sinkt der Strom in die internen Dioden des Pins in den Mikroampere-Bereich.
  • 100-nF-Kondensator: Schalte ihn zwischen Analogpin und GND. Er gleicht den höheren Quellwiderstand durch den Vorwiderstand aus, denn der ADC holt sich die Ladung beim Abtasten aus diesem Kondensator. Außerdem filtert er Rauschen und kurze Spitzen.
  • 5,1-V-Z-Diode: Schließe eine Z-Diode wie 1N4733A oder BZX55C5V1 mit der Kathode an den Pin und der Anode an GND an. Will die Spannung über 5,1 V steigen, leitet die Z-Diode und führt den Überschuss nach GND ab.
  • Achtung, Leckstrom: Eine Z-Diode zieht schon etwas unterhalb ihrer Durchbruchspannung einen kleinen Strom, und bei einem hochohmigen Teiler zieht dieser Strom den Messwert nach unten. Mit Z-Diode solltest du den Pin höchstens auf etwa 4 V bringen, oder du nimmst stattdessen eine Schottky-Diode (BAT85) vom Pin zur 5-V-Schiene.
  • Verpolung: Vertauschst du die Messleitungen, liegt am Pin eine negative Spannung. Der Vorwiderstand begrenzt den Strom; zusätzlich kannst du eine zweite Schottky-Diode mit der Anode an GND und der Kathode am Pin einsetzen.
Dieses Voltmeter ist nur für Gleichspannung und Kleinspannung (höchstens einige zehn Volt) gedacht. Versuche nie, die 230-V-Netzspannung mit zwei Widerständen zu messen: Das ist lebensgefährlich, und die GND des Arduino hängt dann am Netz. Für Netzspannung nimmt man ein galvanisch getrenntes Trafomodul wie den ZMPT101B. Außerdem muss der Minuspol der gemessenen Quelle mit der GND des Arduino verbunden sein; ohne gemeinsame Masse ist der Messwert bedeutungslos.

Das fertige Spannungssensormodul (0–25 V)

Wenn du nicht löten möchtest, kannst du das kleine rote oder blaue Modul verwenden, das als "Voltage Sensor" verkauft wird. Darin steckt nichts Magisches: ein Teiler aus genau 30 kΩ und 7,5 kΩ, eine Schraubklemme und eine dreipolige Stiftleiste. Da das Verhältnis 5 beträgt, misst du mit einem 5-V-Arduino 0–25 V, mit einem 3,3-V-Board aber nur bis 16,5 V. Liegen an einem 3,3-V-Board 25 V an, kommen 5 V am Pin an und beschädigen ihn; für ESP32 und Pico ist ein eigener Teiler aus der Tabelle oben sicherer. Das Modul hat keine Schutzdiode, also gelten die Maßnahmen mit Z- oder Schottky-Diode aus dem vorigen Abschnitt auch hier.

ModulanschlussFunktionArduino UnoESP32 (eigener Teiler)Raspberry Pi Pico (eigener Teiler)
VCC (Schraubklemme)Pluspol der MessquelleQuelle +Oberes Ende von R1Oberes Ende von R1
GND (Schraubklemme)Minuspol der MessquelleQuelle −Quelle − und GNDQuelle − und GND
SGeteiltes SignalA0GPIO 34 (ADC1)GP26 (ADC0, Pin 31)
+Bei den meisten Modulen unbelegtNicht anschließen--
−Modul-GNDGNDGNDGND (z. B. Pin 33)

Schritt für Schritt: dein erstes Arduino Voltmeter

  1. Verbinde den S-Pin des Moduls mit A0 und den −-Pin mit GND. Baust du den Teiler selbst, kommt 30 kΩ auf die Quellenseite, 7,5 kΩ auf die GND-Seite, und der Mittelpunkt geht an A0.
  2. Stecke den Arduino an USB, miss mit dem Multimeter zwischen 5V-Pin und GND und notiere den Wert. Die USB-Spannung liegt oft irgendwo zwischen 4,7 und 5,1 V.
  3. Trage den gemessenen Wert im Code unten in die Konstante VREF ein und lade ihn hoch.
  4. Schließe die Messquelle an die Schraubklemme des Moduls an: Plus an VCC, Minus an GND. Für den ersten Test eignet sich ein 9-V-Block oder ein regelbares Labornetzteil.
  5. Öffne den seriellen Monitor mit 9600 Baud. Lies die Spannung ab, miss gleichzeitig mit dem Multimeter an der Quelle und vergleiche beide Werte.
C++ (Arduino IDE)
1// Arduino voltmetre: 0-25 V gerilim sensörü modülü / Arduino voltmeter: 0-25 V voltage sensor module
2// Modül S -> A0, modül - -> GND / module S -> A0, module - -> GND
3// Ölçülen kaynak modülün VCC ve GND klemensine / measured source goes to the module's VCC and GND terminals
4const int SENSE_PIN = A0;
5const float VREF = 5.00;       // 5V pininde ölçtüğün gerilim / voltage you measured on the 5V pin
6const float R1 = 30000.0;      // üst direnç (ohm) / top resistor (ohms)
7const float R2 = 7500.0;       // alt direnç (ohm) / bottom resistor (ohms)
8const float CAL = 1.000;       // kalibrasyon: gerçek / okunan / calibration: real / measured
9const int SAMPLES = 32;        // ortalama için örnek sayısı / samples to average
10
11float readVoltage() {
12  analogRead(SENSE_PIN);                    // ilk okumayı at / discard the first reading
13  unsigned long sum = 0;
14  for (int i = 0; i < SAMPLES; i++) {
15    sum += analogRead(SENSE_PIN);
16    delayMicroseconds(500);
17  }
18  float adc = (float)sum / SAMPLES;         // 0-1023 arası ortalama / average between 0 and 1023
19  float vPin = adc * VREF / 1024.0;         // pindeki gerilim / voltage at the pin
20  return vPin * (R1 + R2) / R2 * CAL;       // bölücüden önceki gerilim / voltage before the divider
21}
22
23void setup() {
24  Serial.begin(9600);
25}
26
27void loop() {
28  float v = readVoltage();
29  if (v < 0.05) v = 0.0;                    // boşta gürültüyü sıfırla / zero the noise when idle
30  Serial.print(F("Gerilim / Voltage: "));
31  Serial.print(v, 2);
32  Serial.println(F(" V"));
33  delay(500);
34}

Der Code mittelt jedes Mal 32 Messungen, sodass das Zittern des ADC um ±1 Stufe weitgehend verschwindet und die letzte Stelle ruhig wird. Die erste Messung wird verworfen, weil der Abtastkondensator des ADC noch Ladung vom vorherigen Kanal trägt. Werte unter 0,05 V auf null zu runden verhindert, dass ohne angeschlossene Quelle zufällige Werte wie 0,02–0,04 V erscheinen. Denk daran, dass die Auflösung 24,4 mV beträgt: Auch wenn du zwei Nachkommastellen siehst, springt die letzte Stelle in Schritten von 0,02–0,03 V. Brauchst du eine feinere Auflösung, wähle einen kleineren Bereich; mit einem 0–10-V-Teiler sinkt eine Stufe auf 10,7 mV.

Referenzspannung und Kalibrierung

Oft heißt es, Arduino-Voltmeter würden "falsch messen", doch die eigentliche Fehlerquelle ist meist die Referenz. Steht im Code 5,00 V, während das Board über USB nur 4,80 V bekommt, liegt jeder Messwert 4 % zu hoch: Ein 12,00-V-Akku erscheint als 12,50 V. Diese Spannung ändert sich vom Desktop zum Laptop und von einem USB-Kabel zum nächsten, und mit einem externen Netzteil übernimmt der Spannungsregler des Boards und der Wert ist wieder anders. Es gibt drei Lösungen: den 5V-Pin messen und in den Code schreiben, eine feste interne Referenz verwenden oder die eigene Versorgungsspannung des Boards bei jeder Messung neu bestimmen.

MethodeCodeVorteilWorauf achten
Standard (AVcc)analogReference(DEFAULT)Keine Einrichtung, voller Bereich 0–5 VSchwankt die Versorgung, schwankt auch der Messwert
Interne 1,1-V-ReferenzanalogReference(INTERNAL)Stabil und unabhängig von der VersorgungLiegt je nach Board zwischen 1,0 und 1,2 V; das Teilerverhältnis muss etwa 23 sein (z. B. 220 kΩ + 10 kΩ)
Externe Referenz (AREF)analogReference(EXTERNAL)Beste Genauigkeit mit einer Präzisionsreferenz wie dem LM4040Diese Zeile muss laufen, bevor Spannung an AREF liegt, sonst entsteht ein Kurzschluss mit der internen Referenz
Versorgung messen (readVcc)Code untenKeine Zusatzteile, bleibt genau, wenn USB oder Akku wechselnNur auf AVR-Boards (Uno, Nano, Pro Mini); den 1,1-V-Wert einmal kalibrieren
C++ (Arduino IDE)
1// Kendi besleme gerilimini ölçen voltmetre (ATmega328P: Uno, Nano, Pro Mini)
2// Voltmeter that measures its own supply (ATmega328P: Uno, Nano, Pro Mini)
3const int SENSE_PIN = A0;
4const float R1 = 30000.0;      // üst direnç / top resistor
5const float R2 = 7500.0;       // alt direnç / bottom resistor
6long bandgapMv = 1100;         // iç referans (mV), kalibrasyonla düzelt / internal reference (mV), fix by calibration
7
8long readVccMv() {
9  // Referans AVcc, ölçülen kanal iç 1,1 V / reference AVcc, measured channel is the internal 1.1 V
10  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
11  delay(2);                                  // referans otursun / let the reference settle
12  ADCSRA |= _BV(ADSC);                       // dönüşümü başlat / start a conversion
13  while (bit_is_set(ADCSRA, ADSC)) {}        // bitmesini bekle / wait until it finishes
14  unsigned int raw = ADCW;                   // 10 bit sonuç / 10-bit result
15  return bandgapMv * 1024L / raw;            // Vcc = 1,1 V x 1024 / okunan / Vcc = 1.1 V x 1024 / reading
16}
17
18float readVoltage(float vcc) {
19  analogRead(SENSE_PIN);                     // kanal değişti, ilk okumayı at / channel changed, discard first
20  unsigned long sum = 0;
21  for (int i = 0; i < 32; i++) sum += analogRead(SENSE_PIN);
22  float vPin = (sum / 32.0) * vcc / 1024.0;
23  return vPin * (R1 + R2) / R2;
24}
25
26void setup() {
27  Serial.begin(9600);
28}
29
30void loop() {
31  float vcc = readVccMv() / 1000.0;
32  float v = readVoltage(vcc);
33  Serial.print(F("Vcc: "));
34  Serial.print(vcc, 3);
35  Serial.print(F(" V   Giris / Input: "));
36  Serial.print(v, 2);
37  Serial.println(F(" V"));
38  delay(500);
39}
  1. Interne Referenz kalibrieren: Starte den readVcc-Code und vergleiche den Vcc-Wert im seriellen Monitor mit dem, was dein Multimeter am 5V-Pin misst. Neuer bandgapMv = 1100 × gemessen / angezeigt. Zeigt das Board etwa 5,12 V und das Multimeter 4,98 V, trägst du 1100 × 4,98 / 5,12 ≈ 1070 ein.
  2. Einpunkt-Kalibrierung: Lege eine bekannte Spannung nahe am oberen Ende des Bereichs an (z. B. 12 V). CAL = Multimeterwert / Arduino-Wert. Dieser Faktor korrigiert auch den Verhältnisfehler durch die Widerstandstoleranz.
  3. Zweipunkt-Kalibrierung: Siehst du bei kleinen Spannungen einen festen Versatz, miss an zwei Punkten, einem niedrigen (z. B. 2 V) und einem hohen (z. B. 20 V). Steigung = (M2 − M1) / (A2 − A1), Versatz = M1 − Steigung × A1; das Ergebnis ist wahr = Steigung × Messwert + Versatz (M ist der Multimeterwert, A der Arduino-Wert).
  4. Prüfen: Kontrolliere nach der Kalibrierung mit einer dritten Spannung in der Mitte des Bereichs. Ein sorgfältig gebautes Uno-Voltmeter misst im Bereich 0–25 V mit weniger als 1 % Fehler.

Digitales Voltmeter mit LCD

I2C-16x2-LCD
Dank des I2C-Moduls auf der Rückseite braucht das 16x2-LCD nur vier Leitungen: GND, VCC, SDA und SCL.

Damit das Voltmeter ohne Computer auskommt, gibst du den Wert einfach auf einem I2C-LCD aus. Verbinde GND des LCD mit GND, VCC mit 5V, SDA mit A4 und SCL mit A5. Installiere über den Bibliotheksverwalter die Bibliothek LiquidCrystal I2C (Frank de Brabander). Die Adresse des Displays ist meist 0x27, bei manchen Modulen 0x3F. Der folgende Code zeigt oben die aktuelle Spannung und unten den kleinsten und größten Wert seit dem Einschalten; so erwischst du zum Beispiel auch den Spannungseinbruch am Akku, während ein Motor läuft.

C++ (Arduino IDE)
1// LCD ekranlı dijital voltmetre (0-25 V, min/maks) / Digital voltmeter with LCD (0-25 V, min/max)
2// LCD: SDA -> A4, SCL -> A5, VCC -> 5V, GND -> GND; sensör S -> A0 / sensor S -> A0
3#include <Wire.h>
4#include <LiquidCrystal_I2C.h>
5
6LiquidCrystal_I2C lcd(0x27, 16, 2);   // adres 0x27 ya da 0x3F / address 0x27 or 0x3F
7
8const int SENSE_PIN = A0;
9const float VREF = 5.00;              // 5V pininde ölçülen / measured on the 5V pin
10const float RATIO = (30000.0 + 7500.0) / 7500.0;   // = 5,0
11const float CAL = 1.000;              // kalibrasyon katsayısı / calibration factor
12
13float vMin = 99.99;
14float vMax = 0.0;
15
16float readVoltage() {
17  analogRead(SENSE_PIN);
18  unsigned long sum = 0;
19  for (int i = 0; i < 32; i++) sum += analogRead(SENSE_PIN);
20  float v = (sum / 32.0) * VREF / 1024.0 * RATIO * CAL;
21  return v < 0.05 ? 0.0 : v;
22}
23
24void printField(float value) {
25  char buf[8];
26  dtostrf(value, 5, 2, buf);          // sabit genişlik: " 9.87" / fixed width: " 9.87"
27  lcd.print(buf);
28}
29
30void setup() {
31  lcd.init();
32  lcd.backlight();
33  lcd.print(F("Voltmetre 0-25V"));
34  delay(1000);
35  lcd.clear();
36}
37
38void loop() {
39  float v = readVoltage();
40  if (v > 0.5) {                      // boştayken min/maks güncelleme / don't update min/max when idle
41    if (v < vMin) vMin = v;
42    if (v > vMax) vMax = v;
43  }
44
45  lcd.setCursor(0, 0);
46  lcd.print(F("V: "));
47  printField(v);
48  lcd.print(F(" V      "));
49
50  lcd.setCursor(0, 1);
51  lcd.print(F("L"));
52  printField(vMin > 99.0 ? 0.0 : vMin);
53  lcd.print(F("  H"));
54  printField(vMax);
55  lcd.print(F("  "));
56  delay(300);
57}

Voltmeter mit dem ESP32

Der ESP32 arbeitet mit 3,3 V, und seine Pins vertragen nicht mehr als 3,6 V. Nimm für 0–25 V deshalb einen Teiler aus 100 kΩ + 10 kΩ: 25 V am Eingang ergeben 2,27 V am Pin. Schließe den Teiler an einen ADC1-Pin an (GPIO 32–39); ADC2-Pins funktionieren nicht, solange WLAN aktiv ist. Der ADC des ESP32 hat 12 Bit, ist an den Enden aber nicht linear: Unter 0,15 V sieht er kaum etwas, und über 2,5 V wächst sein Fehler. Die Funktion analogReadMilliVolts() nutzt ab Werk im Chip gespeicherte Kalibrierdaten und liefert ein viel genaueres Millivolt-Ergebnis als der Rohwert. Den restlichen Versatz beseitigt der Code mit der Zweipunkt-Kalibrierung aus dem vorigen Abschnitt über die Konstanten GAIN und OFFSET.

C++ (Arduino IDE)
1// ESP32 voltmetre: 100k + 10k bölücü ile 0-25 V / ESP32 voltmeter: 0-25 V with a 100k + 10k divider
2// Kaynak + -> 100k -> GPIO 34 -> 10k -> GND, kaynak - -> GND / source + -> 100k -> GPIO 34 -> 10k -> GND
3const int SENSE_PIN = 34;                 // ADC1_CH6, Wi-Fi açıkken de çalışır / works with Wi-Fi on
4const float RATIO = (100000.0 + 10000.0) / 10000.0;   // = 11,0
5const float GAIN = 1.000;                 // iki noktalı kalibrasyon: eğim / two-point calibration: slope
6const float OFFSET = 0.00;                // iki noktalı kalibrasyon: kayma (V) / two-point calibration: offset (V)
7
8float readVoltage() {
9  uint32_t mv = 0;
10  for (int i = 0; i < 64; i++) {
11    mv += analogReadMilliVolts(SENSE_PIN);   // fabrika kalibrasyonlu mV / factory-calibrated mV
12  }
13  float vPin = mv / 64.0 / 1000.0;           // pindeki gerilim (V) / voltage at the pin (V)
14  float v = vPin * RATIO * GAIN + OFFSET;
15  return v < 0.10 ? 0.0 : v;
16}
17
18void setup() {
19  Serial.begin(115200);
20  analogReadResolution(12);                  // 0-4095
21}
22
23void loop() {
24  float v = readVoltage();
25  Serial.printf("Gerilim / Voltage: %.2f V\n", v);
26  delay(500);
27}

Voltmeter mit dem Raspberry Pi Pico (MicroPython)

Beim Raspberry Pi Pico sind GP26, GP27 und GP28 die Analogeingänge. Schließe denselben Teiler aus 100 kΩ + 10 kΩ wie beim ESP32 an GP26 an. In MicroPython liefert read_u16() das 12-Bit-Ergebnis auf 0–65535 skaliert. Die ADC-Referenz des Pico wird gefiltert aus der 3,3-V-Schiene gewonnen; für mehr Genauigkeit misst du zwischen ADC_VREF (Pin 35) und GND und trägst den Wert in VREF ein. Im Code steckt noch ein Bonus: Beim normalen Pico hängt GP29 (ADC3) an einem internen Teiler, der die Versorgung VSYS durch 3 teilt. So liest du ganz ohne Zusatzteile auch die Spannung des Akkus, der den Pico versorgt. Beim Pico W und Pico 2 W teilt sich GP29 die Leitung mit dem Funkchip, deshalb funktioniert diese Zeile dort nicht direkt.

MicroPython
1# Raspberry Pi Pico voltmetre (MicroPython) / Raspberry Pi Pico voltmeter (MicroPython)
2# Kaynak + -> 100k -> GP26 -> 10k -> GND / source + -> 100k -> GP26 -> 10k -> GND
3from machine import ADC
4import time
5
6sense = ADC(26)            # GP26 = ADC0 (pin 31)
7vsys = ADC(29)             # GP29 = VSYS / 3 (yalnız standart Pico / standard Pico only)
8VREF = 3.3                 # ADC_VREF; multimetreyle ölçüp düzelt / measure and correct with a multimeter
9RATIO = (100000 + 10000) / 10000    # = 11.0
10GAIN = 1.000               # iki noktalı kalibrasyon: eğim / two-point calibration: slope
11OFFSET = 0.00              # iki noktalı kalibrasyon: kayma (V) / two-point calibration: offset (V)
12
13
14def pin_voltage(adc, samples=64):
15    total = 0
16    for _ in range(samples):
17        total += adc.read_u16()            # 0-65535
18    return total / samples * VREF / 65535  # pindeki gerilim / voltage at the pin
19
20
21while True:
22    v_in = pin_voltage(sense) * RATIO * GAIN + OFFSET
23    if v_in < 0.05:
24        v_in = 0.0
25    v_sys = pin_voltage(vsys) * 3          # VSYS = GP29 x 3
26    print("Giris / Input: {:.2f} V   VSYS: {:.2f} V".format(v_in, v_sys))
27    time.sleep(0.5)

Strommessung ergänzen und ein Wattmeter bauen: ACS712 oder INA219

ACS712-Stromsensormodul
Der ACS712 misst den Strom über den Hall-Effekt und trennt den Messkreis elektrisch vom Arduino.

Ergänzt du ein Voltmeter um die Strommessung, erhältst du auch die Leistung: P = U × I. Liefert ein 12-V-Akku 1,5 A, beträgt die Leistung 18 W. Summierst du die Leistung über die Zeit, erhältst du die Energie: Eine 18-W-Last verbraucht in 2 Stunden 36 Wh. Dafür gibt es zwei gängige Lösungen. Der ACS712 hat einen Analogausgang, misst auch Wechselstrom und bietet galvanische Trennung; er wird einfach zum zweiten Analogkanal deines Voltmeters. Der INA219 ist ein DC-Leistungsmesser, der Spannung und Strom im selben Chip mit 12 Bit misst und über I2C kommuniziert; für sich allein ist er schon ein fertiges Wattmeter.

MerkmalSpannungsmodul + ACS712 (5A)INA219-Modul
Spannungsbereich0–25 V (durch den Teiler)0–26 V (im Chip)
Strombereich±5 A±3,2 A (mit 0,1-Ω-Shunt)
StromauflösungEtwa 26 mA am Uno0,1 mA
WechselstromJaNein
AnschlussZwei AnalogpinsI2C (SDA, SCL), Adresse 0x40
Ideal fürMotoren, netzseitigen Strom und überall, wo Trennung nötig istKleine DC-Leistungen wie Akkus, Solarpanels und USB-Geräte
C++ (Arduino IDE)
1// INA219 + I2C LCD ile wattmetre: V, A, W ve Wh / Wattmeter with INA219 + I2C LCD: V, A, W and Wh
2// Kaynak + -> INA219 VIN+ ; INA219 VIN- -> yük + ; yük - -> kaynak - -> Arduino GND
3// Source + -> INA219 VIN+ ; INA219 VIN- -> load + ; load - -> source - -> Arduino GND
4#include <Wire.h>
5#include <Adafruit_INA219.h>
6#include <LiquidCrystal_I2C.h>
7
8Adafruit_INA219 ina219;               // varsayılan adres 0x40 / default address 0x40
9LiquidCrystal_I2C lcd(0x27, 16, 2);
10
11float energyWh = 0.0;
12unsigned long lastMs = 0;
13
14void printField(float value, int width, int decimals) {
15  char buf[10];
16  dtostrf(value, width, decimals, buf);
17  lcd.print(buf);
18}
19
20void setup() {
21  Serial.begin(9600);
22  lcd.init();
23  lcd.backlight();
24  if (!ina219.begin()) {              // modül bulunamadı / module not found
25    lcd.print(F("INA219 yok!"));
26    while (true) delay(10);
27  }
28  // ina219.setCalibration_16V_400mA();  // küçük akımlar için daha hassas / finer for small currents
29  lastMs = millis();
30}
31
32void loop() {
33  float busV = ina219.getBusVoltage_V();           // VIN- ile GND arası / between VIN- and GND
34  float shuntMv = ina219.getShuntVoltage_mV();     // şönt üzerindeki düşüm / drop across the shunt
35  float loadV = busV + shuntMv / 1000.0;           // kaynağın gerilimi / source voltage
36  float currentA = ina219.getCurrent_mA() / 1000.0;
37  float powerW = loadV * currentA;
38
39  unsigned long now = millis();
40  energyWh += powerW * (now - lastMs) / 3600000.0; // W x saat = Wh / W x hours = Wh
41  lastMs = now;
42
43  lcd.setCursor(0, 0);
44  printField(loadV, 5, 2);  lcd.print(F("V "));
45  printField(currentA, 6, 3); lcd.print(F("A  "));
46  lcd.setCursor(0, 1);
47  printField(powerW, 6, 2); lcd.print(F("W "));
48  printField(energyWh, 6, 2); lcd.print(F("Wh"));
49
50  Serial.print(loadV, 2);    Serial.print(F(" V, "));
51  Serial.print(currentA, 3); Serial.print(F(" A, "));
52  Serial.print(powerW, 2);   Serial.print(F(" W, "));
53  Serial.print(energyWh, 3); Serial.println(F(" Wh"));
54  delay(500);
55}

Der INA219 berechnet den Strom aus dem kleinen Spannungsabfall am 0,1-Ω-Shunt zwischen VIN+ und VIN−. Das Modul kommt deshalb in Reihe auf die Plusseite der Quelle (High-Side). Da die Busspannung zwischen VIN− und GND gemessen wird, addiert der Code den Shunt-Abfall, um die echte Quellenspannung zu erhalten. Die Standardkalibrierung gilt für 32 V und 2 A; misst du nur einige hundert Milliampere, aktiviere die Zeile setCalibration_16V_400mA(), dann wird der Bereich auf 400 mA eingeengt und kleine Ströme werden genauer gemessen. Die Energie entsteht, indem in jedem Durchlauf die aktuelle Leistung mal der vergangenen Zeit aufaddiert wird; beim Ausschalten des Arduino geht sie verloren, also schreibe den Wert in Abständen ins EEPROM, wenn er erhalten bleiben soll. Code für dieselbe Rechnung mit dem ACS712 findest du im Abschnitt zu Leistung und Energie im ACS712-Artikel.

Akkutester: ein Voltmeter, das die Kapazität (mAh) misst

18650-Li-Ionen-Akku
Die aufgedruckte und die echte Kapazität einer 18650-Zelle weichen oft voneinander ab; der Tester deckt das auf.

Die Spannung eines Akkus verrät nicht genau, wie viel Energie noch darin steckt; auch eine volle, aber verbrauchte Zelle kann 4,1 V zeigen. Die echte Kapazität findest du, indem du den Akku über eine bekannte Last entlädst und den Strom über die Zeit aufsummierst: mAh = Σ (Strom × Zeit). In dieser Schaltung schaltet ein MOSFET die Last, und der Arduino misst einmal pro Sekunde die Akkuspannung und die Spannung am unteren Ende des Lastwiderstands. Die Differenz geteilt durch den Lastwiderstand ergibt den Strom. Erreicht der Akku die Entladeschlussspannung, schaltet der MOSFET ab und das Ergebnis wird ausgegeben. Zu Beginn vergleicht der Code außerdem die Spannung ohne und mit Last und berechnet daraus den Innenwiderstand; je höher er ist, desto stärker bricht der Akku bei hohem Strom ein.

BauteilAnschlussHinweis
Akku +Über 10 kΩ an A0; außerdem oberes Ende des Lastwiderstands100 nF zwischen A0 und GND
Lastwiderstand 4,7 ΩZwischen Akku + und MOSFET-DrainMindestens 5 W (besser 10 W) Zementwiderstand; mit einer 18650 fließen etwa 0,9 A, er wird heiß
MOSFET-DrainUnteres Ende des Lastwiderstands; über 10 kΩ an A1Auch zwischen A1 und GND 100 nF
MOSFET-SourceGNDHier kommt auch der Minuspol des Akkus hin
MOSFET-GateÜber 220 Ω an D9; über 100 kΩ an GNDNimm einen Logic-Level-MOSFET wie den IRLZ44N
C++ (Arduino IDE)
1// Pil kapasite test cihazı: mAh, Wh ve iç direnç / Battery capacity tester: mAh, Wh and internal resistance
2// Pil + -> 10k -> A0 ; pil + -> 4,7 ohm yük -> MOSFET drain ; drain -> 10k -> A1
3// Battery + -> 10k -> A0 ; battery + -> 4.7 ohm load -> MOSFET drain ; drain -> 10k -> A1
4// MOSFET source -> GND ; gate <- D9 (220 ohm), gate -> 100k -> GND ; pil - / battery - -> GND
5const int BAT_PIN = A0;
6const int DRAIN_PIN = A1;
7const int LOAD_PIN = 9;
8const float VREF = 5.00;        // 5V pininde ölçülen / measured on the 5V pin
9const float R_LOAD = 4.7;       // yük direnci, multimetreyle ölç / load resistor, measure it
10const float CUTOFF_V = 3.00;    // Li-ion 3,00 V ; alkalin AA / alkaline AA 0,90 V
11
12float mAh = 0.0;
13float wh = 0.0;
14unsigned long lastMs = 0;
15unsigned long startMs = 0;
16bool running = false;
17
18float readPin(int pin) {
19  analogRead(pin);                          // kanal değişti, ilk okumayı at / discard first reading
20  unsigned long sum = 0;
21  for (int i = 0; i < 32; i++) sum += analogRead(pin);
22  return (sum / 32.0) * VREF / 1024.0;
23}
24
25float loadCurrent(float vBat) {
26  return (vBat - readPin(DRAIN_PIN)) / R_LOAD;   // dirençteki gerilim / R / voltage across R / R
27}
28
29void setup() {
30  Serial.begin(9600);
31  pinMode(LOAD_PIN, OUTPUT);
32  digitalWrite(LOAD_PIN, LOW);              // yük kapalı / load off
33  delay(1000);
34
35  float vOpen = readPin(BAT_PIN);           // yüksüz gerilim / open-circuit voltage
36  if (vOpen < CUTOFF_V + 0.1) {
37    Serial.println(F("Pil zayif ya da takili degil / Battery low or missing"));
38    return;
39  }
40  digitalWrite(LOAD_PIN, HIGH);             // yükü aç / load on
41  delay(1000);
42  float vLoad = readPin(BAT_PIN);
43  float amps = loadCurrent(vLoad);
44  Serial.print(F("Bos / Open: "));
45  Serial.print(vOpen, 3);
46  Serial.print(F(" V  Yuklu / Loaded: "));
47  Serial.print(vLoad, 3);
48  Serial.print(F(" V  Ic direnc / Internal R: "));
49  Serial.print((vOpen - vLoad) / amps * 1000.0, 0);
50  Serial.println(F(" mOhm"));
51
52  running = true;
53  startMs = lastMs = millis();
54}
55
56void loop() {
57  if (!running) return;
58  unsigned long now = millis();
59  if (now - lastMs < 1000) return;          // saniyede bir ölç / measure once per second
60
61  float hours = (now - lastMs) / 3600000.0;
62  lastMs = now;
63  float vBat = readPin(BAT_PIN);
64  float amps = loadCurrent(vBat);
65  mAh += amps * 1000.0 * hours;             // akım x süre / current x time
66  wh += vBat * amps * hours;
67
68  Serial.print((now - startMs) / 1000);
69  Serial.print(F(" s  "));
70  Serial.print(vBat, 3);
71  Serial.print(F(" V  "));
72  Serial.print(amps, 3);
73  Serial.print(F(" A  "));
74  Serial.print(mAh, 0);
75  Serial.println(F(" mAh"));
76
77  if (vBat <= CUTOFF_V) {                   // kesme gerilimi / cut-off voltage
78    digitalWrite(LOAD_PIN, LOW);
79    running = false;
80    Serial.print(F("Bitti / Done: "));
81    Serial.print(mAh, 0);
82    Serial.print(F(" mAh, "));
83    Serial.print(wh, 2);
84    Serial.println(F(" Wh"));
85  }
86}

Mit 4,7 Ω als Last entlädt sich eine 18650-Zelle mit einem Strom, der bei etwa 0,9 A beginnt und gegen 0,65 A fällt; der Test einer gesunden 2500-mAh-Zelle dauert rund drei Stunden. Bei Li-Ionen-Zellen darf die Abschaltspannung nie unter 3,0 V liegen, sonst nimmt die Zelle Schaden. Testest du eine Alkaline-AA-Batterie, setze CUTOFF_V auf 0,9 V; mit derselben Last fließen etwa 0,3 A. Das Ergebnis kannst du mit dem Aufdruck und dem Akkulaufzeit-Rechner vergleichen. Der so gemessene Innenwiderstand einer neuen 18650 liegt inklusive Halter und Kabel meist unter 0,15 Ω; eine Zelle über 0,3 Ω gehört nicht in Anwendungen mit hohem Strom. Was die Kapazitätsangaben bedeuten, erklärt der Artikel zu mAh und Akkukapazität.

Schließe Li-Ionen-Zellen nie kurz und lege den Lastwiderstand nicht auf eine brennbare Unterlage; ein Widerstand mit rund 4 W Verlustleistung kann 80–100 °C erreichen. Lass den Test nicht unbeaufsichtigt und teste niemals aufgeblähte oder eingedrückte Zellen.

Projektideen mit dem Arduino Voltmeter

  • Akkuwächter mit Unterspannungsalarm: Überwache den 12-V-Akku im Wohnmobil oder in der Solaranlage und lass einen Summer ertönen, wenn er unter 11,8 V fällt.
  • Solarpanel-Logger: Schreibe die Spannung des Panels und mit dem INA219 auch den Strom jede Minute auf eine SD-Karte und berechne den Tagesertrag in Wh.
  • Anzeige fürs Labornetzteil: Ergänze den Ausgang eines LM2596-Moduls um Voltmeter und INA219 und mach daraus ein Labornetzteil.
  • Akku aus der Ferne überwachen: Schicke die mit dem ESP32 gemessene Spannung per MQTT an Home Assistant oder lass dir bei niedriger Spannung eine Telegram-Nachricht senden.
  • 18650-Pack prüfen: Teste die Kapazität der Zellen, die du mit einem TP4056 lädst, und kombiniere Zellen ähnlicher Kapazität zu einem ausgewogenen Pack.
  • Anzeige mit großen Ziffern: Zeige den Wert statt auf dem LCD auf einer 7-Segment-Anzeige oder einem OLED-Display, groß genug für die Ablesung aus der Ferne.

Häufige Fehler und ihre Lösungen

SymptomMögliche UrsacheLösung
Messwert ist immer 2–5 % zu hoch oder zu niedrigIm Code steht VREF = 5,00 V, das Board läuft aber mit einer anderen Spannung5V-Pin messen und in VREF eintragen oder die readVcc-Methode nutzen
Wert springt ständigMinuspol der Quelle nicht mit Arduino-GND verbunden oder Leitung verrauschtGemeinsame Masse, Mittelwert bilden, 100 nF am Pin
Bei hoher Spannung bleibt der Wert hängenPin hat die Referenz erreicht, ADC steht auf 1023Messbereich vergrößern, Teilerverhältnis erhöhen
Messwert knickt oben ab, nicht linearLeckstrom der Z-Diode oder oberes Ende des ESP32-ADCPin unter 4 V halten (beim ESP32 unter 2,5 V) oder Schottky verwenden
Beim ESP32 ist der Wert 0 oder eingefroren, sobald WLAN startetTeiler hängt an einem ADC2-PinEinen ADC1-Pin verwenden, GPIO 32–39
INA219 zeigt negativen StromVIN+ und VIN− vertauschtPlus der Quelle an VIN+, Plus der Last an VIN−
LCD leuchtet, zeigt aber keinen TextFalsche I2C-Adresse oder KontrastAdresse mit einem I2C-Scanner suchen, Trimmer auf der Rückseite drehen
Bevor du einen neuen Teiler an den Arduino anschließt, schalte die Quelle ein und miss die Spannung am Mittelpunkt mit dem Multimeter. Liegt sie nahe am berechneten Wert und unter der Referenz, kannst du den Pin gefahrlos anschließen. Diese zehn Sekunden verhindern, dass zwei vertauschte Widerstände dein Board zerstören.

Ein Arduino Voltmeter ist einer der besten Wege, das Messen zu verstehen: Mit zwei Widerständen, einer Formel und etwas Kalibrierung erreichst du Werte nahe an einem Multimeter; mit Stromsensor wird daraus ein Wattmeter, mit MOSFET ein Akkutester. In der BlueGrays-App baust du im Projekt "Digitales Voltmeter mit LCD" dieselbe Schaltung Schritt für Schritt mit Schaltplan und fertigem Code nach und kannst von dort zu Projekten für Akkuüberwachung und Leistungsmessung weitergehen.

Häufige Fragen

Wie viel Volt kann ein Arduino messen?

Direkt an einen Analogpin dürfen höchstens 5 V (beim ESP32 und Pico 3,3 V). Mit einem Spannungsteiler lässt sich die Grenze beliebig anheben: Mit 30 kΩ + 7,5 kΩ misst du 25 V, mit 100 kΩ + 10 kΩ 50 V. Ab einigen zehn Volt werden Sicherheit und Isolation aber wichtig, und Netzspannung misst man so auf keinen Fall.

Warum misst mein Arduino Voltmeter falsch?

Meist liegt es an der Referenzspannung: Im Code steht 5,00 V, das Board bekommt über USB aber nur 4,7–4,9 V, und alle Messwerte verschieben sich im selben Verhältnis. Weitere Ursachen sind 5-%-Widerstände, eine fehlende gemeinsame Masse und ein zu hochohmiger Teiler. Den 5V-Pin messen und eintragen oder die readVcc-Methode nutzen und dann den Faktor CAL mit einer bekannten Spannung einstellen löst das Problem.

Kann ich das 0–25-V-Spannungssensormodul mit dem ESP32 verwenden?

Ja, aber mit Vorsicht. Da das Modul durch 5 teilt, misst der ESP32 damit höchstens 16,5 V; liegen 25 V an, kommen 5 V am Pin an und der ESP32 nimmt Schaden. Ein eigener Teiler aus 100 kΩ + 10 kΩ ist für den ESP32 sicherer und auch genauer, weil der ADC im linearen Bereich bleibt.

Kann ein Arduino 230 V Wechselspannung messen?

Auf keinen Fall mit einem Spannungsteiler: Das ist lebensgefährlich und verbindet den Arduino mit dem Netz. Für Netzspannung nimmt man Module wie den ZMPT101B mit kleinem Transformator und galvanischer Trennung. Sein Ausgang ist eine Wechselspannung, deshalb berechnet der Code den Effektivwert (RMS).

Kann ein Arduino negative Spannung messen?

Nicht direkt; ein Analogpin kann nichts unter GND lesen und kann beschädigt werden. Die Lösung ist, das Signal mit Widerständen Richtung 5 V zu verschieben: Zwei gleiche Widerstände zwischen Signal und 5 V bilden zum Beispiel einen Mittelpunkt, der −5 V bis +5 V auf 0–5 V abbildet. Für genauere Aufgaben verwendet man eine Pegelverschiebung mit Operationsverstärker.

Kann ein Arduino Voltmeter so genau sein wie ein Multimeter?

Ein kalibriertes Uno-Voltmeter misst 0–25 V mit weniger als 1 % Fehler; das reicht für die meisten Bastelprojekte und kommt an einfache Multimeter heran. Wegen des 10-Bit-ADC ist die Auflösung im 25-V-Bereich auf etwa 24 mV begrenzt. Bessere Ergebnisse liefern ein externer 16-Bit-ADC wie der ADS1115, Widerstände mit 0,1 % Toleranz und eine Präzisionsreferenz.

Alle Projekte ansehen
Lichtstärke messen mit LDR
#11Anfänger

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

4.6(81)
139
Messung der Lichtintensität mit dem ESP32-LDR-Modul
#113Anfänger

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.

4.6(36)
55
Digitales Voltmeter mit LCD-Anzeige
#56Mittel
Premium

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

4.5(27)
36
Temperaturmessung mit NTC und 2x16 Lcd Display
#44Anfänger
Premium

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

4.5(33)
44
Verwendung des LCD-Bildschirms mit I2C
#32Anfänger
Premium

Verwendung des LCD-Bildschirms mit I2C

Gib deinem Arduino ein eigenes Display und lass es seine erste Nachricht schreiben. Das zweizeilige LCD wird mit nur wenigen Kabeln angeschlossen; oben erscheint ein Gruß, dann unten eine zweite Zeile

4.8(53)
70
ESP32 I2C-LCD-Display (16×2)
#119Mittel
Premium

ESP32 I2C-LCD-Display (16×2)

In diesem Projekt zeigen wir Text an, indem wir ein 16x2-Zeichen-LCD-Display über das I2C-Protokoll an den ESP32 anschließen. Dank I2C können wir das Display mit nur zwei Datenpins (SDA und SCL) steuern; die Verschwendung von 6+ Pins bei einer klassischen parallelen Verbindung entfällt. Der Code schreibt in die erste Zeile eine feste Meldung und in die zweite Zeile einen Zähler, der sich jede Sekunde erhöht. Außerdem lassen wir zu Beginn den I2C-Scanner laufen und geben die Adresse des Displays

4.9(23)
40
Abstandsmessung mit LCD-Display
#31Fortgeschritten
Premium

Abstandsmessung mit LCD-Display

Ein Gerät, das ohne Lineal Abstände misst: Beweg deine Hand vor dem Sensor vor und zurück und sieh zu, wie sich die Zahl ändert. Der HC-SR04 sendet eine Schallwelle aus und horcht auf ihr Echo, der Ar

4.6(45)
59
ESP32: LED-Helligkeit mit Potentiometer (Analog → PWM)
#115Mittel
Premium

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.

4.5(19)
32