Guías · 16 min de lectura

Voltímetro con Arduino: medir 0–25 V con LCD y calibración

Cómo hacer un voltímetro con Arduino: medir 0–25 V con divisor, elegir resistencias, protección zener, calibración, LCD, vatímetro INA219 y probador.

Un voltímetro con Arduino es un instrumento de medida que puedes montar en una tarde: dos resistencias, una entrada analógica y unas pocas líneas de código bastan para medir con precisión de 0 a 25 V y mostrarlo en una pantalla. Las entradas analógicas de Arduino leen como máximo 5 V, así que para medir una tensión mayor primero la reduces con un divisor de voltaje y luego la vuelves a escalar en el código con la misma relación. Los monitores de batería, los indicadores de fuentes de alimentación, los registradores de paneles solares y los probadores de pilas se basan en esta misma idea.

En esta guía verás paso a paso cómo elegir las resistencias según el rango de medida, cómo un diodo zener y una resistencia en serie protegen la entrada analógica de sobretensiones, cómo funciona el módulo sensor de voltaje de 0–25 V y cómo el ajuste de la tensión de referencia y la calibración acercan tus lecturas a las de un multímetro. Después mostrarás el valor en una pantalla LCD I2C, montarás el mismo voltímetro con un ESP32 y una Raspberry Pi Pico, añadirás medición de corriente con un INA219 para convertirlo en vatímetro y, por último, construirás un probador que mide la capacidad real de una batería en mAh.

Voltímetro digital
El voltímetro que montes con Arduino puede mostrar la tensión con dos decimales, igual que estos indicadores de panel.

¿Cómo funciona un voltímetro con Arduino?

Arduino no conoce la tensión directamente: su ADC (convertidor analógico-digital) compara la tensión de la entrada analógica con una tensión de referencia y devuelve el resultado como un número entero. El ADC del Arduino Uno es de 10 bits: lee 0 para 0 V y 1023 para la tensión de referencia (5 V por defecto). La tensión en el pin es Vpin = lectura × Vref / 1024. Si hay un divisor de voltaje en la entrada, la tensión que realmente mides es Vent = Vpin × (R1 + R2) / R2. Así que la precisión de todo el voltímetro depende de tres cosas: el valor real de Vref, la relación entre las dos resistencias y el error propio del ADC.

PlacaADCReferencia1 paso en el pin1 paso con divisor de 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)Unos 3,3 V (atenuación de 11 dB)Unos 0,8 mVUnos 9 mV (100 kΩ + 10 kΩ)
Raspberry Pi Pico12 bits (0–65535 con read_u16)3,3 V (ADC_VREF)0,81 mV8,9 mV (100 kΩ + 10 kΩ)

Divisor de voltaje y elección de resistencias para 0–25 V

La tensión que mides entra por la resistencia superior R1, el punto medio donde se unen las dos resistencias va al pin analógico y la resistencia inferior R2 va a GND. Para elegirlas, primero decide la tensión máxima y luego busca una relación que deje el pin un poco por debajo de la referencia a esa tensión, por ejemplo unos 4,5 V en un Uno. La pareja de 30 kΩ y 7,5 kΩ de los módulos comerciales divide exactamente entre 5: 25 V en la entrada dan 5,00 V en el pin. Tampoco elijas los valores al azar: si la resistencia total es muy baja, el divisor consume corriente inútilmente de la fuente que mides; si es muy alta, el condensador de muestreo interno del ADC no llega a cargarse y la lectura se desvía. La hoja de datos del ATmega328P recomienda que la fuente que alimenta una entrada analógica no supere los 10 kΩ; en un divisor, esa resistencia es R1 en paralelo con R2 (6 kΩ para 30 kΩ y 7,5 kΩ). La fórmula en detalle y el efecto de carga están en el artículo sobre el divisor de voltaje.

RangoArduino Uno (5 V): R1 + R2Pin a fondo de escalaESP32 / Pico (3,3 V): R1 + R2Pin a fondo de escala
0–10 V12 kΩ + 10 kΩ4,55 V33 kΩ + 10 kΩ2,33 V
0–25 V30 kΩ + 7,5 kΩ (módulo comercial)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
En lugar de calcular la relación a mano para tu rango, puedes usar la calculadora de divisor de voltaje. En las columnas de ESP32 y Pico hemos mantenido a propósito el pin por debajo de 2,5 V, porque el ADC del ESP32 pierde linealidad en la parte alta. Usa resistencias de película metálica al 1 %; dos resistencias del 5 % pueden desplazar la relación cerca de un 10 % en el peor caso.

Protección: diodo zener, resistencia en serie y condensador

Aunque el divisor esté bien calculado, una punta equivocada, un pico en la fuente o tocar por error 48 V en lugar de 25 V pueden subir el pin por encima de 5 V. Los pines del ATmega328P soportan como máximo la alimentación más 0,5 V. Dentro del pin hay diodos de protección hacia 5 V y GND, pero solo aguantan corrientes pequeñas. La buena noticia es que la resistencia superior del divisor ya limita la corriente. Con una R1 de 30 kΩ, aunque toques 50 V, al pin le llega como mucho 1,5 mA. Para reducir aún más esa corriente y absorber el exceso de tensión con seguridad, puedes añadir estas capas.

  • Resistencia en serie: Coloca una resistencia de 4,7–10 kΩ entre el punto medio del divisor y el pin analógico. Ante una sobretensión, la corriente hacia los diodos internos del pin baja a microamperios.
  • Condensador de 100 nF: Conéctalo entre el pin analógico y GND. Compensa la mayor resistencia de fuente que añade la resistencia en serie, porque el ADC toma de este condensador la carga que necesita al muestrear. Además filtra el ruido y los picos cortos.
  • Diodo zener de 5,1 V: Conecta un zener como el 1N4733A o el BZX55C5V1 con el cátodo al pin y el ánodo a GND. Cuando la tensión intenta superar 5,1 V, el zener conduce y desvía el exceso a GND.
  • Cuidado con la fuga del zener: Un zener empieza a consumir una pequeña corriente algo por debajo de su tensión de ruptura, y con un divisor de alta resistencia esa corriente baja la lectura. Si usas zener, mantén el máximo del pin en torno a 4 V, o usa en su lugar un diodo Schottky (BAT85) del pin a la línea de 5 V.
  • Polaridad invertida: Si conectas las puntas al revés, al pin le llega tensión negativa. La resistencia en serie limita la corriente; para más seguridad puedes añadir un segundo diodo Schottky con el ánodo a GND y el cátodo al pin.
Este voltímetro es solo para corriente continua y baja tensión (unas decenas de voltios como máximo). Nunca intentes medir la red de 230 V con dos resistencias: es potencialmente mortal y además conecta el GND de Arduino a la red. Para la tensión de red se usa un módulo con transformador y aislamiento galvánico, como el ZMPT101B. Además, el negativo de la fuente que mides debe estar unido al GND de Arduino; sin una masa común la lectura no tiene sentido.

El módulo sensor de voltaje (0–25 V)

Si no quieres soldar, puedes usar el pequeño módulo rojo o azul que se vende como "voltage sensor". No tiene nada mágico: un divisor formado por exactamente una resistencia de 30 kΩ y otra de 7,5 kΩ, una bornera de tornillo y un conector de tres pines. Como la relación es 5, con un Arduino de 5 V mides de 0 a 25 V, pero con una placa de 3,3 V solo hasta 16,5 V. En una placa de 3,3 V, tocar 25 V pone 5 V en el pin y lo daña, así que para ESP32 y Pico es más seguro montar tu propio divisor de la tabla anterior. El módulo no lleva diodo de protección, por lo que las medidas con zener o Schottky de la sección anterior también se aplican aquí.

Pin del móduloFunciónArduino UnoESP32 (tu propio divisor)Raspberry Pi Pico (tu propio divisor)
VCC (bornera)Positivo de la fuente a medirFuente +Extremo superior de R1Extremo superior de R1
GND (bornera)Negativo de la fuente a medirFuente −Fuente − y GNDFuente − y GND
SSeñal divididaA0GPIO 34 (ADC1)GP26 (ADC0, pin 31)
+Sin conexión en la mayoría de módulosNo conectar--
−GND del móduloGNDGNDGND (p. ej. pin 33)

Paso a paso: tu primer voltímetro con Arduino

  1. Conecta el pin S del módulo a A0 y el pin − a GND. Si montas tu propio divisor, pon la de 30 kΩ del lado de la fuente y la de 7,5 kΩ del lado de GND, y lleva el punto medio a A0.
  2. Conecta el Arduino por USB, mide con el multímetro entre el pin 5V y GND y apunta el valor. La tensión del USB suele estar entre 4,7 y 5,1 V.
  3. Escribe el valor medido en la constante VREF del código de abajo y súbelo.
  4. Conecta la fuente que quieres medir a la bornera del módulo: positivo a VCC, negativo a GND. Para la primera prueba va perfecta una pila de 9 V o una fuente regulable.
  5. Abre el Monitor Serie a 9600 baudios. Lee la tensión y, al mismo tiempo, mide la fuente con el multímetro y compara los dos valores.
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}

El código promedia 32 lecturas cada vez, así que la oscilación de ±1 paso del ADC casi desaparece y el último dígito se estabiliza. La primera lectura se descarta porque el condensador de muestreo del ADC aún conserva carga del canal anterior. Redondear a cero todo lo que esté por debajo de 0,05 V evita que aparezcan valores aleatorios como 0,02–0,04 V cuando no hay nada conectado. Recuerda que la resolución es de 24,4 mV: aunque veas dos decimales, el último dígito cambia en pasos de 0,02–0,03 V. Si necesitas más resolución, reduce el rango; con un divisor de 0–10 V un paso baja a 10,7 mV.

Tensión de referencia y calibración

Se suele decir que los voltímetros con Arduino "miden mal", pero la fuente real del error casi siempre es la referencia. Si en el código pone 5,00 V y la placa recibe 4,80 V del USB, cada lectura sale un 4 % alta: una batería de 12,00 V aparece como 12,50 V. Esta tensión cambia de un ordenador de sobremesa a un portátil y de un cable USB a otro, y si alimentas la placa con un adaptador externo entra en juego su regulador y el valor vuelve a cambiar. Hay tres soluciones: medir el pin 5V y escribirlo en el código, usar una referencia interna fija o recalcular en cada medida la tensión de alimentación de la propia placa.

MétodoCódigoVentajaTen en cuenta
Por defecto (AVcc)analogReference(DEFAULT)Sin configuración, rango completo de 0–5 VLo que haga la alimentación lo hará también la lectura
Referencia interna de 1,1 VanalogReference(INTERNAL)Estable e independiente de la alimentaciónVaría entre 1,0 y 1,2 V según la placa; la relación del divisor debe ser de unos 23 (p. ej. 220 kΩ + 10 kΩ)
Referencia externa (AREF)analogReference(EXTERNAL)La mejor precisión con una referencia como el LM4040Esta línea debe ejecutarse antes de aplicar tensión a AREF, o habrá un cortocircuito con la referencia interna
Medir la alimentación (readVcc)El código de abajoSin piezas extra, sigue siendo preciso aunque cambie el USB o la pilaSolo funciona en placas AVR (Uno, Nano, Pro Mini); calibra una vez el valor 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. Calibra la referencia interna: Ejecuta el código readVcc y compara el valor de Vcc del Monitor Serie con lo que mide tu multímetro en el pin 5V. Nuevo bandgapMv = 1100 × medido / mostrado. Por ejemplo, si la placa muestra 5,12 V y el multímetro 4,98 V, escribe 1100 × 4,98 / 5,12 ≈ 1070.
  2. Calibración de un punto: Conecta una tensión conocida cerca del máximo del rango (p. ej. 12 V). CAL = valor del multímetro / valor de Arduino. Este factor también corrige el error de relación por la tolerancia de las resistencias.
  3. Calibración de dos puntos: Si ves un desplazamiento fijo en tensiones bajas, mide en dos puntos, uno bajo (p. ej. 2 V) y otro alto (p. ej. 20 V). Pendiente = (M2 − M1) / (A2 − A1), desplazamiento = M1 − pendiente × A1; el resultado es real = pendiente × lectura + desplazamiento (M es el valor del multímetro y A el de Arduino).
  4. Comprueba: Después de calibrar, verifica el resultado con una tercera tensión en mitad del rango. Un voltímetro con Uno montado con cuidado mide de 0 a 25 V con menos de un 1 % de error.

Voltímetro digital con pantalla LCD

Pantalla LCD 16x2 I2C
Gracias al módulo I2C trasero, la LCD 16x2 se conecta con solo cuatro cables: GND, VCC, SDA y SCL.

Para que el voltímetro no dependa del ordenador, basta con mostrar el valor en una pantalla LCD I2C. Conecta GND de la LCD a GND, VCC a 5V, SDA a A4 y SCL a A5. Instala desde el Gestor de Bibliotecas la biblioteca LiquidCrystal I2C (Frank de Brabander). La dirección de la pantalla suele ser 0x27, o 0x3F en algunos módulos. El código siguiente muestra la tensión actual en la línea superior y, en la inferior, los valores mínimo y máximo desde el encendido; así también captas la caída de tensión de una batería mientras funciona un motor.

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}

Voltímetro con ESP32

El ESP32 funciona a 3,3 V y sus pines no aguantan más de 3,6 V, así que para 0–25 V usa un divisor de 100 kΩ + 10 kΩ: 25 V en la entrada dan 2,27 V en el pin. Conecta el divisor a uno de los pines ADC1 (GPIO 32–39); los pines ADC2 no funcionan mientras el Wi-Fi está activo. El ADC del ESP32 es de 12 bits, pero no es lineal en los extremos: apenas ve nada por debajo de 0,15 V y su error crece por encima de 2,5 V. La función analogReadMilliVolts() usa datos de calibración grabados en el chip de fábrica y da un resultado en milivoltios mucho más preciso que el valor en bruto. Para eliminar el desplazamiento restante, el código aplica la calibración de dos puntos de la sección anterior con las constantes GAIN y 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}

Voltímetro con Raspberry Pi Pico (MicroPython)

En la Raspberry Pi Pico las entradas analógicas son GP26, GP27 y GP28. Conecta a GP26 el mismo divisor de 100 kΩ + 10 kΩ que en el ESP32. En MicroPython, read_u16() devuelve el resultado de 12 bits escalado a 0–65535. La referencia del ADC de la Pico se obtiene filtrando la línea de 3,3 V; para más precisión, mide entre ADC_VREF (pin 35) y GND con el multímetro y escribe el valor en VREF. El código trae además un extra: en la Pico estándar, GP29 (ADC3) está conectado a un divisor interno que divide entre 3 la entrada de alimentación VSYS. Así, sin ninguna pieza más, también lees la tensión de la batería que alimenta la Pico. En la Pico W y la Pico 2 W, GP29 se comparte con el chip inalámbrico, por lo que esta línea no funciona directamente en esas placas.

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)

Añadir corriente para hacer un vatímetro: ACS712 o INA219

Módulo sensor de corriente ACS712
El ACS712 mide la corriente por efecto Hall y mantiene el circuito medido aislado eléctricamente del Arduino.

Cuando añades medición de corriente a un voltímetro, también obtienes la potencia: P = V × I. Si una batería de 12 V entrega 1,5 A, la potencia es de 18 W. Si sumas la potencia a lo largo del tiempo, obtienes la energía: una carga de 18 W que funciona 2 horas consume 36 Wh. Hay dos opciones habituales. El ACS712 tiene salida analógica, mide también corriente alterna y ofrece aislamiento; se añade al voltímetro como un segundo canal analógico. El INA219 es un medidor de potencia de continua que mide tensión y corriente en el mismo chip con 12 bits de precisión y se comunica por I2C; por sí solo ya es un vatímetro completo.

CaracterísticaMódulo de voltaje + ACS712 (5A)Módulo INA219
Rango de tensión0–25 V (según el divisor)0–26 V (dentro del chip)
Rango de corriente±5 A±3,2 A (con shunt de 0,1 Ω)
Resolución de corrienteUnos 26 mA en un Uno0,1 mA
Corriente alternaSíNo
ConexiónDos pines analógicosI2C (SDA, SCL), dirección 0x40
Ideal paraMotores, corriente del lado de red y donde haga falta aislamientoPequeñas potencias de continua: baterías, paneles solares y dispositivos 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}

El INA219 calcula la corriente a partir de la pequeña caída de tensión en la resistencia shunt de 0,1 Ω entre VIN+ y VIN−, por eso el módulo se conecta en serie en el lado positivo de la fuente (lado alto). Como la tensión de bus se mide entre VIN− y GND, el código le suma la caída del shunt para obtener la tensión real de la fuente. La calibración por defecto es para 32 V y 2 A; si solo vas a medir unos cientos de miliamperios, activa la línea setCalibration_16V_400mA() para reducir el rango a 400 mA y ganar precisión con corrientes pequeñas. La energía se obtiene sumando en cada vuelta la potencia actual multiplicada por el tiempo transcurrido; se pone a cero al apagar el Arduino, así que, para conservarla, guarda el valor cada cierto tiempo en la EEPROM. El código que hace el mismo cálculo con el ACS712 está en la sección de potencia y energía del artículo sobre el ACS712.

Probador de baterías: un voltímetro que mide la capacidad (mAh)

Batería de iones de litio 18650
La capacidad impresa en una celda 18650 y la real suelen ser distintas; el probador lo deja claro.

La tensión de una batería no dice exactamente cuánta energía le queda; una celda cargada pero desgastada también puede marcar 4,1 V. La forma de conocer la capacidad real es descargarla a través de una carga conocida e ir sumando la corriente a lo largo del tiempo: mAh = Σ (corriente × tiempo). En este circuito un MOSFET conecta y desconecta la carga, y el Arduino mide una vez por segundo la tensión de la batería y la del extremo inferior de la resistencia de carga. La diferencia entre ambas, dividida por la resistencia de carga, da la corriente. Cuando la batería llega a su tensión de corte, el MOSFET se apaga y se muestra el resultado. Al principio, el código compara además la tensión sin carga y con carga para calcular la resistencia interna; cuanto mayor es, más cae la tensión de la batería con corrientes altas.

ComponenteConexiónNota
Batería +A A0 a través de 10 kΩ; también al extremo superior de la resistencia de cargaPon 100 nF entre A0 y GND
Resistencia de carga de 4,7 ΩEntre batería + y el drenador del MOSFETResistencia cerámica de al menos 5 W (mejor 10 W); con una 18650 circulan unos 0,9 A y se calienta
Drenador del MOSFETExtremo inferior de la resistencia de carga; a A1 a través de 10 kΩPon también 100 nF entre A1 y GND
Fuente del MOSFETGNDAquí va también el negativo de la batería
Puerta del MOSFETA D9 a través de 220 Ω; a GND con 100 kΩUsa un MOSFET de nivel lógico como el 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}

Con una carga de 4,7 Ω, una celda 18650 se descarga con una corriente que empieza en unos 0,9 A y baja hacia 0,65 A; probar una celda sana de 2500 mAh lleva unas tres horas. En iones de litio nunca pongas el corte por debajo de 3,0 V, o la celda se estropea. Si pruebas una pila alcalina AA, pon CUTOFF_V en 0,9 V; con la misma carga consume unos 0,3 A. Puedes comparar el resultado con la etiqueta y con la calculadora de duración de batería. La resistencia interna de una 18650 nueva medida así, incluidos portapilas y cables, suele estar por debajo de 0,15 Ω; una celda por encima de 0,3 Ω no debería usarse en aplicaciones de alta corriente. Para entender las unidades de capacidad, echa un vistazo al artículo sobre mAh y capacidad de batería.

Nunca cortocircuites celdas de litio ni pongas la resistencia de carga sobre una superficie inflamable; una resistencia que disipa unos 4 W puede llegar a 80–100 °C. No dejes la prueba sin vigilancia y nunca pruebes celdas hinchadas o abolladas.

Ideas de proyectos con un voltímetro con Arduino

  • Monitor de batería con alarma de baja tensión: Vigila la batería de 12 V de una autocaravana o una instalación solar y haz sonar un zumbador cuando baje de 11,8 V.
  • Registrador de panel solar: Guarda cada minuto en una tarjeta SD la tensión del panel y, con el INA219, su corriente, y calcula la producción diaria en Wh.
  • Indicador para fuente regulable: Añade un voltímetro y un INA219 a la salida de un módulo LM2596 para convertirlo en una fuente de laboratorio.
  • Control remoto de la batería: Envía la tensión medida con un ESP32 a Home Assistant por MQTT o recibe un mensaje de Telegram cuando esté baja.
  • Revisión de packs 18650: Prueba la capacidad de las celdas que cargas con un TP4056 y empareja celdas de capacidad parecida para montar un pack equilibrado.
  • Indicador de dígitos grandes: Muestra el valor en un display de 7 segmentos o una pantalla OLED en lugar de la LCD, lo bastante grande para leerlo de lejos.

Errores frecuentes y cómo solucionarlos

SíntomaCausa probableSolución
La lectura sale siempre un 2–5 % alta o bajaVREF es 5,00 V en el código pero la placa funciona con otra tensiónMide el pin 5V y escríbelo en VREF, o usa el método readVcc
El valor no deja de saltarEl negativo de la fuente no está unido al GND de Arduino o la línea tiene ruidoConecta una masa común, promedia y añade 100 nF en el pin
Se queda en el mismo valor con tensiones altasEl pin alcanzó la referencia y el ADC se saturó en 1023Amplía el rango aumentando la relación del divisor
La lectura se curva en la parte alta y no es linealFuga del zener o extremo superior del ADC del ESP32Mantén el pin por debajo de 4 V (2,5 V en el ESP32) o usa un Schottky
En el ESP32 la lectura es 0 o se congela al activar el Wi-FiEl divisor está en un pin ADC2Usa uno de los pines ADC1, GPIO 32–39
El INA219 muestra corriente negativaVIN+ y VIN− están invertidosEl positivo de la fuente va a VIN+ y el de la carga a VIN−
La LCD se ilumina pero no muestra textoDirección I2C o contraste incorrectosBusca la dirección con un escáner I2C y gira el trimmer trasero
Antes de conectar al Arduino un divisor recién montado, enciende la fuente y mide la tensión del punto medio con el multímetro. Si se parece a lo que calculaste y está por debajo de la referencia, puedes conectarlo al pin con seguridad. Esta comprobación de diez segundos evita que dos resistencias intercambiadas quemen tu placa.

Un voltímetro con Arduino es una de las mejores formas de aprender cómo funciona una medida: con dos resistencias, una fórmula y un poco de calibración obtienes resultados cercanos a los de un multímetro; si añades un sensor de corriente se convierte en vatímetro y, con un MOSFET, en probador de baterías. En la app BlueGrays, el proyecto "Voltímetro digital con LCD" te permite montar el mismo circuito paso a paso con esquema y código listo, y desde ahí pasar a proyectos de monitorización de baterías y medida de potencia.

Preguntas frecuentes

¿Cuántos voltios puede medir un Arduino?

A un pin analógico se pueden conectar directamente como máximo 5 V (3,3 V en el ESP32 y la Pico). Con un divisor de voltaje ese límite se amplía tanto como quieras: con 30 kΩ + 7,5 kΩ mides 25 V y con 100 kΩ + 10 kΩ, 50 V. Eso sí, por encima de unas decenas de voltios la seguridad y el aislamiento pasan a ser importantes, y la tensión de red nunca se mide así.

¿Por qué mi voltímetro con Arduino mide mal?

La causa más habitual es la tensión de referencia: en el código pone 5,00 V pero la placa recibe 4,7–4,9 V del USB y todas las lecturas se desvían en la misma proporción. Otras causas son las resistencias del 5 %, la falta de masa común y un divisor con demasiada resistencia. Se soluciona midiendo el pin 5V y escribiéndolo en el código, o usando el método readVcc, y ajustando el factor CAL con una tensión conocida.

¿Se puede usar el módulo sensor de voltaje de 0–25 V con un ESP32?

Se puede, pero con cuidado. Como la relación del módulo es 5, con un ESP32 solo mides hasta 16,5 V; si tocas 25 V llegan 5 V al pin y el ESP32 se daña. Montar tu propio divisor de 100 kΩ + 10 kΩ es más seguro y también más preciso, porque mantiene el ADC en su zona lineal.

¿Se puede medir la tensión de red de 230 V con Arduino?

Nunca con un divisor de voltaje: es potencialmente mortal y conecta el Arduino a la red. Para la tensión de red se usan módulos como el ZMPT101B, que lleva un pequeño transformador y ofrece aislamiento galvánico. Su salida es alterna, así que el código calcula el valor eficaz (RMS).

¿Puede Arduino medir tensiones negativas?

No directamente; un pin analógico no lee por debajo de GND y puede dañarse. La solución es desplazar la señal hacia 5 V con resistencias: por ejemplo, dos resistencias iguales entre la señal y 5 V crean un punto medio que lleva el rango de −5 V a +5 V a 0–5 V. Para trabajos más precisos se usa un desplazador de nivel con amplificador operacional.

¿Puede un voltímetro con Arduino ser tan preciso como un multímetro?

Un voltímetro con Uno calibrado mide de 0 a 25 V con menos de un 1 % de error, suficiente para la mayoría de proyectos y cercano a un multímetro económico. Por el ADC de 10 bits, la resolución se limita a unos 24 mV en el rango de 25 V. Para mejores resultados puedes usar un ADC externo de 16 bits como el ADS1115, resistencias del 0,1 % y una referencia de precisión.

Ver todos los proyectos
Medir la intensidad de luz con LDR
#11Principiante

Medir la intensidad de luz con LDR

¿Quieres ver en números cuánta luz hay en tu habitación? El LDR, una pequeña pieza sensible a la luz, mide la luz ambiente y el Arduino escribe el valor en la pantalla del ordenador cada medio segundo

4.6(81)
139
Lectura de la intensidad luminosa con el módulo LDR del ESP32
#113Principiante

Lectura de la intensidad luminosa con el módulo LDR del ESP32

Visualización en tiempo real en el monitor serie del valor bruto del ADC del módulo LDR y del porcentaje relativo de luz calculado a partir de referencias de oscuridad y claridad. Este porcentaje no es una medición en lux. Explica el funcionamiento de la calibración del módulo. Es recomendable realizarlo antes del Proyecto 10, ya que se utiliza para determinar el valor umbral.

4.6(36)
55
Voltímetro digital con pantalla LCD
#56Intermedio
Premium

Voltímetro digital con pantalla LCD

Descubre cuánto voltaje da una pila o un adaptador con un medidor hecho por ti. Un divisor de dos resistencias baja la tensión alta a un nivel que la placa puede leer, y el Arduino calcula el valor re

4.5(27)
36
Medición de temperatura con NTC y pantalla LCD 2x16
#44Principiante
Premium

Medición de temperatura con NTC y pantalla LCD 2x16

Mide la temperatura del ambiente con un sensor que parece una pequeña cuenta. Esta pieza, llamada NTC, deja pasar la electricidad con más facilidad cuanto más se calienta; el Arduino lee ese cambio, l

4.5(33)
44
Uso de la pantalla LCD con I2C
#32Principiante
Premium

Uso de la pantalla LCD con I2C

Dale a tu Arduino su propia pantalla y haz que escriba su primer mensaje. La pantalla LCD de dos líneas se conecta con solo unos pocos cables; primero aparece un saludo en la línea de arriba, luego un

4.8(53)
70
Pantalla LCD I2C para ESP32 (16x2)
#119Intermedio
Premium

Pantalla LCD I2C para ESP32 (16x2)

En este proyecto, mostramos texto conectando una pantalla LCD de 16x2 caracteres al ESP32 a través del protocolo I2C. Gracias al I2C, podemos controlar la pantalla con solo 2 pines de datos (SDA y SCL); así se elimina el desperdicio de pines que supone la conexión paralela clásica, que requiere más de 6 pines. El código imprime un mensaje fijo en la primera línea y un contador que aumenta cada segundo en la segunda línea. Además, al inicio ejecutamos el escáner I2C para mostrar la dirección de l

4.9(23)
40
Medición de distancias mediante pantalla LCD
#31Avanzado
Premium

Medición de distancias mediante pantalla LCD

Un aparato que mide distancias sin regla: mueve la mano delante del sensor y mira cómo cambia el número. El HC-SR04 envía una onda de sonido y escucha su eco, y el Arduino calcula la distancia en cent

4.6(45)
59
Brillo de LED con Potenciómetro en ESP32 (Analógico → PWM)
#115Intermedio
Premium

Brillo de LED con Potenciómetro en ESP32 (Analógico → PWM)

En este proyecto controlamos el brillo de un LED de forma analógica mediante un potenciómetro. El pin ADC del ESP32 lee la tensión de 0-3,3 V procedente del potenciómetro y este valor se convierte en una señal PWM (modulación por ancho de pulso) que se envía al LED. Al girar el potenciómetro, el LED se enciende y se apaga gradualmente. Con Arduino Core 3.0+ se usa directamente analogWrite(); en el ESP32-S2/S3, la resolución del ADC es de 12 bits.

4.5(19)
32