Tutorial · Iniciante · 30 min

Leitura de tensões analógicas: referências do ADC e divisores

analogRead retorna uma razão, não uma tensão. Escolha uma referência estável, dimensione um divisor e faça um monitor de bateria confiável.

Introdução

analogRead() é a função mais amigável de um Arduino e uma das mais traiçoeiramente enganosas. Ela devolve um número entre 0 e 1023, todo mundo trata esse número como uma tensão e, na maior parte do tempo, nada dá errado.

Em um robô, dá errado, porque um robô tem motores, e os motores alteram justamente a tensão de referência usada nessa medição.

analogRead retorna uma razão

O ADC não mede volts. Ele compara sua entrada com uma referência e informa a razão:

reading = 1023 × V_in / V_ref

Em um Arduino Uno, V_ref é definido como AVCC por padrão — o trilho de 5 V da placa. Portanto, analogRead() está realmente respondendo “que fração do trilho de 5 V isso representa?”, e converter a leitura para volts multiplicando-a por 5/1023 só é correto enquanto o trilho for exatamente 5 V.

Você já sabe que essa tensão não é, sempre que os motores estão funcionando.

A referência é o defeito

Conecte a tensão de uma bateria, por meio de um divisor, a A0 e observe o número enquanto os motores iniciam.

Dois gráficos empilhados. O superior mostra contagens do ADC em função da tensão da bateria, de 6 a 8,4 volts, para dois projetos: uma referência de trilho de 5 volts com divisor 20k/10k subindo de cerca de 409 para 573 contagens, e uma referência interna de 1,1 volt com divisor 68k/10k subindo de cerca de 715 para 1002. O gráfico inferior mostra a tensão da bateria que cada projeto informa para uma bateria estável de 7,4 volts enquanto o trilho real de 5 volts varia de 4,2 a 5,2 volts: o projeto referenciado ao trilho cai de 8,8 volts para 7,1 volts, enquanto o projeto com referência interna permanece em 7,4.
Parte inferior: a tensão da bateria nunca muda. Quando o trilho cai de 5,0 V para 4,2 V sob carga dos motores, o código que confia em uma referência de 5 V informa que a bateria subiu de 7,4 V para 8,8 V. A referência bandgap informa 7,40 V durante todo o percurso. Parte superior: os mesmos 10 bits se espalham por 286 contagens em vez de 164, porque o divisor foi dimensionado para aproveitar a faixa da referência. Baixar SVG

Um desligamento por bateria fraca baseado no primeiro projeto cumpre o papel oposto: quanto mais o robô trabalha, mais sadia a bateria parece. E a falha é silenciosa, porque cada leitura individual é uma razão perfeitamente válida.

A solução é uma referência que não se move. O ATmega328P tem uma referência bandgap de 1,1 V interna:

analogReference(INTERNAL);   // 1.1 V on an Uno; INTERNAL1V1 on a Mega
analogRead(A0);              // discard — the reference needs a moment to settle

Sempre descarte a primeira leitura depois de trocar a referência. A referência interna e o capacitor de entrada precisam de tempo para estabilizar, e a primeira amostra é feita antes que isso aconteça.

Dimensionando o divisor

A referência agora é 1,1 V e a bateria chega a 8,4 V, então o divisor precisa levar o valor máximo da faixa a um nível ligeiramente inferior ao da referência:

V_adc = V_pack × R2 / (R1 + R2)

Com R1 = 68 kΩ e R2 = 10 kΩ, a razão é 0,128, portanto uma bateria totalmente carregada de 8,4 V apresenta 1,077 V — logo abaixo da referência, usando quase toda a escala. Há três números que vale verificar em qualquer divisor que você projetar:

Verificação Este divisor Por quê
Topo da faixa em relação à referência 1,077 V contra 1,1 V Se a tensão ultrapassar a referência, a leitura satura
Corrente de repouso 108 µA Drena 2,6 mAh por dia — irrelevante frente a 2000 mAh
Impedância de saída (R1∥R2) 8,7 kΩ Mantenha abaixo de cerca de 10 kΩ; veja abaixo

Compare isso com a versão ingênua — um divisor de 20 kΩ/10 kΩ lido contra o trilho de 5 V. Ela coloca uma bateria totalmente carregada em 2,80 V, que correspondem a 573 contagens de 1023 possíveis, e usa 164 contagens em toda a faixa de 6,0–8,4 V da bateria, contra 286 do melhor projeto. Quase o dobro da resolução, com os mesmos dois resistores e uma linha de código.

Resolução não é precisão

Dez bits contra uma referência de 5 V são 4,88 mV por nível; contra a referência de 1,1 V, são 1,07 mV. Nenhum desses números representa sua precisão.

O que realmente limita você:

  • Tolerância da referência. A bandgap é nominalmente 1,1 V e varia alguns pontos percentuais entre chips. Esse é um erro de escala fixo, portanto meça-a uma vez por placa: aplique uma tensão conhecida, leia as contagens e calcule a referência real. Armazene essa constante. Esta é uma etapa de calibração, não um refinamento opcional.
  • Ruído. A alimentação de um robô é ruidosa, e a média é a resposta simples. Fazer a média de N amostras reduz o ruído aleatório em √N — com 16 amostras, o ruído cai a um quarto, o equivalente a um bit extra de resolução utilizável. Isso não resolve um erro de escala.
  • Impedância da fonte. O ADC carrega um pequeno capacitor de amostragem e retenção por meio da fonte de sinal à qual está conectado. Uma fonte de sinal com alta impedância não consegue carregá-lo no tempo permitido, e o resíduo do canal lido anteriormente continua presente.

Este último item produz uma falha característica que vale nomear.

Canais que refletem o valor dos vizinhos

Leia A0 e A1 alternadamente com fontes de sinal de alta impedância e cada leitura será puxada na direção da anterior. Varie um potenciômetro em A0 e veja A1 se mover junto. Nada está ligado errado.

Há duas correções, e você pode usar as duas:

int readSettled(uint8_t pin) {
  analogRead(pin);        // charge the sample-and-hold on this channel
  return analogRead(pin); // then take the one you keep
}

Ler duas vezes e descartar a primeira dá ao capacitor uma segunda janela de amostragem para se carregar até a nova tensão. A outra correção é reduzir a impedância da fonte — e é por isso que o divisor acima usa 68 kΩ/10 kΩ, em vez dos 100 kΩ/100 kΩ que parecem mais simétricos e dão uma impedância de saída de 50 kΩ.

Onde isso aparece em um robô

  • Monitoramento da bateria, como acima — e é o que torna um desligamento por tensão baixa suficientemente confiável para proteger um conjunto de células de íon-lítio.
  • Sensores de linha analógicos. Uma matriz de sensores de reflexão por infravermelho fornece um valor contínuo por sensor, o que permite que um seguidor de linha calcule uma posição contínua, em vez de um indicador esquerda/direita. Esses sensores são lidos contra o mesmo trilho que sofre queda de tensão quando os motores funcionam, e essa é uma razão pela qual a calibração de um seguidor de linha muda conforme a bateria esvazia.
  • Medição de corrente, por meio de um resistor de derivação (shunt) ou de um sensor Hall cuja saída é uma tensão.
  • Potenciômetros como botões de ajuste, que é a maneira mais amigável de ajustar um ganho de PID sem reprogramar o firmware.
  • Não use um sensor de 5 V com uma placa de 3,3 V. Um ESP32 ou Raspberry Pi precisa do divisor para proteção, não apenas para faixa.

Quando algo dá errado

Sintoma Causa provável
A leitura da bateria sobe quando os motores iniciam Referenciada ao trilho que caiu; use INTERNAL
Leitura presa em 1023 Entrada acima da referência — razão do divisor grande demais
Um canal repete o valor do canal anterior Impedância da fonte alta demais; leia duas vezes e descarte
As leituras saltam dezenas de contagens Ruído da fonte; faça a média e verifique os trilhos de alimentação
Tensão consistentemente alguns pontos percentuais fora Referência interna não calibrada — meça-a uma vez
A primeira leitura depois de analogReference() está errada Esperado; descarte-a
A calibração do sensor de linha sofre deriva conforme a bateria esvazia Leituras referenciadas ao trilho em queda
Apenas 15% da faixa é usado Divisor dimensionado para 5 V, mas lido contra 1,1 V

A regra que evita a maior parte disso: decida qual é sua referência antes de decidir qualquer outra coisa. Cada número que o ADC fornece é relativo a ela, portanto uma referência que se move faz de cada leitura uma medição que depende simultaneamente da entrada e da referência.

Explore o grafo

Faz parte destas montagens

Projetos e caminhos de aprendizagem que incluem este tutorial.

Leitura complementar

Referências