Guides · 16 min de lecture

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.

Voltmètre numérique
Le voltmètre que tu fabriques avec un Arduino peut afficher la tension avec deux décimales, comme ces afficheurs de tableau.

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.

CarteCANRéférence1 pas sur la broche1 pas avec un pont 0–25 V
Arduino Uno, Nano, Pro Mini10 bits (0–1023)5 V (AVcc)4,88 mV24,4 mV (30 kΩ + 7,5 kΩ)
ESP3212 bits (0–4095)Environ 3,3 V (atténuation 11 dB)Environ 0,8 mVEnviron 9 mV (100 kΩ + 10 kΩ)
Raspberry Pi Pico12 bits (0–65535 via read_u16)3,3 V (ADC_VREF)0,81 mV8,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.

PlageArduino Uno (5 V) : R1 + R2Broche à pleine échelleESP32 / Pico (3,3 V) : R1 + R2Broche à pleine échelle
0–10 V12 kΩ + 10 kΩ4,55 V33 kΩ + 10 kΩ2,33 V
0–25 V30 kΩ + 7,5 kΩ (module tout fait)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
Au lieu de calculer le rapport à la main pour ta plage, tu peux utiliser le calculateur de pont diviseur. Dans les colonnes ESP32 et Pico, nous avons volontairement gardé la broche sous 2,5 V, car le CAN de l'ESP32 perd sa linéarité en haut de l'échelle. Préfère des résistances à couche métallique à 1 % ; deux résistances à 5 % peuvent décaler le rapport d'environ 10 % dans le pire des cas.

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.
Ce voltmètre est réservé au continu et aux basses tensions (quelques dizaines de volts au maximum). N'essaie jamais de mesurer le secteur 230 V avec deux résistances : c'est potentiellement mortel et la masse de l'Arduino se retrouve reliée au secteur. Pour la tension secteur, on utilise un module à transformateur isolé galvaniquement comme le ZMPT101B. De plus, le moins de la source mesurée doit être relié au GND de l'Arduino ; sans masse commune, la mesure n'a aucun sens.

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 moduleRôleArduino UnoESP32 (ton propre pont)Raspberry Pi Pico (ton propre pont)
VCC (bornier)Plus de la source à mesurerSource +Extrémité haute de R1Extrémité haute de R1
GND (bornier)Moins de la source à mesurerSource −Source − et GNDSource − et GND
SSignal diviséA0GPIO 34 (ADC1)GP26 (ADC0, broche 31)
+Non connectée sur la plupart des modulesNe pas brancher--
−GND du moduleGNDGNDGND (ex. broche 33)

Pas à pas : ton premier voltmètre Arduino

  1. 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.
  2. 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.
  3. Inscris la valeur mesurée dans la constante VREF du code ci-dessous et téléverse-le.
  4. 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.
  5. 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.
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}

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éthodeCodeAvantagePoint de vigilance
Par défaut (AVcc)analogReference(DEFAULT)Aucun réglage, pleine échelle 0–5 VSi l'alimentation varie, la mesure varie aussi
Référence interne 1,1 VanalogReference(INTERNAL)Stable et indépendante de l'alimentationVarie 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 LM4040Cette 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-dessousAucune pièce en plus, reste juste même si l'USB ou la pile changeUniquement sur cartes AVR (Uno, Nano, Pro Mini) ; étalonne une fois la valeur de 1,1 V
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. É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.
  2. É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.
  3. É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).
  4. 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

Écran LCD 16x2 I2C
Grâce au module I2C au dos, l'écran LCD 16x2 se branche avec seulement quatre fils : GND, VCC, SDA et SCL.

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.

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}

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.

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}

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.

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)

Ajouter le courant pour faire un wattmètre : ACS712 ou INA219

Module capteur de courant ACS712
L'ACS712 mesure le courant par effet Hall et isole électriquement le circuit mesuré de l'Arduino.

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éristiqueModule de tension + ACS712 (5A)Module INA219
Plage de tension0–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 courantEnviron 26 mA sur un Uno0,1 mA
Courant alternatifOuiNon
ConnexionDeux broches analogiquesI2C (SDA, SCL), adresse 0x40
Idéal pourMoteurs, courant côté secteur et cas où l'isolation est nécessairePetites puissances continues : batteries, panneaux solaires, appareils USB
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}

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)

Accumulateur Li-ion 18650
La capacité imprimée sur un élément 18650 et sa capacité réelle diffèrent souvent ; le testeur révèle la vérité.

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.

ComposantConnexionRemarque
Batterie +Vers A0 via 10 kΩ ; aussi le haut de la résistance de chargeMets 100 nF entre A0 et GND
Résistance de charge 4,7 ΩEntre batterie + et le drain du MOSFETRé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 MOSFETBas de la résistance de charge ; vers A1 via 10 kΩMets aussi 100 nF entre A1 et GND
Source du MOSFETGNDLe moins de la batterie se branche ici aussi
Grille du MOSFETVers D9 via 220 Ω ; vers GND via 100 kΩUtilise un MOSFET à niveau logique comme l'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}

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.

Ne court-circuite jamais un élément Li-ion et ne pose pas la résistance de charge sur une surface inflammable ; une résistance qui dissipe environ 4 W peut atteindre 80–100 °C. Ne laisse pas le test sans surveillance et ne teste jamais un élément gonflé ou cabossé.

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ômeCause probableSolution
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 tensionMesure la broche 5V et inscris-la dans VREF, ou utilise la méthode readVcc
La valeur saute sans arrêtLe moins de la source n'est pas relié au GND de l'Arduino ou la ligne est bruitéeRelie une masse commune, fais une moyenne, ajoute 100 nF sur la broche
Bloquée à la même valeur en haute tensionLa 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éaireFuite de la Zener ou haut de l'échelle du CAN de l'ESP32Garde 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émarreLe pont est sur une broche ADC2Utilise une broche ADC1, GPIO 32–39
L'INA219 affiche un courant négatifVIN+ et VIN− sont inverséesLe plus de la source va sur VIN+, le plus de la charge sur VIN−
L'écran LCD s'allume mais n'affiche rienMauvaise adresse I2C ou contraste mal régléTrouve l'adresse avec un scanner I2C et tourne le potentiomètre au dos
Avant de brancher un nouveau pont sur l'Arduino, allume la source et mesure la tension du point milieu au multimètre. Si elle est proche du calcul et sous la référence, tu peux la relier à la broche sans risque. Ce contrôle de dix secondes évite que deux résistances inversées grillent ta carte.

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.

Voir tous les projets
Mesurer l'intensité lumineuse avec une LDR
#11Débutant

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

4.6(81)
139
Mesure de l'intensité lumineuse avec le module LDR ESP32
#113Débutant

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.

4.6(36)
55
Voltmètre numérique avec écran LCD
#56Intermédiaire
Premium

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

4.5(27)
36
Mesure de la température avec NTC et écran LCD 2x16
#44Débutant
Premium

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

4.5(33)
44
Utilisation de l'écran LCD avec I2C
#32Débutant
Premium

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

4.8(53)
70
Écran LCD I2C ESP32 (16x2)
#119Intermédiaire
Premium

É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

4.9(23)
40
Mesure de la distance à l'aide d'un écran LCD
#31Avancé
Premium

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

4.6(45)
59
Luminosité d'une LED avec un Potentiomètre sur ESP32 (Analogique → PWM)
#115Intermédiaire
Premium

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.

4.5(19)
32