Entrada Analógica
Como o Arduino transforma uma tensão qualquer num número inteiro, o que esse número significa em volts, e por que ele nunca é exato.
Ao terminar, você consegue
- Ligar um trimpot em A1 e ver o valor lido aparecer no Monitor Serial.
- Converter 307 em 1,50 V, e 1,50 V em 307, de cabeça.
- Explicar por que o código 1023 não vale 5 V exatos.
Se for além: justificar por que o trimpot é de 10 kΩ; dizer o que muda no ESP32-S3; criar o sensor de nível do desafio.
Na bancada
- Arduino Uno + cabo USB
- Protoboard e fios jumper
- Trimpot de 10 kΩ (marcação 103); um potenciômetro de 10 kΩ serve
- Multímetro (recomendado)
- LED + resistor de 220 Ω (opcional, para o limiar)
- LM35 (opcional)
- ESP32-S3 N16R8: só na seção da ponte
Como estudar esta página
- Preveja antes de cada experimento. Errar a previsão é o que faz a ideia grudar.
- Teste primeiro na bancada virtual daqui, depois no kit.
- Explique com suas palavras na caixa Feynman do fim.
- Revise nas datas da agenda. Ler uma vez só não funciona.
De onde você vem e o aquecimento de hoje
Antes do assunto de hoje, um aquecimento com o que você já sabe: dois botões, um LED e um módulo relé. Vale refazer, porque o pino e o botão voltam no desafio do fim.
Onde esta aula se encaixa
- Antes daqui o mundo tinha dois estados: o botão está apertado ou não, o relé está ligado ou não. Tudo 0 ou 1.
- Aqui entram os valores do meio: uma tensão que pode parar em qualquer ponto entre 0 V e 5 V, e o número que representa essa tensão.
- Depois daqui vêm a saída analógica (fabricar o meio-termo com PWM) e a decisão automática com
if.
Aquecimento: relé e dois botões
Objetivo: o botão da entrada 2 acende o LED do pino 13; o botão da entrada 4 aciona o módulo relé do pino 5. Clique numa linha para ver a explicação.
const int PINO_BOTAO_LED = 2;
const int PINO_BOTAO_RELE = 4;
const int PINO_RELE = 5;
const int PINO_LED = 13;
const bool RELE_ATIVO_EM_LOW = true;
void setup() {
digitalWrite(PINO_RELE, RELE_ATIVO_EM_LOW ? HIGH : LOW);
pinMode(PINO_RELE, OUTPUT);
pinMode(PINO_BOTAO_LED, INPUT_PULLUP);
pinMode(PINO_BOTAO_RELE, INPUT_PULLUP);
pinMode(PINO_LED, OUTPUT);
}
void loop() {
bool botaoLed = (digitalRead(PINO_BOTAO_LED) == LOW);
bool botaoRele = (digitalRead(PINO_BOTAO_RELE) == LOW);
digitalWrite(PINO_LED, botaoLed ? HIGH : LOW);
bool nivelParaLigar = RELE_ATIVO_EM_LOW ? LOW : HIGH;
digitalWrite(PINO_RELE, botaoRele ? nivelParaLigar : !nivelParaLigar);
}
Arquivo: codigo/aquecimento_rele_dois_botoes_uno.ino
Digital e analógico
O botão tem dois estados. O mundo não. Luz, temperatura, giro e nível passam por todos os valores do meio, e é disso que esta aula trata.
Transdutor é qualquer peça que transforma uma forma de energia em outra. Sensor é o transdutor usado para medir: ele entrega, em forma elétrica, uma grandeza do mundo. O LDR muda de resistência com a luz. O LM35 entrega uma tensão que sobe com a temperatura. O trimpot transforma o giro do seu dedo em tensão.
Um conversor, seis portas
analogRead gira essa chave e dispara uma conversão.O pino mede tensão. Só tensão.
A entrada analógica não mede resistência, nem corrente, nem temperatura. Ela mede a tensão entre o pino e o GND. Tudo que você quiser ler precisa virar tensão antes de chegar lá.
O conversor: de tensão a número
Este é o mecanismo central da aula. Entenda a escada aqui e o resto vira consequência.
- Ponha os números na fórmula: 1,5 × 1024 ÷ 5.
- Multiplique e divida: 1,5 × 1024 = 1536, e 1536 ÷ 5 = 307,2.
- Jogue fora o ",2". O conversor devolve 307.
- Caminho de volta, que você vai usar o tempo todo: 307 × 5 ÷ 1024 = 1,50 V.
- 3 × 1024 ÷ 5 = 614,4.
- Sem a parte decimal, o código é ?.
Calcule o código. Depois faça o caminho de volta e diga que tensão esse código representa.
Fórmula e o significado do código de topo (0x3FF = Vref menos 1 LSB): ATmega328/P, Atmel-42735B, §28.7.
1023 não é 5 V
Faça a conta do topo com a fórmula: 5 × 1024 ÷ 5 = 1024. Mas 1024 não cabe em dez bits, onde o maior número é 1023. O conversor trava ali. Ou seja: o código 1023 representa 1023 × 5 ÷ 1024 = 4,995 V, um degrau abaixo da referência, e ainda serve para tudo que estiver acima disso.
Alguns pontos da escada, com referência de 5 V
| Tensão no pino | Conta | Código lido |
|---|---|---|
| 0 V | 0 × 1024 ÷ 5 = 0 | 0 |
| 1,5 V | 1,5 × 1024 ÷ 5 = 307,2 | 307 |
| 3 V | 3 × 1024 ÷ 5 = 614,4 | 614 |
| 5 V | 5 × 1024 ÷ 5 = 1024 | 1023 |
A última linha é a mais instrutiva: a conta dá 1024 e o conversor entrega 1023. Isso é saturação: o número bateu no teto e parou de subir.
Por que dez bits
Bancada do conversor
Mexa na tensãoAcima da referência o código satura em 1023: o conversor não tem número maior.
O erro de quantização é a diferença entre a tensão de verdade e a que o código representa. Ele nunca chega a um degrau inteiro, a não ser no topo, quando o número satura.
Resolução não é precisão
Um degrau vale 5 V ÷ 1024 = 4,88 mV. Essa é a resolução: o menor passo que o número consegue dar. Já o erro do conversor inteiro, medido no laboratório do fabricante, é de cerca de ±2 degraus, ou 9,8 mV. Essa é a precisão absoluta: o quanto o número pode estar deslocado da tensão de verdade.
Na prática: não adianta mostrar a leitura com quatro casas decimais. Os últimos dígitos dançam.
Precisão absoluta típica de 2 LSB e resolução de 10 bits: ATmega328/P, Atmel-42735B, Table 32-11.
Quanto tempo leva uma leitura
O conversor tem um relógio próprio, que o núcleo do Arduino configura como o relógio da placa dividido por 128: 16 MHz ÷ 128 = 125 kHz. Uma conversão normal gasta 13 batidas desse relógio, ou seja 104 µs. Isso dá cerca de 9615 leituras por segundo; a documentação arredonda para "cerca de 10 mil".
Guarde a ordem de grandeza: ler é rápido. Quem atrasa o seu programa é o delay que você escreve e a linha que você manda para a Serial.
Tempo de conversão e divisão do relógio: ATmega328/P, Atmel-42735B, §28.4; divisor por 128 configurado em wiring.c do núcleo Arduino AVR 1.8.6.
O trimpot: girar o dedo vira volts
O pino só entende tensão. O trimpot é o jeito mais simples de fabricar uma tensão que você controla com o dedo — e ele não faz mágica nenhuma: divide os 5 V em dois pedaços.
Na bancada do conversor você empurrou uma tensão com o mouse. No kit real, alguém precisa produzir essa tensão. Todo sensor analógico termina no mesmo lugar: um ponto do circuito cuja tensão sobe e desce. Aqui quem faz ela subir e descer é o seu dedo.
Trimpot é o apelido de um potenciômetro pequeno, ajustado com chave de fenda. Potenciômetro é o mesmo componente, com eixo e botão. Funcionam igual; os dois servem.
Você já girou um destes hoje
O botão de volume de um rádio, o dimmer de parede que escurece a sala, o joystick do videogame e boa parte dos pedais de acelerador eletrônicos têm, quase sempre, a mesma peça por dentro: um potenciômetro. As exceções são recentes e confirmam a ideia: aparelhos digitais trocam o botão de volume por um encoder, e os pedais mais novos trocam o potenciômetro por um sensor magnético sem contato, mas em todos eles uma posição vira um sinal elétrico que um conversor lê. O trimpot do kit é essa peça em miniatura, sem o eixo e sem o knob. Se você tiver um potenciômetro de painel de 10 kΩ, com eixo, use-o à vontade: é mais fácil de girar com o dedo e a aula inteira vale igual.
- A trilha toda vale 10 kΩ. No meio do curso, o cursor parte a trilha ao meio: R1 = 5 kΩ e R2 = 5 kΩ.
- Tensão no cursor: 5 V × 5000 ÷ (5000 + 5000) = 2,50 V.
- O que o conversor devolve: ⌊2,50 × 1024 ÷ 5⌋ = 512. E 512 volta a 2,50 V pela conta inversa.
- Os extremos: encostado no 5 V dá 5 V; encostado no GND dá 0 V. Nunca mais que isso, porque não existe tensão maior que a da fonte.
O cursor parou onde R1 = 7,5 kΩ e R2 = 2,5 kΩ.
- Tensão no cursor: 5 × 2500 ÷ 10000 = ? V.
- Código no Uno: ⌊… × 1024 ÷ 5⌋ = ?.
Mesmo trimpot de 10 kΩ, agora com R1 = 6 kΩ e R2 = 4 kΩ. Qual é a tensão no cursor e qual código o Uno devolve?
Por que 10 kΩ, e não 1 kΩ nem 100 kΩ?
O ADC não mede a tensão direto do fio. Ele fecha uma chave por alguns microssegundos, enche um capacitor minúsculo de 14 pF com a tensão do pino, abre a chave e converte a carga guardada. Esse capacitor tem nome: sample-and-hold, ou S/H.
Quem enche o capacitor é a sua fonte. Pouca resistência enche num instante; muita resistência não termina no tempo disponível, e o número sai puxado na direção da leitura anterior — que pode ter sido de outro canal.
O datasheet do chip resolve a discussão em uma frase: a fonte ligada à entrada analógica deve ter aproximadamente 10 kΩ ou menos.
Fonte: ATmega328/P, Atmel-42735B (11/2016), §28.6.1 Analog Input Circuitry — capacitor de amostragem de 14 pF e a recomendação de impedância de fonte.
E os outros valores? Com 1 kΩ a trilha puxa 5 mA e queima 25 mW o tempo todo, sem nenhum ganho. Com 10 kΩ são 0,5 mA e 2,5 mW: nada esquenta. Com 100 kΩ a corrente deixa de ser problema, mas o pior caso visto pelo ADC sobe para 25 kΩ — o capacitor de amostragem não termina de encher a tempo, e a leitura sai puxada na direção do canal medido antes dela. O tempo da conversão não muda: continua em 104 µs; o que muda é a tensão que o capacitor conseguiu guardar.
Bancada do trimpot
Gire e acompanheTrilha de 10 kΩ: o ADC nunca enxerga mais que 2,5 kΩ. Folga confortável.
Experimento 1: o trimpot na Serial
Objetivo: ligar o trimpot de 10 kΩ na entrada A1, imprimir o número lido no Monitor Serial e comparar esse número com o que o multímetro marca no mesmo ponto.
trimpot_serial_uno.ino.- Com a placa desligada da USB, espete o trimpot na protoboard, cada perna em uma linha diferente. Ligue a perna 1 ao 5V, a perna 3 ao GND e o cursor ao A1.
- Grave o
trimpot_serial_uno.inoe abra o Monitor Serial em 9600 baud. Se aparecer lixo na tela, a velocidade da janela não é a do sketch. - Gire devagar de um extremo ao outro: os números varrem de 0 a 1023.
- Feche o Monitor e abra o Serial Plotter, no mesmo menu. O número vira um gráfico que sobe e desce com o seu dedo.
- Com o multímetro em tensão contínua, ponta preta no GND e ponta vermelha em A1, meça três posições do cursor e compare com
código × 5 ÷ 1024.
Monitor Serial virtual
Uma linha a cada 100 msO delay(100) do sketch dá dez linhas por segundo. As leituras acima acompanham o cursor; a janela mostra o que a Serial imprimiu, com o tremido de um degrau que existe no kit de verdade.
Anote o que você mediu
Preencha a tabela na hora do experimento e guarde as conclusões na caixa abaixo, que fica salva neste navegador.
| Posição do cursor | Tensão no multímetro | Código lido | Código × 5 ÷ 1024 | Diferença |
|---|---|---|---|---|
| Um extremo | ||||
| Perto do meio | ||||
| O outro extremo |
analogRead na prática
Quatro linhas põem o número do trimpot na tela do computador. As armadilhas não estão nas quatro linhas: estão na conta que vem depois delas.
O código mínimo
Este é o sketch inteiro. Clique em qualquer linha para ver a explicação.
const int PINO_TRIMPOT = A1;
void setup() {
Serial.begin(9600);
}
void loop() {
int valor = analogRead(PINO_TRIMPOT);
Serial.println(valor);
delay(100);
}
Repare no que não está lá: nenhum pinMode. Entrada analógica não tem modo para configurar. O analogRead escreve o número do canal num registrador chamado multiplexador, que é a chave de seis posições que escolhe qual dos pinos A0 a A5 chega ao único conversor do chip, e dispara a conversão.
Fonte: ArduinoCore-avr 1.8.6, wiring_analog.c — analogRead só escreve o canal em ADMUX, liga o bit de início e espera o fim da conversão.
De número para volts e para porcentagem
O número sozinho não diz nada a ninguém. Duas linhas resolvem:
float volts = valor * 5.0 / 1024.0;int porcento = valor * 100L / 1023;
Repare nos dois denominadores diferentes, e é de propósito: os volts dividem por 1024 porque seguem a fórmula do chip; a porcentagem divide por 1023 para o topo do curso, código 1023, dar exatamente 100%.
Os detalhes chatos dessas duas linhas derrubam mais gente do que o circuito inteiro. Antes da explicação, arrisque:
Três regras saem dali:
- Ponha a casa decimal.
5.0e1024.0são ponto flutuante;5e1024são inteiros. Basta um lado ter casa decimal para a conta inteira virar float. - A ordem importa.
valor / 1024 * 5.0divide primeiro, e como 307 ÷ 1024 dá 0 entre inteiros, o resultado final é 0,00 V. Multiplique antes, divida depois. - Cuidado com o estouro. Um
intno Uno guarda até 32767, evalor * 100passa de 100 mil. OLem100Lmanda calcular emlong, que aguenta.
Conversor de unidades
Arraste o códigoAs duas versões da conversão, com a referência de 5 V
float volts = valor * 5.0 / 1024.0;
Serial.print(volts, 2) imprime 1.50
int volts = valor * 5 / 1023;
Serial.print(volts) imprime 1
A Serial escreve o separador decimal com ponto: é o ponto do C, não um erro seu. E repare que a versão errada só acerta por acidente, quando o resultado calha de ser redondo.
Quem é o lento aqui: o conversor ou a Serial?
Uma conversão leva 104 µs no Uno: o clock do conversor é o da placa dividido por 128, ou seja 125 kHz, e cada conversão gasta 13 ciclos. Dá cerca de 9615 leituras por segundo.
Fontes: ATmega328/P, Atmel-42735B, §28.4 Prescaling and Conversion Timing (13 ciclos por conversão) e ArduinoCore-avr 1.8.6, wiring.c (prescaler 128 em 16 MHz, ou seja clock de 125 kHz no ADC).
Agora a outra ponta: imprimir 1023 mais o fim de linha são seis caracteres, e a 9600 baud cada caractere ocupa dez bits de tempo. A linha inteira leva 6,25 ms.
Quem segura o ritmo não é o conversor: é a Serial. É por isso que o delay(100) existe e que o Serial Plotter fica bonito com pausas entre 50 e 100 ms. Sem pausa, o buffer enche, o loop passa a esperar por ele e a janela vira uma cachoeira ilegível.
Pino solto e ruído
Deixe um pino analógico sem nada ligado e leia: você não vê 0, vê números pulando. Uma entrada de altíssima impedância capta o campo elétrico de tudo em volta, e a documentação do Arduino avisa que o valor depende das outras entradas e até de quão perto está a sua mão.
Com o trimpot ligado isso quase some, porque a trilha de 10 kΩ segura o pino. Mas o último dígito ainda treme: um degrau vale 4,88 mV, e o erro típico do conversor é de dois degraus, ou 9,8 mV.
A versão que serve para o Serial Plotter
O trimpot_volts_uno.ino imprime três colunas separadas por tabulação. O Plotter entende cada coluna como uma curva.
const int PINO_TRIMPOT = A1;
void setup() {
Serial.begin(9600);
}
void loop() {
int valor = analogRead(PINO_TRIMPOT);
float volts = valor * 5.0 / 1024.0;
int porcento = valor * 100L / 1023;
Serial.print(valor);
Serial.print('\t');
Serial.print(volts, 2);
Serial.print('\t');
Serial.println(porcento);
delay(100);
}
Referência: o metro contra o qual tudo é medido
1023 não quer dizer 5 V por decreto. Quer dizer "o topo da referência, menos um degrau". Trocar a referência troca o significado de todos os números que o sketch imprime.
Fontes: ATmega328/P, Atmel-42735B, Table 28-3 ADC Voltage Reference Selection (AREF, AVCC e a interna de 1,1 V) e Table 32-11 (referência externa de 1,0 V até AVCC; referência interna de 1,0 a 1,2 V, típica 1,1 V).
Cuidado com um engano comum: 1,1 V não é um mínimo do pino AREF. A referência externa aceita de 1,0 V até a tensão de alimentação; 1,1 V é o valor típico da referência que já vem dentro do chip.
- O LM35 entrega 10 mV para cada grau. A 25 °C, a saída dele é 250 mV.
- Com a referência padrão de 5 V: ⌊0,250 × 1024 ÷ 5⌋ = 51. Um degrau vale 4,88 mV, ou 0,49 °C: o termômetro anda de meio em meio grau e usa só o comecinho da escala.
- Com
analogReference(INTERNAL), a referência vira 1,1 V: ⌊0,250 × 1024 ÷ 1,1⌋ = 232. Agora um degrau vale 1,07 mV, ou 0,11 °C. - Mesmo sensor, mesma temperatura, mesma fiação. Só a régua mudou — e a leitura ficou cerca de 4,5 vezes mais fina (5 ÷ 1,1).
Com a referência interna, tudo acima de 1,1 V vira 1023. Qual é a maior temperatura que esse termômetro ainda consegue distinguir?
- 1,1 V ÷ 0,010 V/°C = ? °C.
Você trocou para a referência interna e esqueceu o trimpot ligado no 5 V. Gira o cursor de um extremo ao outro. O que o Monitor Serial mostra?
LM35 com 5 V ou com 1,1 V
Mova a temperaturaNesta faixa as duas referências funcionam. Empurre a temperatura para cima e veja qual das duas desiste primeiro.
O LM35 entrega 10 mV por grau (datasheet do LM35, Texas Instruments). Aqui ele é simulado como um sensor ideal, sem erro próprio.
Experimento 2, opcional: o LM35 de verdade
Se você tiver um LM35 na gaveta, vale meia hora; se não tiver, a bancada acima já ensina o essencial. Com a face chata virada para você, as três pernas são, da esquerda para a direita: alimentação, saída e GND. Confira no datasheet do seu antes de energizar: encapsulamento trocado queima o sensor na hora.
- Alimentação no 5V, GND no GND, saída no A0. Nada de resistor: a saída do LM35 já é uma tensão pronta.
- Grave o
lm35_referencia_interna_uno.ino. Ele chamaanalogReference(INTERNAL)nosetup, descarta a primeira leitura — trocar a referência leva tempo, e a documentação do Arduino avisa que as primeiras podem sair erradas — e tira a média de oito. - Anote o número com o sensor no ar; depois segure o corpinho entre dois dedos por trinta segundos e anote de novo.
- Converta na mão com a fórmula desta seção e compare com o que o sketch imprime. Guarde os dois números na caixa de observação do Experimento 1.
Resolução não é precisão
Um degrau de 4,88 mV é a resolução: o menor pedaço que a escala consegue nomear. Ela não promete que o número esteja certo. A precisão absoluta típica do conversor é de dois degraus, ou 9,8 mV, somando erro de ganho, de offset e não linearidade.
Fonte: ATmega328/P, Atmel-42735B, Table 32-11 — Absolute accuracy típica de 2 LSB, que inclui erro de quantização, INL, DNL, ganho e offset.
No termômetro com referência de 5 V, esses 9,8 mV valem cerca de um grau inteiro: o último dígito do display é decoração. É por isso que mais bits, sozinhos, não resolvem nada — e você vai ver isso doer no ESP32-S3, que tem doze.
Nove armadilhas da entrada analógica
Cada uma segue o mesmo ritual: leia o mito, preveja, observe na bancada ou no kit, e só então abra a explicação.
"1023 quer dizer 5 V exatos."
Observe: na bancada do conversor, leve o controle a 5,000 V e leia a tensão que o código representa.
"O analogRead mede a resistência do sensor."
Observe: na bancada do trimpot, troque a trilha de 10 kΩ por uma de 100 kΩ sem mexer no giro. A tensão não muda.
"Preciso de pinMode(A1, INPUT) antes de ler."
Observe: o trimpot_serial_uno.ino não tem nenhum pinMode, e funciona.
analogRead aponta o multiplexador para o canal pedido e dispara a conversão. O pinMode só entra em cena se você usar A0 a A5 como pinos digitais."Pino analógico sem nada ligado lê 0."
Observe: com o sketch rodando, tire o fio do cursor e olhe o Monitor Serial. Depois aproxime a mão da placa.
"A linha int volts = valor * 5 / 1023; dá a tensão."
Observe: no conversor de unidades, compare as duas versões do código com o mesmo 307.
float volts = valor * 5.0 / 1024.0; — o .0 obriga a conta a sair em ponto flutuante. Muitos tutoriais dividem por 1023; a diferença é de no máximo um degrau (4,88 mV, e só no topo da escala), mas a fórmula do fabricante é a de 1024."Girando o trimpot eu mudo a tensão da fonte."
Observe: na bancada do trimpot, olhe a corrente na trilha enquanto gira: ela fica parada em 0,5 mA.
"Mais bits significa medida mais exata."
Observe: na bancada das duas placas, compare os degraus; depois leia a linha de precisão na Ponte.
"No ESP32-S3, 4095 quer dizer 3,3 V."
Observe: na bancada das duas placas, gire até o fim e veja onde o número para de subir.
analogReadMilliVolts() e trate os últimos 6% do giro como zona cega."A0 a A5 só servem para analógico."
Observe: no kit, ligue um botão entre A0 e o GND e use pinMode(A0, INPUT_PULLUP) com digitalRead(A0).
Código completo, linha a linha
Clique em qualquer linha para abrir a explicação. Os dez arquivos estão listados no fim desta seção; a versão ESP32-S3 do primeiro está na Ponte.
Os dois sketches de base já apareceram anotados: trimpot_serial_uno.ino imprime o número cru, e trimpot_volts_uno.ino imprime código, volts e porcentagem em três colunas. Os três de baixo são novos: transformam a leitura em decisão.
Todos os sketches desta página são autorais, escritos para o seu kit.
const int PINO_TRIMPOT = A1;
const int PINO_LED = 13;
const int LIMIAR = 512;
const int INTERVALO_MS = 100;
void setup() {
pinMode(PINO_LED, OUTPUT);
Serial.begin(9600);
}
void loop() {
int valor = analogRead(PINO_TRIMPOT);
bool acima = (valor > LIMIAR);
digitalWrite(PINO_LED, acima ? HIGH : LOW);
Serial.print(valor);
Serial.print('\t');
Serial.println(acima ? "aceso" : "apagado");
delay(INTERVALO_MS);
}
// No limiar exato o LED pisca. A saída é usar dois limiares.
const int PINO_BOTAO = 2;
const int PINO_TRIMPOT = A1;
const float TENSAO_REFERENCIA = 5.0;
const float DEGRAUS = 1024.0;
const unsigned long ESPERA_REPIQUE_MS = 30;
const unsigned long INTERVALO_MS = 200;
bool mostrarVolts = false;
bool estadoEstavel = HIGH;
bool ultimaLeitura = HIGH;
unsigned long instanteMudanca = 0;
unsigned long ultimoEnvio = 0;
void setup() {
pinMode(PINO_BOTAO, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Botao no pino 2 alterna entre codigo e volts.");
}
void loop() {
bool leitura = digitalRead(PINO_BOTAO);
if (leitura != ultimaLeitura) {
instanteMudanca = millis();
ultimaLeitura = leitura;
}
if (leitura != estadoEstavel && millis() - instanteMudanca >= ESPERA_REPIQUE_MS) {
estadoEstavel = leitura;
if (estadoEstavel == LOW) mostrarVolts = !mostrarVolts;
}
if (millis() - ultimoEnvio >= INTERVALO_MS) {
ultimoEnvio = millis();
int valor = analogRead(PINO_TRIMPOT);
if (mostrarVolts) Serial.println(valor * TENSAO_REFERENCIA / DEGRAUS, 2);
else Serial.println(valor);
}
}
const float TENSAO_REFERENCIA = 1.1; // referência interna do chip
const float VOLTS_POR_GRAU = 0.010; // o LM35 entrega 10 mV por grau
const int AMOSTRAS = 8;
void setup() {
Serial.begin(9600);
analogReference(INTERNAL);
analogRead(A0);
}
void loop() {
long soma = 0;
for (int i = 0; i < AMOSTRAS; i++) { soma += analogRead(A0); delay(5); }
float codigo = soma / (float)AMOSTRAS;
float temperatura = codigo * TENSAO_REFERENCIA / 1024.0 / VOLTS_POR_GRAU;
Serial.println(temperatura, 1);
delay(1000);
}
O if desses dois sketches ganha uma aula só para ele mais adiante; aqui entra como ferramenta.
Faltam os dois do desafio: desafio_nivel_uno.ino e desafio_nivel_esp32s3.ino tratam o trimpot como a boia de um reservatório e disparam o alarme abaixo de 20%. O enunciado está no desafio de criação.
Todos os sketches desta aula
Ficam na pasta codigo/, ao lado desta página. Clique para abrir ou salvar, e cole na IDE.
| Arquivo | Placa | O que faz |
|---|---|---|
aquecimento_rele_dois_botoes_uno.ino | Arduino Uno | Aquecimento: um botão acende o LED 13, o outro comanda o módulo relé ativo em LOW. |
trimpot_serial_uno.ino | Arduino Uno | O sketch de base: lê o trimpot em A1 e imprime 0 a 1023 na Serial. |
trimpot_serial_esp32s3.ino | ESP32-S3 N16R8 | O mesmo no GPIO4: código de 12 bits e milivolts calibrados. |
trimpot_volts_uno.ino | Arduino Uno | Código, volts e porcentagem em três colunas, para o Serial Plotter. |
trimpot_volts_esp32s3.ino | ESP32-S3 N16R8 | As mesmas colunas com analogReadMilliVolts(), sem conta na mão. |
trimpot_limiar_led_uno.ino | Arduino Uno | A leitura vira decisão: o LED 13 acende acima de 512. |
intercalado_botao_trimpot_uno.ino | Arduino Uno | Digital e analógica juntas: o botão do pino 2 alterna entre código e volts. |
lm35_referencia_interna_uno.ino | Arduino Uno | LM35 em A0 com analogReference(INTERNAL), primeira leitura descartada, média de 8. |
desafio_nivel_uno.ino | Arduino Uno | Desafio: trimpot como boia, nível em porcentagem, alarme abaixo de 20%. |
desafio_nivel_esp32s3.ino | ESP32-S3 N16R8 | O mesmo em 3,3 V, com o LED RGB da placa em vermelho ou verde. |
O mesmo giro, na outra placa
A ideia não muda: uma tensão entra, um número sai. Mudam três coisas, e uma delas pode queimar a placa — a alimentação é 3,3 V, a escada tem 4096 degraus, e o topo do curso satura antes do fim.
| Nesta aula | Arduino Uno | ESP32-S3 DevKitC-1 N16R8 |
|---|---|---|
| Alimentação do trimpot | 5V | 3V3 — nunca o 5V |
| Resolução do conversor | 10 bits: 0 a 1023 | 12 bits: 0 a 4095 |
| Tamanho de um degrau | 4,88 mV (5 V ÷ 1024) | 0,76 mV (valor ideal estimado: 3,1 V ÷ 4096) |
| Faixa que o conversor mede | 0 V até a referência (5 V) | 0 V até cerca de 3,1 V (atenuação padrão do núcleo). Com o trimpot no 3V3 nominal (3,30 V), satura a partir de 94% do curso; se o regulador entregar outro valor, o percentual muda |
| Faixa com erro garantido | toda a escala | até 2,9 V, ou 88% do curso |
| Precisão típica | ±2 degraus, cerca de 9,8 mV | ±50 mV, já com a calibração de fábrica |
| Pinos de entrada | A0 a A5 (também as digitais 14 a 19) | ADC1 nos GPIO1 a GPIO10; ADC2 nos GPIO11 a GPIO20, indisponível com Wi-Fi. Aqui usamos o GPIO4 (ADC1_CH3) |
| Referência | AVCC (5 V), interna de 1,1 V ou o pino AREF (1,0 V até AVCC) | Não existe AREF: quem define a faixa é a atenuação, com analogSetAttenuation() |
| Funções a mais | — | analogReadMilliVolts(), analogReadResolution(), analogSetAttenuation() |
| Corrente na trilha de 10 kΩ | 0,5 mA | 0,33 mA |
Fontes: ESP32-S3 Series Datasheet v2.2 (Espressif), §4.2.2.1 SAR ADC, Table 2-8 (funções analógicas por GPIO), Table 5-5 (características do ADC) e Table 5-6 (erro após calibração); documentação Arduino-ESP32 3.3.11, api/adc, e o núcleo esp32-hal-adc.c; ATmega328/P, Atmel-42735B (11/2016), §28.7 e Table 32-11.
O mesmo sketch nas duas placas
A linha que lê o pino é igual. O que muda é a velocidade da Serial, o nome do pino e a função extra que devolve milivolts já calibrados.
Arduino Uno
const int PINO_TRIMPOT = A1;
void setup() {
Serial.begin(9600);
}
void loop() {
int valor = analogRead(PINO_TRIMPOT);
Serial.println(valor); // 0 a 1023
delay(100);
}
ESP32-S3 N16R8
const int PINO_TRIMPOT = 4;
void setup() {
Serial.begin(115200);
// analogReadResolution(10);
}
void loop() {
int valor = analogRead(PINO_TRIMPOT);
uint32_t mV = analogReadMilliVolts(PINO_TRIMPOT);
Serial.print(valor);
Serial.print('\t');
Serial.println(mV);
delay(100);
}
O mesmo giro nas duas placas
Mexa no controleConfiguração do Arduino IDE para o N16R8
- Placa: ESP32S3 Dev Module.
- Flash Size: 16MB (128Mb). PSRAM: OPI PSRAM.
- USB CDC On Boot: Enabled, para o Monitor Serial usar a porta USB-C nativa.
- Monitor Serial em 115200, e não em 9600.
- Se o upload falhar: segure BOOT, aperte RESET, solte BOOT, tente de novo.
Onde a entrada analógica aparece em IoT e robótica
Todo dado que não é "ligado ou desligado" entra no microcontrolador por um conversor como o que você acabou de estudar.
Posição de uma junta ou de uma garra
Dentro de quase todo servo há um potenciômetro preso ao eixo: é assim que ele sabe onde está. Do lado de fora você faz igual — um potenciômetro no eixo do braço, um analogRead, e o programa conhece o ângulo.
Bateria do robô
Um pack 2S cheio tem 8,4 V, 1,7 vezes o que o pino aceita. Um divisor de 100 kΩ e 47 kΩ derruba isso para 2,69 V, que no Uno vira o código 550. No código você multiplica de volta pelo fator 3,128 e tem a tensão da bateria na tela.
Sensores que mudam de resistência
LDR (luz), NTC (temperatura), FSR (força) e sonda de umidade do solo mudam de resistência, e resistência o pino não lê. Cada um entra num divisor com um resistor fixo, no lugar de metade do trimpot: o pino lê o meio.
Joystick analógico
São dois trimpots em cruz, um por eixo, e dois analogRead por volta do loop. Em repouso os dois param perto do meio (512), nunca exatamente nele: daí vem a "zona morta" de todo firmware de joystick.
O ponto de entrada de quase todo dado de IoT
O ESP32-S3 faz o mesmo analogRead e, com o Wi-Fi ligado, publica o número: um gráfico no celular, um alarme por mensagem. Só lembre de usar um pino do ADC1 — o ADC2 não funciona junto com o Wi-Fi.
- O divisor entrega 8,4 × 47 ÷ (100 + 47) = 2,69 V no pino. Cabe nos 5 V do Uno e ainda fica na faixa calibrada do ESP32-S3.
- O conversor do Uno devolve ⌊2,69 × 1024 ÷ 5⌋ = 550.
- Para voltar à bateria, multiplique pelo fator (100 + 47) ÷ 47 = 3,128: 550 × 5 ÷ 1024 × 3,128 dá os 8,4 V de novo.
Os resistores são grandes de propósito, para a bateria não se descarregar pelo divisor. O preço é uma fonte "pesada", bem acima dos 10 kΩ do datasheet: leia duas vezes e use a segunda leitura, ou ligue 100 nF do ponto de leitura para o GND. Use resistores de 1 %: com tolerância de 5 %, o fator 3,128 pode errar até 7%.
Pratique até marcar tudo
Só passe adiante quando todos os "Eu consigo" estiverem marcados com honestidade. Tudo aqui fica salvo neste navegador.
Eu consigo…
Caixa Feynman
Explique, para alguém de 12 anos, como uma tensão vira um número inteiro e por que o maior número não é a tensão da referência. Se travar numa palavra, é ali que está a lacuna.
Salva sozinho enquanto você digitaAgora o trimpot: explique por que girar o eixo muda a tensão no cursor sem mudar a tensão da fonte, e por que ele é de 10 kΩ.
Salva sozinho enquanto você digitaFlashcards
Clique para virar. Responda em voz alta antes.
Agenda de revisão espaçada
As datas contam do dia em que você abriu esta página pela primeira vez. Cada revisão aponta para um bloco daqui: a bancada do conversor, o trimpot no kit, a bancada da referência e o desafio.
Exercício intercalado: botão digital + trimpot analógico
Junte as duas entradas: no pino 2, um botão em INPUT_PULLUP ligado ao GND; em A1, o trimpot. Cada aperto alterna o que a Serial imprime — ora o código puro, ora a tensão em volts.
Preveja antes de gravar: você aperta o botão e segura por dois segundos. Quantas vezes a impressão troca?
Uma vez só, se o sketch reagir à borda: a leitura em que o pino acabou de passar de HIGH para LOW. Enquanto você segura, ele continua em LOW e nada mais acontece. Se trocar duas ou três vezes num aperto só, é o repique do contato, que quica tanto ao fechar quanto ao abrir — por isso o sketch só aceita uma mudança depois de o pino ficar parado por 30 ms no novo estado.
O sketch está em intercalado_botao_trimpot_uno.ino. Variação: imprima as duas colunas sempre e use o botão para congelar a leitura.
Sensor de nível de reservatório
O trimpot faz o papel da boia: cursor no extremo do GND é reservatório vazio; no extremo dos 5 V, cheio. O programa lê A1, converte em porcentagem, imprime o nível a cada 500 ms e acende o LED do pino 13 abaixo de 20%. Um LDR serve igual: mais luz, mais "água".
Isso não é invenção de exercício: é como o carro mede o combustível. No tanque há uma boia presa a um braço, e o braço arrasta o cursor de uma trilha resistiva. Nos carros modernos, o módulo do painel lê a tensão que essa resistência produz num divisor e move o ponteiro; nos antigos, o próprio ponteiro era movido pela corrente que atravessava o sensor, sem módulo nenhum. Repare num detalhe de projeto que você vai reencontrar na sua variação: com o carro andando o combustível balança, a boia sobe e desce a cada curva, e um ponteiro que seguisse a leitura crua dançaria o tempo todo. Por isso o painel amortece a leitura de propósito: nos antigos, pela inércia térmica do medidor, de um a dois segundos; nos modernos, por média em software, por vários segundos. A média e a histerese que a rubrica pede existem em produção há décadas, dentro de qualquer carro.
Sua variação (é ela que vale como "criar"): histerese, para o alarme não tremer no limite (liga em 20%, só desliga em 25%); média de 8 leituras; ou dois níveis, um aviso e um alarme.
Rubrica, para ler antes de dizer que terminou:
- O nível aparece a cada 500 ms e bate com o cursor nos dois extremos (0% e 100%).
- O alarme acende abaixo de 20% e apaga sozinho quando o nível sobe.
- O número não pula sozinho com o cursor parado: já tem média, histerese ou as duas.
- A mesma lógica roda no ESP32-S3 e você sabe dizer por que o número lá é outro.
Pontos de partida: desafio_nivel_uno.ino e desafio_nivel_esp32s3.ino, com o LED RGB da placa no lugar do pino 13.
Ainda não: bomba de verdade, sensor ultrassônico, nível pela rede. Primeiro o número tem que estar certo na Serial.
Simuladores e fontes
Grátis, no navegador. Cada um mostra uma parte diferente da mesma história.
Wokwi
Arduino Uno com o código de verdade. Monte: Uno + potenciômetro deslizante (procure "potentiometer" na lista de peças), as pontas no 5V e no GND, o cursor em A1; cole o sketch do trimpot e abra o Serial Monitor. Depois troque para o Serial Plotter.
Tinkercad Circuits
Protoboard virtual com multímetro. Monte o potenciômetro em A0 e veja o Monitor Serial acompanhar o giro. Depois troque-o por uma chave deslizante entre 5 V e GND: só aparecem 0 e 1023, nunca o meio — digital e analógico na mesma tela.
Falstad CircuitJS
Mostra a corrente como pontinhos. Monte: fonte de 5 V, um potenciômetro (Draw → Passive → Potentiometer) e um voltímetro no cursor. Arraste o cursor: a tensão muda, a corrente pela trilha não.
PhET: Kit de Construção de Circuitos DC
Física pura. Monte bateria + dois resistores em série e meça o ponto do meio: é o divisor sem o trimpot. Troque um resistor e confira a fórmula no medidor.
Documentação do Arduino
analogRead() (faixa, tempo de leitura e o aviso do pino solto) e analogReference() (DEFAULT, INTERNAL, EXTERNAL e o risco de curto na referência).
ADC do ESP32-S3
Documentação do ADC no Arduino-ESP32: analogReadMilliVolts(), analogReadResolution() e as atenuações.
Datasheets usados nesta aula
ATmega328/P (Atmel-42735B, 11/2016): §28.1 (ADC de 10 bits), §28.4 (prescaler e os 13 ciclos da conversão), §28.6.1 (circuito de entrada, capacitor de amostragem de 14 pF e a fonte de "cerca de 10 kΩ ou menos"), §28.7 (a fórmula ADC = V_in × 1024 ÷ V_ref e o topo em V_ref − 1 LSB), Table 28-3 (seleção da referência), Table 32-11 (precisão absoluta, VREF, VINT e tempo de conversão) e §32.1 (limites absolutos dos pinos).
ESP32-S3 (datasheet v2.2, Espressif): §4.2.2.1 (dois SAR ADC de 12 bits e o aviso do ADC2 com Wi-Fi), Table 2-8 (quais GPIO são ADC1 e ADC2), Table 5-5 (DNL, INL e taxa de amostragem) e Table 5-6 (erro depois da calibração, por atenuação).
O que o núcleo faz de verdade: wiring.c (prescaler 128, clock do ADC em 125 kHz) e wiring_analog.c (o analogRead inteiro) do Arduino AVR Core 1.8.6; esp32-hal-adc.c do Arduino-ESP32 3.3.11. Sensor de temperatura: LM35 (Texas Instruments), 10 mV por °C.
Canal Crescer Indústria de Automação
Canal do professor Cristiano Nazário, com mais de 400 vídeos. Foi com ele que eu aprendi eletrônica. Blog: crescerengenharia.com/blog.
Material complementar
Se quiser uma segunda voz, procure tutoriais clássicos de "potentiometer with Arduino". Quase todos convertem com ÷ 1023; esta aula usa ÷ 1024, a fórmula do datasheet, e a diferença é de no máximo um degrau.
Glossário
- Analógico
- Grandeza contínua: entre dois valores sempre cabe outro. A tensão no cursor do trimpot é analógica.
- Digital
- Grandeza com valores discretos. Na entrada digital são dois: HIGH e LOW.
- ADC
- Analog-to-Digital Converter: o circuito que transforma uma tensão em um número inteiro. O do Uno tem 10 bits.
- DAC
- O caminho contrário, de número para tensão. O ATmega328P não tem: no lugar, oferece PWM.
- Transdutor
- Peça que converte uma forma de energia em outra (luz em corrente, som em tensão, giro em resistência).
- Sensor
- Transdutor usado para medir: entrega um sinal elétrico proporcional à grandeza física.
- Resolução
- O tamanho do menor passo que o conversor distingue. No Uno com 5 V: 4,88 mV.
- LSB
- Least Significant Bit: o bit de menor peso e, por extensão, o valor de um degrau. Aqui, 4,88 mV.
- Código
- O inteiro que o
analogReaddevolve (0 a 1023 no Uno). Não é volt: é o degrau da escada. - Quantização
- O ato de encaixar uma tensão contínua no degrau de baixo. O que sobra é o erro de quantização, sempre menor que 1 LSB.
- Precisão absoluta
- A distância entre o código lido e o ideal, somados todos os erros do conversor. No Uno, ±2 LSB típicos (9,8 mV).
- Referência (V_ref)
- A tensão que corresponde ao topo da escada. É ela, e não "5 V", que define quanto vale cada degrau.
- AVCC
- O pino de alimentação da parte analógica do chip. É a referência padrão do Uno: 5 V.
- AREF
- Pino da referência externa. Só ligue tensão nele depois de chamar
analogReference(EXTERNAL). - Referência interna
- Fonte de 1,1 V dentro do próprio chip, ligada por
analogReference(INTERNAL). Escada mais fina, teto mais baixo. - Divisor de tensão
- Dois resistores em série entre uma tensão e o GND: o ponto do meio entrega uma fração dela.
- Potenciômetro / trimpot
- Resistor de três pernas com cursor móvel: um divisor ajustável. É o que há dentro do botão de volume, do dimmer e do joystick. "Trimpot" é a versão de ajuste com chave de fenda, quase sempre linear. Na marcação mais comum, B (B103) indica trilha linear e A (A10K) logarítmica, própria para áudio; peças europeias ou antigas podem inverter as letras.
- Cursor
- A perna do meio, ligada ao contato que desliza pela trilha. É de lá que sai a tensão que o pino lê.
- Impedância de fonte
- A resistência que o circuito apresenta ao pino. Alta demais, o conversor não consegue carregar seu capacitor a tempo.
- Sample-and-hold
- O par chave + capacitor (14 pF) que "congela" a tensão no instante da amostra.
- Multiplexador
- Chave eletrônica que liga o conversor a um canal por vez. Por isso A0 a A5 dividem um só ADC.
- Taxa de amostragem
- Quantas conversões por segundo. No Uno, cerca de 9615; no ESP32-S3, até 100 mil.
- Baud
- Símbolos por segundo na porta serial. Em 9600, cada caractere leva dez bits.
- Divisão inteira
- Em C, dividir dois inteiros descarta a parte fracionária.
5 / 1024é 0;5.0 / 1024.0é 0,00488. - Saturação
- Quando a tensão passa do topo da escada e o conversor devolve sempre o maior código (1023 no Uno, 4095 no ESP32-S3).
- Atenuação
- No ESP32-S3, o ajuste que define até que tensão o ADC enxerga. O padrão do Arduino vai até cerca de 3,1 V.
- Calibração
- Correção de fábrica gravada no chip. É o que
analogReadMilliVolts()usa para devolver milivolts.
Aula autoral de Fabrício Ferreira. Aprendi eletrônica no curso do professor Cristiano Nazário (Crescer Indústria de Automação). Esta página não reproduz o material do curso. Site independente, sem vínculo com a empresa. Números técnicos conferidos nos datasheets do ATmega328P (Microchip), do ESP32-S3 (Espressif) e do LM35 (Texas Instruments).
Metodologia: prática de recuperação, revisão espaçada, exemplos resolvidos, três camadas concreto → visual → fórmula, e desmontagem de equívocos.