Guias · 16 min de leitura

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.

Voltímetro digital
O voltímetro que você monta com Arduino pode mostrar a tensão com duas casas decimais, assim como estes medidores de painel.

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.

PlacaADCReferência1 passo no pino1 passo com 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)Cerca de 3,3 V (atenuação de 11 dB)Cerca de 0,8 mVCerca de 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Ω)

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.

FaixaArduino Uno (5 V): R1 + R2Tensão no pino no fundo de escalaESP32 / Pico (3,3 V): R1 + R2Tensão no pino no fundo 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 pronto)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
Em vez de calcular à mão a razão para sua própria faixa, você pode usar a calculadora de divisor de tensão. Nas colunas do ESP32 e do Pico, mantivemos deliberadamente o pino abaixo de 2,5 V, porque o ADC do ESP32 perde linearidade perto do limite superior. Prefira resistores de filme metálico de 1%; dois resistores de 5% podem alterar a razão em cerca de 10% no pior caso.

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.
Este voltímetro é apenas para CC e baixas tensões (no máximo algumas dezenas de volts). Nunca tente medir a rede elétrica de 230 V com dois resistores: isso pode ser fatal e conecta o GND do Arduino à rede elétrica. Para tensão da rede, use um módulo com transformador e isolação galvânica, como o ZMPT101B. Além disso, o negativo da fonte que você está medindo deve ser conectado ao GND do Arduino; sem um GND comum, a leitura não tem sentido.

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óduloFunçãoArduino UnoESP32 (divisor próprio)Raspberry Pi Pico (divisor próprio)
VCC (borne com parafuso)Positivo da fonte a medirFonte +Extremidade superior de R1Extremidade superior de R1
GND (borne com parafuso)Negativo da fonte a medirFonte −Fonte − e GNDFonte − e GND
SSinal divididoA0GPIO 34 (ADC1)GP26 (ADC0, pino 31)
+Sem conexão na maioria dos módulosDeixe desconectado--
−GND do móduloGNDGNDGND (por exemplo, pino 33)

Passo a passo: seu primeiro voltímetro com Arduino

  1. 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.
  2. 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.
  3. Insira o valor medido na constante VREF do código abaixo e carregue-o.
  4. 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.
  5. 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.
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}

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étodoCódigoVantagemPonto de atenção
Padrão (AVcc)analogReference(DEFAULT)Sem configuração, faixa completa de 0–5 VQualquer variação da alimentação também afeta a leitura
Referência interna de 1,1 VanalogReference(INTERNAL)Estável e independente da alimentaçãoVaria 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 LM4040Esta 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 abaixoSem componentes extras, mantém a precisão quando o USB ou a bateria variamSó funciona em placas AVR (Uno, Nano, Pro Mini); calibre o valor de 1,1 V uma vez
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. 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.
  2. 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.
  3. 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).
  4. 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

Display LCD I2C 16x2
Graças ao adaptador I2C, o LCD 16x2 é conectado com apenas quatro fios: GND, VCC, SDA e SCL.

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.

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}

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.

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}

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.

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)

Adicionando corrente para criar um wattímetro: ACS712 ou INA219

Módulo sensor de corrente ACS712
O ACS712 mede a corrente usando o efeito Hall e mantém o circuito medido eletricamente isolado do Arduino.

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ísticaMódulo de tensão + ACS712 (5A)Módulo INA219
Faixa de tensão0–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 correnteCerca de 26 mA em um Uno0,1 mA
Corrente CASimNão
ConexãoDois pinos analógicosI2C (SDA, SCL), endereço 0x40
Ideal paraMotores, corrente do lado da rede elétrica e situações que exigem isolaçãoMedições de pequenas potências em CC, como baterias, painéis solares e 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}

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)

Célula Li-ion 18650
A capacidade impressa em uma célula 18650 e sua capacidade real muitas vezes são diferentes; o testador revela a verdade.

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.

ComponenteConexãoObservação
Bateria +A A0 por 10 kΩ; também à extremidade superior do resistor de cargaColoque 100 nF entre A0 e GND
Resistor de carga de 4,7 ΩEntre o positivo da bateria e o dreno do MOSFETResistor 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 MOSFETExtremidade inferior do resistor de carga; a A1 por 10 kΩColoque também 100 nF entre A1 e GND
Terminal fonte do MOSFETGNDO negativo da bateria também é conectado aqui
Gate do MOSFETA D9 por 220 Ω; ao GND por 100 kΩUse um MOSFET de nível lógico, como o 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}

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.

Nunca coloque células Li-ion em curto-circuito e não coloque o resistor de carga sobre uma superfície inflamável; um resistor dissipando cerca de 4 W pode atingir 80–100 °C. Não deixe o teste sem supervisão e nunca teste células estufadas ou amassadas.

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

SintomaCausa provávelSolução
A leitura fica sempre 2–5% acima ou abaixoVREF está em 5,00 V no código, mas a placa funciona com outra tensãoMeça o pino 5V e insira o valor em VREF ou use o método readVcc
O valor fica oscilandoO negativo da fonte não está ligado ao GND do Arduino ou há ruído na linhaConecte um GND comum, calcule a média das leituras e adicione 100 nF no pino
O valor fica travado em tensões altasO pino atingiu a referência e o ADC saturou em 1023Amplie a faixa aumentando a razão do divisor
A leitura se curva perto do limite superior e não é linearFuga do zener ou região superior do ADC do ESP32Mantenha 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 iniciaO divisor está em um pino ADC2Use um dos pinos ADC1, GPIO 32–39
O INA219 mostra corrente negativaVIN+ e VIN− estão invertidosO positivo da fonte vai a VIN+, e o positivo da carga, a VIN−
O LCD está aceso, mas não mostra textoEndereço I2C ou ajuste de contraste incorretoEncontre o endereço com um scanner I2C e gire o trimpot no verso
Antes de conectar um divisor recém-montado ao Arduino, ligue a fonte e meça a tensão no ponto intermediário com um multímetro. Se ela estiver próxima do valor calculado e abaixo da referência, é seguro conectá-la ao pino. Essa verificação de dez segundos evita que dois resistores invertidos queimem sua placa.

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.

Ver todos os projetos
Medição da intensidade da luz com LDR
#11Iniciante

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

4.6(81)
139
Leitura da intensidade da luz com módulo LDR e ESP32
#113Iniciante

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.

4.6(36)
55
Voltímetro digital com display LCD
#56Intermediário
Premium

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

4.5(27)
36
Medição de temperatura com NTC e display LCD 2x16
#44Iniciante
Premium

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

4.5(33)
44
Uso do display LCD com I2C
#32Iniciante
Premium

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

4.8(53)
70
Display LCD I2C com ESP32 (16x2)
#119Intermediário
Premium

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).

4.9(23)
40
Medição de distância com display LCD
#31Avançado
Premium

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

4.6(45)
59
Brilho do LED com potenciômetro no ESP32 (analógico → PWM)
#115Intermediário
Premium

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.

4.5(19)
32