Voltmètre Arduino : mesurer 0–25 V avec LCD et étalonnage
Fabriquer un voltmètre Arduino : mesurer 0–25 V avec un pont, choisir les résistances, protection Zener, étalonnage, LCD, wattmètre INA219 et testeur.
Un voltmètre Arduino est un appareil de mesure que tu peux fabriquer en une soirée : deux résistances, une entrée analogique et quelques lignes de code suffisent pour mesurer précisément de 0 à 25 V et l'afficher sur un écran. Les entrées analogiques de l'Arduino lisent au maximum 5 V ; pour mesurer une tension plus élevée, tu la réduis d'abord avec un pont diviseur, puis tu la remets à l'échelle dans le code avec le même rapport. Surveillance de batterie, affichage d'alimentation, suivi de panneau solaire ou testeur de piles reposent tous sur cette idée.
Dans ce guide, tu verras étape par étape comment choisir les résistances selon la plage de mesure, comment une diode Zener et une résistance série protègent l'entrée analogique des surtensions, comment fonctionne le module capteur de tension 0–25 V et comment le réglage de la tension de référence et l'étalonnage rapprochent tes mesures de celles d'un multimètre. Ensuite, tu afficheras la valeur sur un écran LCD I2C, tu construiras le même voltmètre avec un ESP32 et un Raspberry Pi Pico, tu ajouteras une mesure de courant avec un INA219 pour en faire un wattmètre et, pour finir, tu fabriqueras un testeur qui mesure la capacité réelle d'une batterie en mAh.

Comment fonctionne un voltmètre Arduino ?
L'Arduino ne connaît pas directement la tension : son CAN (convertisseur analogique-numérique) compare la tension présente sur l'entrée analogique à une tension de référence et renvoie le résultat sous forme d'entier. Le CAN de l'Arduino Uno est sur 10 bits : il lit 0 pour 0 V et 1023 pour la tension de référence (5 V par défaut). La tension sur la broche vaut Vbroche = lecture × Vref / 1024. Si un pont diviseur se trouve en entrée, la tension réellement mesurée vaut Ventrée = Vbroche × (R1 + R2) / R2. La précision de tout le voltmètre dépend donc de trois choses : la valeur réelle de Vref, le rapport des deux résistances et l'erreur propre du CAN.
| Carte | CAN | Référence | 1 pas sur la broche | 1 pas avec un pont 0–25 V |
|---|---|---|---|---|
| Arduino Uno, Nano, Pro Mini | 10 bits (0–1023) | 5 V (AVcc) | 4,88 mV | 24,4 mV (30 kΩ + 7,5 kΩ) |
| ESP32 | 12 bits (0–4095) | Environ 3,3 V (atténuation 11 dB) | Environ 0,8 mV | Environ 9 mV (100 kΩ + 10 kΩ) |
| Raspberry Pi Pico | 12 bits (0–65535 via read_u16) | 3,3 V (ADC_VREF) | 0,81 mV | 8,9 mV (100 kΩ + 10 kΩ) |
Pont diviseur et choix des résistances pour 0–25 V
La tension à mesurer entre par la résistance du haut R1, le point milieu entre les deux résistances va à la broche analogique, et la résistance du bas R2 va à GND. Pour les choisir, fixe d'abord la tension maximale, puis un rapport qui laisse la broche un peu sous la référence à cette tension, par exemple environ 4,5 V sur un Uno. Le duo 30 kΩ et 7,5 kΩ des modules tout faits divise exactement par 5 : 25 V en entrée donnent 5,00 V sur la broche. Ne choisis pas non plus les valeurs au hasard : si la résistance totale est trop faible, le pont gaspille du courant de la source mesurée ; si elle est trop forte, le condensateur d'échantillonnage interne du CAN n'a pas le temps de se charger et la mesure dérive. La fiche technique de l'ATmega328P recommande que la source qui attaque une entrée analogique ne dépasse pas 10 kΩ ; pour un pont, cette résistance est R1 en parallèle avec R2 (6 kΩ pour 30 kΩ et 7,5 kΩ). La formule détaillée et l'effet de charge sont expliqués dans l'article sur le pont diviseur de tension.
| Plage | Arduino Uno (5 V) : R1 + R2 | Broche à pleine échelle | ESP32 / Pico (3,3 V) : R1 + R2 | Broche à pleine échelle |
|---|---|---|---|---|
| 0–10 V | 12 kΩ + 10 kΩ | 4,55 V | 33 kΩ + 10 kΩ | 2,33 V |
| 0–25 V | 30 kΩ + 7,5 kΩ (module tout fait) | 5,00 V | 100 kΩ + 10 kΩ | 2,27 V |
| 0–30 V | 56 kΩ + 10 kΩ | 4,55 V | 120 kΩ + 10 kΩ | 2,31 V |
| 0–50 V | 100 kΩ + 10 kΩ | 4,55 V | 220 kΩ + 10 kΩ | 2,17 V |
Protection : diode Zener, résistance série et condensateur
Même avec un pont bien calculé, une mauvaise sonde, un pic sur l'alimentation ou un contact accidentel avec 48 V au lieu de 25 V peuvent faire dépasser 5 V à la broche. Les broches de l'ATmega328P supportent au maximum l'alimentation plus 0,5 V. À l'intérieur, des diodes de protection vont vers 5 V et GND, mais elles ne tolèrent que de faibles courants. Bonne nouvelle : la résistance du haut du pont limite déjà le courant. Avec une R1 de 30 kΩ, même en touchant 50 V, il entre au plus environ 1,5 mA dans la broche. Pour réduire encore ce courant et absorber l'excès de tension en sécurité, tu peux ajouter les couches suivantes.
- Résistance série : place une résistance de 4,7–10 kΩ entre le point milieu du pont et la broche analogique. En cas de surtension, le courant vers les diodes internes de la broche tombe à quelques microampères.
- Condensateur de 100 nF : branche-le entre la broche analogique et GND. Il compense la résistance de source plus élevée due à la résistance série, car le CAN prend dans ce condensateur la charge dont il a besoin pendant l'échantillonnage. Il filtre aussi le bruit et les pics brefs.
- Diode Zener de 5,1 V : branche une Zener comme la 1N4733A ou la BZX55C5V1, cathode sur la broche et anode à GND. Quand la tension cherche à dépasser 5,1 V, la Zener conduit et envoie l'excédent vers GND.
- Attention au courant de fuite : une Zener commence à consommer un petit courant un peu avant sa tension de claquage, et avec un pont de forte résistance ce courant fait baisser la mesure. Si tu utilises une Zener, garde le maximum de la broche vers 4 V, ou remplace-la par une diode Schottky (BAT85) de la broche vers le rail 5 V.
- Inversion de polarité : si tu inverses les pointes, une tension négative arrive sur la broche. La résistance série limite le courant ; pour plus de sécurité, ajoute une seconde diode Schottky, anode à GND et cathode sur la broche.
Le module capteur de tension tout fait (0–25 V)
Si tu ne veux pas souder, tu peux utiliser le petit module rouge ou bleu vendu sous le nom de « voltage sensor ». Il n'a rien de magique : un pont formé d'exactement une résistance de 30 kΩ et une de 7,5 kΩ, un bornier à vis et un connecteur à trois broches. Comme le rapport vaut 5, tu mesures 0–25 V avec un Arduino 5 V, mais seulement jusqu'à 16,5 V avec une carte 3,3 V. Sur une carte 3,3 V, toucher 25 V met 5 V sur la broche et l'abîme ; pour l'ESP32 et le Pico, il est donc plus sûr de monter ton propre pont avec le tableau ci-dessus. Le module n'a pas de diode de protection, les précautions Zener ou Schottky de la section précédente s'appliquent aussi.
| Borne du module | Rôle | Arduino Uno | ESP32 (ton propre pont) | Raspberry Pi Pico (ton propre pont) |
|---|---|---|---|---|
| VCC (bornier) | Plus de la source à mesurer | Source + | Extrémité haute de R1 | Extrémité haute de R1 |
| GND (bornier) | Moins de la source à mesurer | Source − | Source − et GND | Source − et GND |
| S | Signal divisé | A0 | GPIO 34 (ADC1) | GP26 (ADC0, broche 31) |
| + | Non connectée sur la plupart des modules | Ne pas brancher | - | - |
| − | GND du module | GND | GND | GND (ex. broche 33) |
Pas à pas : ton premier voltmètre Arduino
- Relie la broche S du module à A0 et la broche − à GND. Si tu montes ton propre pont, mets la 30 kΩ côté source et la 7,5 kΩ côté GND, et amène le point milieu sur A0.
- Branche l'Arduino en USB, mesure au multimètre entre la broche 5V et GND et note la valeur. La tension USB se situe souvent entre 4,7 et 5,1 V.
- Inscris la valeur mesurée dans la constante VREF du code ci-dessous et téléverse-le.
- Branche la source à mesurer sur le bornier du module : plus sur VCC, moins sur GND. Une pile 9 V ou une alimentation réglable est idéale pour un premier essai.
- Ouvre le moniteur série à 9600 bauds. Lis la tension et mesure en même temps la source au multimètre pour comparer les deux valeurs.
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}Le code fait chaque fois la moyenne de 32 lectures : la fluctuation de ±1 pas du CAN disparaît en grande partie et le dernier chiffre se stabilise. La première lecture est ignorée parce que le condensateur d'échantillonnage du CAN garde encore la charge du canal précédent. Arrondir à zéro tout ce qui est sous 0,05 V évite d'afficher des valeurs aléatoires comme 0,02–0,04 V quand rien n'est branché. N'oublie pas que la résolution est de 24,4 mV : même si tu vois deux décimales, le dernier chiffre évolue par pas de 0,02–0,03 V. Pour une résolution plus fine, réduis la plage ; avec un pont 0–10 V, un pas descend à 10,7 mV.
Tension de référence et étalonnage
On dit souvent que les voltmètres Arduino « mesurent faux », mais la vraie source d'erreur est généralement la référence. Si le code indique 5,00 V alors que la carte reçoit 4,80 V par l'USB, chaque mesure est trop haute de 4 % : une batterie de 12,00 V s'affiche à 12,50 V. Cette tension change d'un ordinateur fixe à un portable et d'un câble USB à l'autre, et si tu alimentes la carte par un adaptateur externe, son régulateur prend le relais et la valeur change encore. Il existe trois solutions : mesurer la broche 5V et l'écrire dans le code, utiliser une référence interne fixe, ou recalculer à chaque mesure la tension d'alimentation de la carte.
| Méthode | Code | Avantage | Point de vigilance |
|---|---|---|---|
| Par défaut (AVcc) | analogReference(DEFAULT) | Aucun réglage, pleine échelle 0–5 V | Si l'alimentation varie, la mesure varie aussi |
| Référence interne 1,1 V | analogReference(INTERNAL) | Stable et indépendante de l'alimentation | Varie de 1,0 à 1,2 V selon la carte ; le rapport du pont doit être d'environ 23 (ex. 220 kΩ + 10 kΩ) |
| Référence externe (AREF) | analogReference(EXTERNAL) | Meilleure précision avec une référence comme le LM4040 | Cette ligne doit s'exécuter avant d'appliquer une tension sur AREF, sinon court-circuit avec la référence interne |
| Mesure de l'alimentation (readVcc) | Le code ci-dessous | Aucune pièce en plus, reste juste même si l'USB ou la pile change | Uniquement sur cartes AVR (Uno, Nano, Pro Mini) ; étalonne une fois la valeur de 1,1 V |
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}- Étalonne la référence interne : lance le code readVcc et compare la valeur Vcc du moniteur série avec celle que ton multimètre mesure sur la broche 5V. Nouveau bandgapMv = 1100 × mesuré / affiché. Par exemple, si la carte affiche 5,12 V et le multimètre 4,98 V, inscris 1100 × 4,98 / 5,12 ≈ 1070.
- Étalonnage en un point : applique une tension connue proche du haut de la plage (ex. 12 V). CAL = valeur du multimètre / valeur de l'Arduino. Ce coefficient corrige aussi l'erreur de rapport due à la tolérance des résistances.
- Étalonnage en deux points : si tu constates un décalage constant aux basses tensions, mesure en deux points, un bas (ex. 2 V) et un haut (ex. 20 V). Pente = (M2 − M1) / (A2 − A1), décalage = M1 − pente × A1 ; le résultat est réel = pente × lecture + décalage (M est la valeur du multimètre, A celle de l'Arduino).
- Vérifie : après l'étalonnage, contrôle le résultat avec une troisième tension au milieu de la plage. Un voltmètre Uno monté avec soin mesure 0–25 V avec moins de 1 % d'erreur.
Voltmètre numérique avec écran LCD

Pour rendre le voltmètre indépendant de l'ordinateur, il suffit d'afficher la valeur sur un écran LCD I2C. Relie GND de l'écran à GND, VCC à 5V, SDA à A4 et SCL à A5. Installe la bibliothèque LiquidCrystal I2C (Frank de Brabander) depuis le gestionnaire de bibliothèques. L'adresse de l'écran est généralement 0x27, parfois 0x3F. Le code suivant affiche la tension instantanée sur la ligne du haut et, sur celle du bas, les valeurs minimale et maximale vues depuis la mise sous tension ; tu repères ainsi la chute de tension d'une batterie pendant qu'un moteur tourne.
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}Voltmètre avec un ESP32
L'ESP32 fonctionne en 3,3 V et ses broches ne supportent pas plus de 3,6 V : pour 0–25 V, utilise donc un pont de 100 kΩ + 10 kΩ, qui donne 2,27 V sur la broche pour 25 V en entrée. Branche le pont sur une broche ADC1 (GPIO 32–39) ; les broches ADC2 ne fonctionnent pas quand le Wi-Fi est actif. Le CAN de l'ESP32 est sur 12 bits mais n'est pas linéaire aux extrémités : il ne voit presque rien sous 0,15 V et son erreur augmente au-dessus de 2,5 V. La fonction analogReadMilliVolts() utilise les données d'étalonnage écrites dans la puce en usine et donne un résultat en millivolts bien plus juste que la valeur brute. Pour supprimer le décalage restant, le code applique l'étalonnage en deux points de la section précédente avec les constantes GAIN et OFFSET.
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}Voltmètre avec un Raspberry Pi Pico (MicroPython)
Sur le Raspberry Pi Pico, les entrées analogiques sont GP26, GP27 et GP28. Branche sur GP26 le même pont de 100 kΩ + 10 kΩ que sur l'ESP32. En MicroPython, read_u16() renvoie le résultat 12 bits mis à l'échelle sur 0–65535. La référence du CAN du Pico est filtrée depuis le rail 3,3 V ; pour plus de précision, mesure entre ADC_VREF (broche 35) et GND au multimètre et inscris la valeur dans VREF. Le code contient un bonus : sur le Pico standard, GP29 (ADC3) est relié à un pont interne qui divise par 3 l'entrée d'alimentation VSYS. Sans aucune pièce supplémentaire, tu lis donc aussi la tension de la batterie qui alimente le Pico. Sur le Pico W et le Pico 2 W, GP29 est partagée avec la puce sans fil, cette ligne n'y fonctionne donc pas directement.
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)Ajouter le courant pour faire un wattmètre : ACS712 ou INA219

En ajoutant une mesure de courant à un voltmètre, tu obtiens aussi la puissance : P = U × I. Si une batterie de 12 V débite 1,5 A, la puissance vaut 18 W. En additionnant la puissance dans le temps, tu obtiens l'énergie : une charge de 18 W qui fonctionne 2 heures consomme 36 Wh. Deux options courantes existent. L'ACS712 a une sortie analogique, mesure aussi le courant alternatif et assure une isolation ; il devient simplement une deuxième voie analogique de ton voltmètre. L'INA219 est un wattmètre continu qui mesure tension et courant dans la même puce avec une précision de 12 bits et communique en I2C ; à lui seul, c'est déjà un wattmètre complet.
| Caractéristique | Module de tension + ACS712 (5A) | Module INA219 |
|---|---|---|
| Plage de tension | 0–25 V (fixée par le pont) | 0–26 V (dans la puce) |
| Plage de courant | ±5 A | ±3,2 A (avec un shunt de 0,1 Ω) |
| Résolution en courant | Environ 26 mA sur un Uno | 0,1 mA |
| Courant alternatif | Oui | Non |
| Connexion | Deux broches analogiques | I2C (SDA, SCL), adresse 0x40 |
| Idéal pour | Moteurs, courant côté secteur et cas où l'isolation est nécessaire | Petites puissances continues : batteries, panneaux solaires, appareils USB |
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}L'INA219 calcule le courant à partir de la petite chute de tension aux bornes du shunt de 0,1 Ω placé entre VIN+ et VIN− ; le module se branche donc en série, côté positif de la source (côté haut). Comme la tension de bus est mesurée entre VIN− et GND, le code y ajoute la chute du shunt pour obtenir la vraie tension de la source. L'étalonnage par défaut vise 32 V et 2 A ; si tu ne mesures que quelques centaines de milliampères, active la ligne setCalibration_16V_400mA() pour réduire la plage à 400 mA et gagner en précision sur les petits courants. L'énergie s'obtient en additionnant à chaque boucle la puissance du moment multipliée par le temps écoulé ; elle repart à zéro à l'extinction de l'Arduino, donc pour la conserver, écris la valeur régulièrement en EEPROM. Le code qui fait le même calcul avec l'ACS712 se trouve dans la partie puissance et énergie de l'article sur l'ACS712.
Testeur de batterie : un voltmètre qui mesure la capacité (mAh)

La tension d'une batterie ne dit pas exactement combien d'énergie il lui reste ; un élément chargé mais fatigué peut aussi afficher 4,1 V. Pour connaître la capacité réelle, on décharge la batterie dans une charge connue et on additionne le courant au fil du temps : mAh = Σ (courant × temps). Dans ce montage, un MOSFET commute la charge, et l'Arduino mesure chaque seconde la tension de la batterie et celle du bas de la résistance de charge. La différence entre les deux, divisée par la résistance de charge, donne le courant. Quand la batterie atteint sa tension de coupure, le MOSFET se bloque et le résultat s'affiche. Au départ, le code compare aussi la tension à vide et en charge pour calculer la résistance interne ; plus elle est élevée, plus la tension s'effondre à fort courant.
| Composant | Connexion | Remarque |
|---|---|---|
| Batterie + | Vers A0 via 10 kΩ ; aussi le haut de la résistance de charge | Mets 100 nF entre A0 et GND |
| Résistance de charge 4,7 Ω | Entre batterie + et le drain du MOSFET | Résistance céramique d'au moins 5 W (idéalement 10 W) ; avec une 18650 il passe environ 0,9 A et elle chauffe |
| Drain du MOSFET | Bas de la résistance de charge ; vers A1 via 10 kΩ | Mets aussi 100 nF entre A1 et GND |
| Source du MOSFET | GND | Le moins de la batterie se branche ici aussi |
| Grille du MOSFET | Vers D9 via 220 Ω ; vers GND via 100 kΩ | Utilise un MOSFET à niveau logique comme l'IRLZ44N |
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}Avec une charge de 4,7 Ω, un élément 18650 se décharge sous un courant qui commence vers 0,9 A et descend vers 0,65 A ; tester un élément sain de 2500 mAh prend environ trois heures. Pour le Li-ion, ne règle jamais la coupure sous 3,0 V, sinon l'élément s'abîme. Si tu testes une pile alcaline AA, mets CUTOFF_V à 0,9 V ; elle débite environ 0,3 A avec la même charge. Tu peux comparer le résultat avec l'étiquette et avec le calculateur d'autonomie de batterie. La résistance interne d'une 18650 neuve mesurée ainsi, support et fils compris, est généralement inférieure à 0,15 Ω ; un élément au-delà de 0,3 Ω ne devrait pas servir aux usages à fort courant. Pour comprendre les unités de capacité, jette un œil à l'article sur les mAh et la capacité des batteries.
Idées de projets avec un voltmètre Arduino
- Surveillance de batterie avec alarme de sous-tension : surveille la batterie 12 V d'un camping-car ou d'une installation solaire et fais sonner un buzzer quand elle passe sous 11,8 V.
- Enregistreur de panneau solaire : écris chaque minute sur une carte SD la tension du panneau et, avec l'INA219, son courant, puis calcule la production journalière en Wh.
- Affichage d'alimentation de labo : ajoute un voltmètre et un INA219 à la sortie d'un module LM2596 pour en faire une alimentation d'établi.
- Suivi de batterie à distance : envoie la tension mesurée par un ESP32 vers Home Assistant en MQTT, ou reçois un message Telegram quand elle est basse.
- Contrôle de pack 18650 : teste la capacité des éléments que tu charges avec un TP4056 et associe des éléments de capacité proche pour un pack équilibré.
- Afficheur à gros chiffres : affiche la valeur sur un afficheur 7 segments ou un écran OLED plutôt que sur le LCD, assez grand pour être lu de loin.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| La mesure est toujours trop haute ou trop basse de 2–5 % | VREF vaut 5,00 V dans le code mais la carte est alimentée sous une autre tension | Mesure la broche 5V et inscris-la dans VREF, ou utilise la méthode readVcc |
| La valeur saute sans arrêt | Le moins de la source n'est pas relié au GND de l'Arduino ou la ligne est bruitée | Relie une masse commune, fais une moyenne, ajoute 100 nF sur la broche |
| Bloquée à la même valeur en haute tension | La broche a atteint la référence et le CAN est saturé à 1023 | Élargis la plage en augmentant le rapport du pont |
| La mesure s'infléchit en haut et n'est pas linéaire | Fuite de la Zener ou haut de l'échelle du CAN de l'ESP32 | Garde la broche sous 4 V (2,5 V sur l'ESP32) ou utilise une Schottky |
| Sur l'ESP32, la mesure passe à 0 ou se fige dès que le Wi-Fi démarre | Le pont est sur une broche ADC2 | Utilise une broche ADC1, GPIO 32–39 |
| L'INA219 affiche un courant négatif | VIN+ et VIN− sont inversées | Le plus de la source va sur VIN+, le plus de la charge sur VIN− |
| L'écran LCD s'allume mais n'affiche rien | Mauvaise adresse I2C ou contraste mal réglé | Trouve l'adresse avec un scanner I2C et tourne le potentiomètre au dos |
Un voltmètre Arduino est l'un des meilleurs moyens de comprendre la mesure : avec deux résistances, une formule et un peu d'étalonnage, tu obtiens des résultats proches d'un multimètre ; ajoute un capteur de courant et il devient wattmètre, ajoute un MOSFET et il devient testeur de batterie. Dans l'application BlueGrays, le projet « Voltmètre numérique avec LCD » te permet de monter le même circuit pas à pas avec le schéma et le code prêt à l'emploi, puis de passer aux projets de surveillance de batterie et de mesure de puissance.
Questions fréquentes
Combien de volts un Arduino peut-il mesurer ?
On peut appliquer directement au maximum 5 V sur une broche analogique (3,3 V sur l'ESP32 et le Pico). Avec un pont diviseur, cette limite peut être repoussée autant que nécessaire : 30 kΩ + 7,5 kΩ mesurent 25 V, 100 kΩ + 10 kΩ mesurent 50 V. Au-delà de quelques dizaines de volts, la sécurité et l'isolation deviennent toutefois essentielles, et la tension secteur ne se mesure jamais ainsi.
Pourquoi mon voltmètre Arduino mesure-t-il faux ?
La cause la plus fréquente est la tension de référence : le code indique 5,00 V mais la carte reçoit 4,7–4,9 V par l'USB, et toutes les mesures se décalent dans la même proportion. D'autres causes sont les résistances à 5 %, l'absence de masse commune et un pont trop résistif. Il suffit de mesurer la broche 5V et de l'inscrire dans le code, ou d'utiliser la méthode readVcc, puis de régler le coefficient CAL avec une tension connue.
Peut-on utiliser le module capteur de tension 0–25 V avec un ESP32 ?
Oui, mais avec prudence. Comme le module divise par 5, un ESP32 ne peut mesurer que jusqu'à 16,5 V avec lui ; à 25 V, la broche reçoit 5 V et l'ESP32 est endommagé. Monter ton propre pont de 100 kΩ + 10 kΩ est plus sûr et plus précis, car le CAN reste dans sa zone linéaire.
Peut-on mesurer la tension secteur 230 V avec un Arduino ?
Jamais avec un pont diviseur : c'est potentiellement mortel et l'Arduino se retrouve relié au secteur. Pour la tension secteur, on utilise un module comme le ZMPT101B, qui contient un petit transformateur et assure l'isolation galvanique. Sa sortie est alternative, le code calcule donc la valeur efficace (RMS).
Un Arduino peut-il mesurer une tension négative ?
Pas directement ; une broche analogique ne lit rien sous GND et peut être endommagée. La solution consiste à décaler le signal vers 5 V avec des résistances : par exemple, deux résistances égales entre le signal et 5 V créent un point milieu qui ramène la plage −5 V à +5 V sur 0–5 V. Pour un travail plus précis, on utilise un décaleur de niveau à amplificateur opérationnel.
Un voltmètre Arduino peut-il être aussi précis qu'un multimètre ?
Un voltmètre Uno étalonné mesure 0–25 V avec moins de 1 % d'erreur, ce qui suffit pour la plupart des projets et se rapproche d'un multimètre d'entrée de gamme. À cause du CAN 10 bits, la résolution est limitée à environ 24 mV sur une plage de 25 V. Pour faire mieux, utilise un CAN externe 16 bits comme l'ADS1115, des résistances à 0,1 % et une référence de précision.
Projets à réaliser après cet article
Voir tous les projets
Mesurer l'intensité lumineuse avec une LDR
Envie de voir en chiffres à quel point ta chambre est lumineuse ? Le LDR, une petite pièce sensible à la lumière, mesure la lumière ambiante, et l'Arduino écrit la valeur sur l'écran de ton ordinateur

Mesure de l'intensité lumineuse avec le module LDR ESP32
Suivi en temps réel sur le moniteur série de la valeur brute de l'ADC du module LDR et du pourcentage relatif de luminosité calculé à partir de références dans l'obscurité et à la lumière. Ce pourcentage n'est pas une mesure en lux. Permet de comprendre le principe de calibrage du module. Il est préférable de réaliser cet exercice avant le projet 10, car il sert à déterminer la valeur seuil.

Voltmètre numérique avec écran LCD
Découvre quelle tension fournit une pile ou un adaptateur avec un appareil de mesure fait maison. Un diviseur de deux résistances abaisse la tension élevée à un niveau que la carte peut lire, et l'Ard

Mesure de la température avec NTC et écran LCD 2x16
Mesure la température ambiante avec un capteur qui ressemble à une petite perle. Cette pièce, appelée NTC, laisse passer l'électricité de plus en plus facilement en chauffant ; l'Arduino lit ce change

Utilisation de l'écran LCD avec I2C
Offre un écran à ton Arduino et fais-lui écrire son premier message. L'écran LCD à deux lignes se branche avec seulement quelques fils ; un bonjour s'affiche sur la ligne du haut, puis un deuxième tex

Écran LCD I2C ESP32 (16x2)
Dans ce projet, nous affichons du texte en connectant un écran LCD 16x2 à l'ESP32 via le protocole I2C. Grâce à l'I2C, nous pouvons contrôler l'écran avec seulement 2 broches de données (SDA et SCL) ; cela évite le gaspillage de 6 broches ou plus inhérent à la connexion parallèle classique. Le code affiche un message fixe sur la première ligne et un compteur qui augmente chaque seconde sur la deuxième ligne. De plus, au démarrage, nous lançons un scanner I2C pour afficher l'adresse de l'écran su

Mesure de la distance à l'aide d'un écran LCD
Un appareil qui mesure les distances sans règle : avance et recule ta main devant le capteur et regarde le nombre changer. Le HC-SR04 envoie une onde sonore et écoute son écho, puis l'Arduino calcule

Luminosité d'une LED avec un Potentiomètre sur ESP32 (Analogique → PWM)
Dans ce projet, nous contrôlons la luminosité d'une LED de manière analogique à l'aide d'un potentiomètre. La broche ADC de l'ESP32 lit la tension entre 0 et 3,3 V provenant du potentiomètre, puis cette valeur est convertie en signal PWM (modulation de largeur d'impulsion) envoyé à la LED. Ainsi, la LED s'allume et s'éteint progressivement. Avec Arduino Core 3.0+, analogWrite() est utilisable directement; sur ESP32-S2/S3, la résolution de l'ADC est fixée à 12 bits.
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 200 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

