Voltímetro com Arduino: meça 0–25 V com LCD e calibração
Como montar um voltímetro com Arduino: meça 0–25 V com um divisor, escolha resistores, adicione proteção com zener, calibre e use LCD, INA219 e testador de baterias.
Um voltímetro com Arduino é um instrumento de medição que você pode montar em uma noite: dois resistores, uma entrada analógica e algumas linhas de código bastam para medir 0–25 V com precisão e mostrar o resultado em um display. As entradas analógicas do Arduino podem ler no máximo 5 V, então, para medir uma tensão maior, você primeiro a reduz com um divisor de tensão e depois a multiplica no código pela mesma razão. Monitores de bateria, indicadores de fontes de alimentação, dataloggers de painéis solares e testadores de baterias se baseiam nessa mesma ideia.
Neste guia você vai aprender passo a passo como escolher os valores dos resistores para uma determinada faixa, como um zener e um resistor em série protegem a entrada analógica contra sobretensão, como funciona o módulo sensor de tensão de 0–25 V pronto e como o ajuste da tensão de referência e a calibração aproximam suas leituras das de um multímetro. Depois, você vai mostrar o valor em um LCD I2C, montar o mesmo voltímetro em um ESP32 e em um Raspberry Pi Pico, adicionar medição de corrente com um INA219 para transformá-lo em wattímetro e, por fim, fazer um testador que mede a capacidade real de uma bateria em mAh.

Como funciona um voltímetro com Arduino?
O Arduino não conhece a tensão diretamente; seu ADC (conversor analógico-digital) compara a tensão na entrada analógica com uma tensão de referência e retorna o resultado como um número inteiro. O ADC do Arduino Uno é de 10 bits: ele lê 0 para 0 V e 1023 para a tensão de referência (5 V por padrão). A tensão no pino é Vpin = leitura × Vref / 1024. Se houver um divisor de tensão na entrada, a tensão que você realmente está medindo é Vin = Vpin × (R1 + R2) / R2. Portanto, a precisão de todo o voltímetro depende de três coisas: o valor real de Vref, a razão entre os dois resistores e o erro do próprio ADC.
| Placa | ADC | Referência | 1 passo no pino | 1 passo com divisor de 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) | Cerca de 3,3 V (atenuação de 11 dB) | Cerca de 0,8 mV | Cerca de 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Ω) |
O divisor de tensão e a escolha dos resistores para 0–25 V
A tensão que você está medindo entra pelo resistor superior R1, o ponto intermediário onde os dois resistores se encontram vai ao pino analógico e o resistor inferior R2 vai ao GND. Ao escolher os resistores, primeiro defina a tensão máxima e depois escolha uma razão que mantenha o pino um pouco abaixo da referência nessa tensão, por exemplo, cerca de 4,5 V em um Uno. O par de 30 kΩ e 7,5 kΩ usado nos módulos prontos divide exatamente por 5: 25 V na entrada resultam em 5,00 V no pino. Também não escolha valores aleatórios: se a resistência total for muito baixa, o divisor desperdiça corrente da fonte que você está medindo; se for muito alta, o capacitor de amostragem dentro do ADC não consegue carregar e a leitura varia. O datasheet do ATmega328P recomenda que a fonte que alimenta uma entrada analógica tenha resistência de no máximo 10 kΩ; em um divisor, essa resistência da fonte corresponde a R1 e R2 em paralelo (6 kΩ para 30 kΩ e 7,5 kΩ). Você encontra a fórmula em detalhes, além dos efeitos de carga, no artigo sobre divisor de tensão.
| Faixa | Arduino Uno (5 V): R1 + R2 | Tensão no pino no fundo de escala | ESP32 / Pico (3,3 V): R1 + R2 | Tensão no pino no fundo de escala |
|---|---|---|---|---|
| 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Ω (módulo pronto) | 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 |
Proteção: diodo zener, resistor em série e capacitor
Mesmo com um divisor calculado corretamente, uma ponta de prova no lugar errado, um pico na fonte de alimentação ou o contato acidental com 48 V em vez de 25 V pode elevar o pino acima de 5 V. Os pinos do ATmega328P toleram no máximo a alimentação mais 0,5 V. Dentro do pino há diodos de proteção para 5 V e GND, mas eles só suportam correntes pequenas. A boa notícia é que o resistor superior do divisor já limita a corrente. Com um R1 de 30 kΩ, mesmo o contato com 50 V deixa passar no máximo cerca de 1,5 mA para o pino. Para reduzir ainda mais essa corrente e absorver o excesso de tensão com segurança, você pode adicionar as seguintes camadas de proteção.
- Resistor em série: Coloque um resistor de 4,7–10 kΩ entre o ponto intermediário do divisor e o pino analógico. Durante uma sobretensão, a corrente nos diodos internos do pino cai para a faixa de microampères.
- Capacitor de 100 nF: Conecte-o entre o pino analógico e o GND. Ele compensa a resistência de fonte mais alta causada pelo resistor em série, porque o ADC retira desse capacitor a carga necessária durante a amostragem. Também filtra ruído e picos curtos.
- Diodo zener de 5,1 V: Conecte um zener, como o 1N4733A ou o BZX55C5V1, com o cátodo no pino e o ânodo no GND. Quando a tensão tenta subir acima de 5,1 V, o zener conduz e desvia o excesso para o GND.
- Atenção à fuga do zener: Um zener começa a consumir uma pequena corrente um pouco abaixo de sua tensão de ruptura e, com um divisor de alta resistência, essa corrente reduz a leitura. Se usar um zener, mantenha o máximo do pino em torno de 4 V ou use, em seu lugar, um diodo Schottky (BAT85) do pino para a linha de 5 V.
- Polaridade invertida: Se conectar as pontas de prova ao contrário, uma tensão negativa chega ao pino. O resistor em série limita a corrente; para maior segurança, você pode adicionar um segundo diodo Schottky com o ânodo no GND e o cátodo no pino.
O módulo sensor de tensão pronto (0–25 V)
Se preferir não soldar, você pode usar o pequeno módulo vermelho ou azul vendido como “sensor de tensão”. Não há nada de mágico dentro dele: apenas um divisor feito exatamente com um resistor de 30 kΩ e um de 7,5 kΩ, um borne com parafuso e uma barra de três pinos. Como a razão é 5, você pode medir 0–25 V com um Arduino de 5 V, mas apenas até 16,5 V com uma placa de 3,3 V. Em uma placa de 3,3 V, o contato com 25 V coloca 5 V no pino e o danifica; por isso, para o ESP32 e o Pico, é mais seguro montar seu próprio divisor com base na tabela acima. O módulo não tem diodo de proteção, então as medidas com zener ou Schottky da seção anterior também se aplicam aqui.
| Pino do módulo | Função | Arduino Uno | ESP32 (divisor próprio) | Raspberry Pi Pico (divisor próprio) |
|---|---|---|---|---|
| VCC (borne com parafuso) | Positivo da fonte a medir | Fonte + | Extremidade superior de R1 | Extremidade superior de R1 |
| GND (borne com parafuso) | Negativo da fonte a medir | Fonte − | Fonte − e GND | Fonte − e GND |
| S | Sinal dividido | A0 | GPIO 34 (ADC1) | GP26 (ADC0, pino 31) |
| + | Sem conexão na maioria dos módulos | Deixe desconectado | - | - |
| − | GND do módulo | GND | GND | GND (por exemplo, pino 33) |
Passo a passo: seu primeiro voltímetro com Arduino
- Conecte o pino S do módulo a A0 e o pino − ao GND. Se estiver montando seu próprio divisor, coloque o resistor de 30 kΩ no lado da fonte e o de 7,5 kΩ no lado do GND e ligue o ponto intermediário a A0.
- Conecte o Arduino ao USB, meça entre o pino 5V e o GND com um multímetro e anote o valor. A tensão USB costuma ficar entre 4,7 e 5,1 V.
- Insira o valor medido na constante VREF do código abaixo e carregue-o.
- Conecte a fonte que você quer medir ao borne com parafuso do módulo: positivo em VCC, negativo em GND. Uma bateria de 9 V ou uma fonte de bancada ajustável é ideal para o primeiro teste.
- Abra o Monitor Serial em 9600 baud. Leia a tensão e, ao mesmo tempo, meça a fonte com o multímetro e compare os dois valores.
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}O código calcula a média de 32 leituras a cada vez, então a oscilação de ±1 passo do ADC praticamente desaparece e o último dígito se estabiliza. A primeira leitura é descartada porque o capacitor de amostragem do ADC ainda guarda carga do canal anterior. Arredondar qualquer valor abaixo de 0,05 V para zero evita que valores aleatórios como 0,02–0,04 V apareçam quando nada está conectado. Lembre-se de que a resolução é de 24,4 mV: mesmo que você veja duas casas decimais, o último dígito varia em passos de 0,02–0,03 V. Se precisar de uma resolução mais fina, reduza a faixa; com um divisor de 0–10 V, cada passo cai para 10,7 mV.
Tensão de referência e calibração
É comum dizer que voltímetros com Arduino “medem errado”, mas a verdadeira origem do erro geralmente é a referência. Se o código indica 5,00 V enquanto a placa recebe 4,80 V do USB, todas as leituras ficam 4% acima: uma bateria de 12,00 V aparece como 12,50 V. Essa tensão muda de um computador de mesa para um notebook e de um cabo USB para outro; quando você alimenta a placa com uma fonte externa, o regulador assume o controle e o valor muda novamente. Há três formas de corrigir isso: medir o pino 5V e inserir o valor no código, usar uma referência interna fixa ou recalcular a tensão de alimentação da própria placa a cada medição.
| Método | Código | Vantagem | Ponto de atenção |
|---|---|---|---|
| Padrão (AVcc) | analogReference(DEFAULT) | Sem configuração, faixa completa de 0–5 V | Qualquer variação da alimentação também afeta a leitura |
| Referência interna de 1,1 V | analogReference(INTERNAL) | Estável e independente da alimentação | Varia de 1,0 a 1,2 V entre placas; a razão do divisor deve ser de aproximadamente 23 (por exemplo, 220 kΩ + 10 kΩ) |
| Referência externa (AREF) | analogReference(EXTERNAL) | Melhor precisão com uma referência de precisão, como o LM4040 | Esta linha deve ser executada antes de aplicar tensão a AREF, ou ocorrerá um curto com a referência interna |
| Medição da alimentação (readVcc) | O código abaixo | Sem componentes extras, mantém a precisão quando o USB ou a bateria variam | Só funciona em placas AVR (Uno, Nano, Pro Mini); calibre o valor de 1,1 V uma vez |
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}- Calibre a referência interna: Execute o código readVcc e compare o valor de Vcc no Monitor Serial com a leitura do multímetro no pino 5V. Novo bandgapMv = 1100 × medido / exibido. Por exemplo, se a placa mostrar 5,12 V e o multímetro indicar 4,98 V, insira 1100 × 4.98 / 5.12 ≈ 1070.
- Calibração de um ponto: Conecte uma tensão conhecida perto do limite superior da faixa (por exemplo, 12 V). CAL = valor do multímetro / valor do Arduino. Esse fator também corrige o erro de razão causado pela tolerância dos resistores.
- Calibração de dois pontos: Se você observar um offset constante em baixas tensões, meça em dois pontos, um baixo (por exemplo, 2 V) e um alto (por exemplo, 20 V). Inclinação = (M2 − M1) / (A2 − A1), offset = M1 − inclinação × A1; o resultado é real = inclinação × leitura + offset (M é o valor do multímetro e A, o valor do Arduino).
- Verifique: Após calibrar, confira o resultado com uma terceira tensão no meio da faixa. Um voltímetro com Uno montado com cuidado mede 0–25 V com erro inferior a 1%.
Um voltímetro digital com LCD

Para tornar o voltímetro independente do computador, basta exibir o valor em um LCD I2C. Conecte o GND do LCD ao GND, VCC a 5V, SDA a A4 e SCL a A5. Instale a biblioteca LiquidCrystal I2C (Frank de Brabander) pelo Gerenciador de Bibliotecas. O endereço do display geralmente é 0x27 ou, em alguns módulos, 0x3F. O código abaixo mostra a tensão em tempo real na linha superior e os menores e maiores valores registrados desde que foi ligado na linha inferior, permitindo também detectar a queda de tensão de uma bateria enquanto um motor funciona.
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}Montando o voltímetro com um ESP32
O ESP32 funciona com 3,3 V e seus pinos não suportam mais de 3,6 V, então use um divisor de 100 kΩ + 10 kΩ para 0–25 V: 25 V na entrada resultam em 2,27 V no pino. Conecte o divisor a um dos pinos ADC1 (GPIO 32–39); os pinos ADC2 não funcionam enquanto o Wi-Fi está ligado. O ADC do ESP32 é de 12 bits, mas não é linear nas extremidades: ele quase não detecta valores abaixo de 0,15 V e seu erro aumenta acima de 2,5 V. A função analogReadMilliVolts() usa dados de calibração gravados no chip na fábrica e fornece um resultado em milivolts muito mais preciso que o valor bruto. Para remover o offset restante, o código aplica a calibração de dois pontos da seção anterior com as constantes GAIN e 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}Montando o voltímetro com um Raspberry Pi Pico (MicroPython)
No Raspberry Pi Pico, as entradas analógicas são GP26, GP27 e GP28. Conecte a GP26 o mesmo divisor de 100 kΩ + 10 kΩ usado no ESP32. Em MicroPython, read_u16() retorna o resultado de 12 bits escalonado para 0–65535. A referência do ADC do Pico é obtida por filtragem da linha de 3,3 V; para melhorar a precisão, meça entre ADC_VREF (pino 35) e GND com um multímetro e insira o valor em VREF. Há também um bônus no código: no Pico padrão, GP29 (ADC3) está ligado a um divisor interno que divide por 3 a entrada de alimentação VSYS da placa. Assim, sem nenhum componente extra, você também pode ler a tensão da bateria que alimenta o Pico. No Pico W e no Pico 2 W, GP29 é compartilhado com o chip sem fio, então essa linha não funciona diretamente nessas placas.
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)Adicionando corrente para criar um wattímetro: ACS712 ou INA219

Quando você adiciona medição de corrente a um voltímetro, também obtém a potência: P = V × I. Se uma bateria de 12 V fornece 1,5 A, a potência é de 18 W. Some a potência ao longo do tempo e você obtém a energia: uma carga de 18 W funcionando por 2 horas consome 36 Wh. Há duas opções comuns. O ACS712 tem saída analógica, também mede corrente CA e oferece isolação; ele simplesmente se torna um segundo canal analógico no voltímetro que você já tem. O INA219 é um monitor de potência CC que mede tensão e corrente no mesmo chip com precisão de 12 bits e se comunica por I2C; sozinho, ele já é um wattímetro pronto.
| Característica | Módulo de tensão + ACS712 (5A) | Módulo INA219 |
|---|---|---|
| Faixa de tensão | 0–25 V (definida pelo divisor) | 0–26 V (dentro do chip) |
| Faixa de corrente | ±5 A | ±3,2 A (com um shunt de 0,1 Ω) |
| Resolução de corrente | Cerca de 26 mA em um Uno | 0,1 mA |
| Corrente CA | Sim | Não |
| Conexão | Dois pinos analógicos | I2C (SDA, SCL), endereço 0x40 |
| Ideal para | Motores, corrente do lado da rede elétrica e situações que exigem isolação | Medições de pequenas potências em CC, como baterias, painéis solares e dispositivos 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}O INA219 calcula a corrente a partir da pequena queda de tensão no resistor shunt de 0,1 Ω entre VIN+ e VIN−, então o módulo é colocado em série no lado positivo da fonte (lado alto). Como a tensão do barramento é medida entre VIN− e GND, o código soma a queda no shunt para obter a tensão real da fonte. A calibração padrão é para 32 V e 2 A; se você for medir apenas algumas centenas de miliampères, habilite a linha setCalibration_16V_400mA() para reduzir a faixa a 400 mA e melhorar a precisão em correntes pequenas. A energia é obtida somando a potência atual multiplicada pelo tempo decorrido em cada ciclo; ela é zerada quando você desliga o Arduino, então, para preservá-la, grave o valor na EEPROM em intervalos. Para ver um código que faz o mesmo cálculo com o ACS712, consulte a seção de potência e energia do artigo sobre o ACS712.
Testador de baterias: um voltímetro que mede capacidade (mAh)

A tensão de uma bateria não informa exatamente quanta energia ainda resta nela; uma célula carregada, mas desgastada, também pode mostrar 4,1 V. A maneira de descobrir a capacidade real é descarregar a bateria por uma carga conhecida e somar a corrente ao longo do tempo: mAh = Σ (corrente × tempo). Neste circuito, um MOSFET liga e desliga a carga, e o Arduino mede a tensão da bateria e a tensão na extremidade inferior do resistor de carga uma vez por segundo. A diferença entre as duas, dividida pela resistência da carga, fornece a corrente. Quando a bateria atinge sua tensão de corte, o MOSFET desliga e o resultado é exibido. No início, o código também compara a tensão da bateria sem carga e com carga para calcular sua resistência interna; quanto maior a resistência interna, maior a queda de tensão da bateria em correntes altas.
| Componente | Conexão | Observação |
|---|---|---|
| Bateria + | A A0 por 10 kΩ; também à extremidade superior do resistor de carga | Coloque 100 nF entre A0 e GND |
| Resistor de carga de 4,7 Ω | Entre o positivo da bateria e o dreno do MOSFET | Resistor cimentado de pelo menos 5 W (de preferência 10 W); com uma 18650, passam cerca de 0,9 A e ele aquece |
| Dreno do MOSFET | Extremidade inferior do resistor de carga; a A1 por 10 kΩ | Coloque também 100 nF entre A1 e GND |
| Terminal fonte do MOSFET | GND | O negativo da bateria também é conectado aqui |
| Gate do MOSFET | A D9 por 220 Ω; ao GND por 100 kΩ | Use um MOSFET de nível lógico, como o 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}Com uma carga de 4,7 Ω, uma célula 18650 descarrega com uma corrente que começa em cerca de 0,9 A e cai para perto de 0,65 A; testar uma célula saudável de 2.500 mAh leva cerca de três horas. Para Li-ion, nunca ajuste o corte abaixo de 3,0 V, ou a célula será danificada. Se estiver testando uma pilha AA alcalina, ajuste CUTOFF_V para 0,9 V; ela fornece cerca de 0,3 A com a mesma carga. Você pode comparar o resultado com o rótulo e com a calculadora de autonomia da bateria. A resistência interna de uma 18650 nova, medida dessa forma, incluindo o suporte e os fios, geralmente fica abaixo de 0,15 Ω; uma célula acima de 0,3 Ω não deve ser usada em aplicações de alta corrente. Para entender as unidades de capacidade, veja o artigo sobre mAh e capacidade da bateria.
Ideias de projetos com um voltímetro com Arduino
- Monitor de bateria e alarme de baixa tensão: Monitore a bateria de 12 V de um motorhome ou sistema fotovoltaico e acione um buzzer quando ela cair abaixo de 11,8 V.
- Datalogger de painel solar: Grave a tensão do painel e sua corrente, medida pelo INA219, em um cartão SD a cada minuto e calcule a produção diária em Wh.
- Indicador para fonte de bancada: Adicione um voltímetro e um INA219 à saída de um módulo LM2596 para transformá-lo em uma fonte de bancada.
- Monitoramento remoto de bateria: Envie a tensão medida com um ESP32 ao Home Assistant por MQTT ou receba uma mensagem no Telegram quando ela estiver baixa.
- Verificação de conjunto de células 18650: Teste a capacidade das células que você carrega com um TP4056 e depois agrupe células de capacidade semelhante para montar um conjunto equilibrado.
- Display com dígitos grandes: Mostre o valor em um display de 7 segmentos ou em um display OLED no lugar do LCD, em tamanho suficiente para ler do outro lado do cômodo.
Erros comuns e como corrigi-los
| Sintoma | Causa provável | Solução |
|---|---|---|
| A leitura fica sempre 2–5% acima ou abaixo | VREF está em 5,00 V no código, mas a placa funciona com outra tensão | Meça o pino 5V e insira o valor em VREF ou use o método readVcc |
| O valor fica oscilando | O negativo da fonte não está ligado ao GND do Arduino ou há ruído na linha | Conecte um GND comum, calcule a média das leituras e adicione 100 nF no pino |
| O valor fica travado em tensões altas | O pino atingiu a referência e o ADC saturou em 1023 | Amplie a faixa aumentando a razão do divisor |
| A leitura se curva perto do limite superior e não é linear | Fuga do zener ou região superior do ADC do ESP32 | Mantenha o pino abaixo de 4 V (2,5 V no ESP32) ou use um Schottky |
| No ESP32, a leitura fica em 0 ou congela quando o Wi-Fi inicia | O divisor está em um pino ADC2 | Use um dos pinos ADC1, GPIO 32–39 |
| O INA219 mostra corrente negativa | VIN+ e VIN− estão invertidos | O positivo da fonte vai a VIN+, e o positivo da carga, a VIN− |
| O LCD está aceso, mas não mostra texto | Endereço I2C ou ajuste de contraste incorreto | Encontre o endereço com um scanner I2C e gire o trimpot no verso |
Um voltímetro com Arduino é uma das melhores formas de aprender como a medição funciona: com dois resistores, uma fórmula e um pouco de calibração, você obtém resultados próximos aos de um multímetro; adicione um sensor de corrente e ele vira um wattímetro, adicione um MOSFET e ele vira um testador de baterias. No app BlueGrays, o projeto “Voltímetro digital com LCD” permite montar o mesmo circuito passo a passo com um diagrama de fiação e código pronto; a partir dele, você pode avançar para projetos de monitoramento de bateria e medição de potência.
Perguntas frequentes
Quantos volts um Arduino pode medir?
Você pode conectar no máximo 5 V (3,3 V no ESP32 e no Pico) diretamente a um pino analógico. Com um divisor de tensão, pode elevar esse limite quanto quiser: 30 kΩ + 7,5 kΩ mede 25 V, e 100 kΩ + 10 kΩ mede 50 V. Acima de algumas dezenas de volts, porém, a segurança e a isolação se tornam importantes, e a tensão da rede elétrica nunca deve ser medida dessa forma.
Por que meu voltímetro com Arduino está medindo errado?
A causa mais comum é a tensão de referência: o código indica 5,00 V, mas a placa recebe 4,7–4,9 V do USB, então todas as leituras se deslocam na mesma proporção. Outras causas são resistores de 5%, falta de GND comum e um divisor com resistência alta demais. Medir o pino 5V e inserir o valor no código, ou usar o método readVcc, e depois ajustar o fator CAL com uma tensão conhecida resolve o problema.
Posso usar o módulo sensor de tensão de 0–25 V com um ESP32?
Pode, mas com cuidado. Como a razão do módulo é 5, um ESP32 só pode medir até 16,5 V com ele; ao encostar em 25 V, chegam 5 V ao pino, danificando o ESP32. Montar seu próprio divisor de 100 kΩ + 10 kΩ para o ESP32 é mais seguro e mais preciso, pois mantém o ADC na região linear.
Um Arduino pode medir a tensão da rede elétrica de 230 V CA?
Nunca com um divisor de tensão: isso pode ser fatal e conecta o Arduino à rede elétrica. Para tensão da rede, use um módulo como o ZMPT101B, que contém um pequeno transformador e oferece isolação galvânica. Sua saída é CA, então o código calcula o valor RMS.
Um Arduino pode medir tensão negativa?
Não diretamente; um pino analógico não consegue ler abaixo do GND e pode ser danificado. A solução é deslocar o sinal para cima, em direção a 5 V, com resistores: por exemplo, dois resistores iguais entre o sinal e 5 V criam um ponto intermediário que mapeia −5 V a +5 V para 0–5 V. Para trabalhos mais precisos, usa-se um conversor de nível com amplificador operacional.
Um voltímetro com Arduino pode ser tão preciso quanto um multímetro?
Um voltímetro com Uno calibrado mede 0–25 V com erro inferior a 1%, suficiente para a maioria dos projetos de hobby e próximo de um multímetro barato. Por causa do ADC de 10 bits, a resolução fica limitada a cerca de 24 mV em uma faixa de 25 V. Para obter resultados melhores, você pode usar um ADC externo de 16 bits, como o ADS1115, resistores de 0,1% e uma referência de precisão.
Projetos para montar depois desta leitura
Ver todos os projetos
Medição da intensidade da luz com LDR
Quer ver a luminosidade do seu quarto em números? O LDR, um pequeno componente sensível à luz, mede a luz ambiente, e o Arduino exibe o valor na tela do computador a cada meio segundo. Cubra o sensor

Leitura da intensidade da luz com módulo LDR e ESP32
Acompanhe em tempo real no Monitor Serial o valor bruto do ADC do módulo LDR e a porcentagem relativa de luz calculada a partir de referências de escuridão e claridade. Essa porcentagem não é uma medida em lux. O projeto ensina a lógica de calibração do módulo. É ideal fazê-lo antes do projeto 10, pois ajuda a determinar o valor do limiar.

Voltímetro digital com display LCD
Descubra a tensão de uma pilha ou de um adaptador de alimentação com um medidor feito por você. Um divisor formado por dois resistores reduz a tensão alta a um nível que a placa consegue ler, e o Ardu

Medição de temperatura com NTC e display LCD 2x16
Meça a temperatura ao seu redor com um sensor que parece uma pequena conta. Esse componente, chamado NTC, deixa a eletricidade passar com mais facilidade à medida que aquece; o Arduino lê essa mudança

Uso do display LCD com I2C
Dê ao seu Arduino um display próprio e faça-o escrever sua primeira mensagem. O display LCD de duas linhas é conectado com poucos fios; primeiro aparece uma saudação na linha de cima, depois uma segun

Display LCD I2C com ESP32 (16x2)
Neste projeto, exibimos texto conectando um display LCD de 16x2 caracteres ao ESP32 pelo protocolo I2C. Com o I2C, controlamos o display usando apenas dois pinos de dados (SDA e SCL), dispensando o uso de seis ou mais pinos da conexão paralela tradicional. O código mostra uma mensagem fixa na primeira linha e um contador que aumenta a cada segundo na segunda linha. Na inicialização, também executamos um scanner I2C para mostrar o endereço do display no Monitor Serial (geralmente 0x27 ou 0x3F).

Medição de distância com display LCD
Uma ferramenta que mede distâncias sem régua: aproxime e afaste a mão na frente do sensor e veja o número mudar. O HC-SR04 emite uma onda sonora e escuta seu eco, e o Arduino calcula a distância em ce

Brilho do LED com potenciômetro no ESP32 (analógico → PWM)
Neste projeto, controlamos o brilho de um LED de forma analógica com um potenciômetro. O pino ADC do ESP32 lê a tensão de 0-3,3V do potenciômetro e converte esse valor em um sinal PWM (modulação por largura de pulso), enviado ao LED. Assim, ao girar o potenciômetro, o brilho do LED aumenta e diminui gradualmente. Com Arduino Core 3.0+, você pode usar analogWrite() diretamente; no ESP32-S2/S3, a resolução do ADC é fixada em 12 bits.
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

