O que é ADC? Conversão analógico-digital com Arduino
O que é um ADC e como ele funciona? Sinais analógicos e digitais, resolução de 10 e 12 bits, analogReference, fórmula da tensão, ADC2 do ESP32 e redução de ruído.
Um ADC (conversor analógico-digital) é o circuito que transforma uma tensão que varia continuamente em um pino em um número com o qual o microcontrolador pode trabalhar. Toda vez que você chama analogRead() no Arduino, esse conversor faz o trabalho nos bastidores: o ADC de 10 bits do Arduino Uno transforma uma tensão entre 0 e 5 V em um número de 0 a 1023, enquanto os ADCs de 12 bits do ESP32 e do Raspberry Pi Pico transformam aproximadamente 0–3,3 V em um número de 0 a 4095. O ADC é a chave para ler qualquer coisa com saída analógica: potenciômetros, LDRs, sensores de umidade do solo, joysticks e sensores de temperatura.
Neste guia você vai aprender a diferença entre sinais analógicos e digitais, como um ADC transforma uma tensão em um número passo a passo e como a resolução e a tensão de referência afetam suas medições. Com números reais, vamos ver a fórmula que converte uma leitura em volts, como mudar a faixa de medição com analogReference, a taxa de amostragem e formas práticas de reduzir o ruído. Também vamos falar do ADC do ESP32, que não é linear nas extremidades, do conflito do ADC2 com o Wi-Fi e do ajuste de atenuação (attenuation), do uso do ADC do Raspberry Pi Pico com MicroPython e, por fim, fazer uma breve introdução ao DAC, que faz o trabalho inverso.

Qual é a diferença entre sinal analógico e digital?
Um sinal analógico é uma grandeza que pode assumir infinitos valores dentro de uma faixa e varia continuamente ao longo do tempo. Quando a tensão no terminal do meio de um potenciômetro vai de 0 V a 5 V, ela passa por todos os valores intermediários, como 1,2 V, 1,21 V e 1,215 V; a onda sonora de um microfone, a tensão de um termistor que varia com a temperatura e a tensão de uma pilha que cai lentamente também são analógicas. Já um sinal digital só conhece níveis específicos. No mundo da lógica do Arduino, eles são dois: LOW (0) e HIGH (1). No Uno, uma entrada digital considera LOW qualquer coisa abaixo de cerca de 1,5 V e HIGH qualquer coisa acima de 3,0 V; a região entre os dois é indefinida. É por isso que digitalRead() não consegue distinguir 3,7 V de 4,2 V em uma bateria e chama os dois de HIGH. A força do sinal digital é a imunidade ao ruído: 4,6 V e 5,0 V significam o mesmo HIGH. Para medir, armazenar ou fazer cálculos com um valor analógico, primeiro você precisa transformá-lo em um número, ou seja, em um valor digital, e a peça que faz isso é o ADC.
O que é um ADC e como ele funciona?
O trabalho de um ADC pode ser resumido em dois passos. O primeiro é a amostragem: no momento da medição, o conversor copia a tensão de entrada para um pequeno capacitor (o circuito de amostragem e retenção, sample-and-hold) e a mantém estável até a conversão terminar; no ATmega328P esse capacitor tem cerca de 14 pF. O segundo é a quantização: a tensão retida é arredondada para o degrau mais próximo de uma escala que divide a tensão de referência em degraus iguais, e o número do degrau é devolvido como resultado. Os ADCs do Arduino Uno, do ESP32 e do Pico são todos do tipo aproximações sucessivas (SAR, Successive Approximation Register). Um ADC SAR funciona como um jogo de adivinhar números: primeiro testa metade da referência, coloca o bit mais significativo em 1 se a entrada for maior e o deixa em 0 se for menor, depois testa metade da faixa restante e repete isso para cada bit. É assim que um ADC de 10 bits encontra o degrau certo entre 1024 possibilidades com apenas 10 comparações. Para simplificar, a tabela abaixo mostra como um ADC de 4 bits com referência de 5 V mede uma entrada de 3,2 V:
| Passo | Bit testado | Tensão de comparação | A entrada (3,2 V) é maior? | Bits do resultado |
|---|---|---|---|---|
| 1 | Bit 3 (vale 8) | 8 / 16 × 5 = 2,500 V | Sim → 1 | 1000 |
| 2 | Bit 2 (vale 4) | 12 / 16 × 5 = 3,750 V | Não → 0 | 1000 |
| 3 | Bit 1 (vale 2) | 10 / 16 × 5 = 3,125 V | Sim → 1 | 1010 |
| 4 | Bit 0 (vale 1) | 11 / 16 × 5 = 3,4375 V | Não → 0 | 1010 |
| Resultado | Todos os bits concluídos | 1010 = 10 → 10 × 5 / 16 = 3,125 V | Erro de 0,075 V (um degrau vale 0,3125 V) | 1010 |
A diferença de 0,075 V no resultado é o erro de quantização, e nenhum ADC escapa dele: se a tensão real estiver entre dois degraus, o ADC só pode informar um deles. O erro fica abaixo de um degrau (LSB), então quanto menor o degrau, mais fina a medição. Como o capacitor de amostragem e retenção precisa carregar a cada medição, a resistência da fonte que alimenta o ADC também importa: o datasheet do ATmega328P recomenda uma impedância de saída de cerca de 10 kΩ ou menos, e um divisor de tensão com resistência maior não consegue carregar o capacitor a tempo, fazendo as leituras desviarem. Além do tipo SAR encontrado nos microcontroladores, existem outros tipos de ADC. Os ADCs sigma-delta são lentos, mas muito precisos: o HX711, usado em projetos de balança, oferece 24 bits, e o módulo ADS1115, ligado por I2C, oferece 16 bits. Os ADCs flash usam um comparador separado para cada degrau; são extremamente rápidos e aparecem em osciloscópios.
Resolução do ADC: o que significam 10 bits e 12 bits?
A resolução diz em quantos degraus o ADC divide sua faixa de medição. Um ADC de N bits produz 2^N degraus: 10 bits significam 1024 degraus (0–1023), 12 bits, 4096 degraus (0–4095) e 16 bits, 65.536 degraus. A tensão de um único degrau se chama LSB (bit menos significativo) e é calculada com LSB = Vref / 2^N. No Arduino Uno isso dá 5 V / 1024 = 4,88 mV, e no ESP32 e no Pico, 3,3 V / 4096 = 0,81 mV. Ou seja, o Uno não enxerga variações menores que 4,88 mV; com um LM35, que fornece 10 mV/°C, isso equivale a um passo de cerca de 0,5 °C. Mas resolução e exatidão não são a mesma coisa. O ruído do ADC, a não linearidade e o erro da referência tornam inúteis alguns dos bits que existem no papel. A medida disso é o número efetivo de bits (ENOB): o ADC do RP2040, no Raspberry Pi Pico, devolve um resultado de 12 bits, mas segundo o datasheet o número efetivo de bits é 8,7. Vamos comparar os ADCs das três placas lado a lado:
| Característica | Arduino Uno R3 | ESP32 (WROOM-32) | Raspberry Pi Pico |
|---|---|---|---|
| Resolução do ADC | 10 bits (0–1023) | 12 bits (0–4095) | 12 bits (escalonado para 0–65535 no MicroPython) |
| Entradas analógicas | 6 (A0–A5; A0–A7 no Nano) | 18 canais: 8 no ADC1, 10 no ADC2 | 3 pinos (GP26–GP28) + VSYS/3 (GP29) + sensor de temperatura |
| Faixa de medição padrão | 0–5 V | Cerca de 0–3,1 V (atenuação de 11 dB) | 0–3,3 V (ADC_VREF) |
| Um degrau (LSB) | 4,88 mV | Cerca de 0,8 mV | 0,81 mV |
| Opções de referência | DEFAULT (5 V), INTERNAL (1,1 V), EXTERNAL (AREF) | Atenuação: 0, 2,5, 6 e 11 dB | Referência externa no pino ADC_VREF |
| Taxa de amostragem | Cerca de 10.000 leituras/s | 20 kHz – 2 MHz no modo contínuo (DMA) | 500.000 leituras/s no hardware |
| Observação sobre exatidão | Erro absoluto de ±2 LSB | Não linear nas extremidades, precisa de calibração | ENOB de 8,7 bits, offset de cerca de 30 mV |
| Saída analógica (DAC) | Nenhuma (usa-se PWM) | 2 canais, 8 bits (GPIO 25 e 26) | Nenhuma (usa-se PWM) |
Fórmula para converter a leitura do ADC em tensão
O número que o ADC devolve não significa nada sozinho; para transformá-lo em tensão, você usa a tensão de referência e o número de degraus: Tensão = valor do ADC × Vref / 2^N. No Arduino Uno isso fica V = valor × 5,0 / 1024; então, se analogRead() devolveu 512, a tensão no pino é 512 × 5 / 1024 = 2,50 V. No sentido inverso, você descobre a que número uma tensão corresponde com valor = V × 1024 / Vref: 3,3 V é lido como cerca de 675 no Uno. Em muitos exemplos você vai ver uma divisão por 1023 em vez de 1024. O datasheet do ATmega328P dá a fórmula ADC = Vin × 1024 / Vref; o maior valor, 1023, representa um degrau abaixo de Vref. Dividir por 1023 faz o valor máximo mostrar exatamente 5,00 V, mas desloca todos os valores em cerca de 0,1%. Essa diferença é menor que o próprio erro de ±2 LSB do ADC, então as duas formas funcionam; o importante é ser consistente dentro do projeto. A grande fonte de erro, na verdade, é o próprio Vref: o pino 5V de um Uno alimentado por USB costuma ficar entre 4,7 e 5,1 V, e escrever 5,0 na fórmula causa até 5% de erro. Por isso, para medições precisas, meça o pino 5V com um multímetro e coloque o valor real no seu código. A única entrada analógica do ESP8266 (A0) também é de 10 bits; o chip em si mede 0–1 V, e o divisor embutido em placas como a NodeMCU e a Wemos D1 Mini amplia essa faixa para cerca de 0–3,2 V.
| Placa e configuração | Faixa de leitura | Conversão para volts | Exemplo |
|---|---|---|---|
| Arduino Uno / Nano (DEFAULT, 5 V) | 0–1023 | V = valor × 5,0 / 1024 | 768 → 3,75 V |
| Uno, analogReference(INTERNAL) | 0–1023 | V = valor × 1,1 / 1024 | 512 → 0,55 V |
| ESP32 (11 dB) | 0–4095 | Calibrado: analogReadMilliVolts() / 1000; aproximado: valor × 3,3 / 4095 | 1650 mV → 1,65 V |
| Raspberry Pi Pico (read_u16) | 0–65535 | V = valor × 3,3 / 65535 | 32768 → 1,65 V |
| ESP8266 NodeMCU / Wemos D1 Mini (A0) | 0–1023 | V = valor × 3,2 / 1024 | 512 → 1,60 V |
Ligação do potenciômetro: Arduino, ESP32 e Pico
| Terminal do potenciômetro | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| Terminal externo 1 | 5V | 3V3 | 3V3(OUT) (pino 36) |
| Terminal do meio (sinal) | A0 | GPIO 34 (ADC1_CH6) | GP26 / ADC0 (pino 31) |
| Terminal externo 2 | GND | GND | AGND (pino 33) ou GND |
| Capacitor antirruído opcional | 100 nF entre A0 e GND | 100 nF entre GPIO 34 e GND | 100 nF entre GP26 e AGND |
Passo a passo: sua primeira leitura de ADC com Arduino
- Monte o circuito: Ligue os terminais externos de um potenciômetro de 10 kΩ em 5V e GND, e o terminal do meio em A0.
- Meça o pino 5V: Meça a tensão entre 5V e GND com um multímetro e coloque o valor na constante VREF do código (ex.: 4.93).
- Carregue o código: Abra o sketch abaixo no Arduino IDE, selecione a placa e a porta e carregue-o.
- Abra o Monitor Serial: Ajuste para 9600 baud e observe o valor do ADC variar entre 0 e 1023 conforme você gira o botão (detalhes no guia do Monitor Serial).
- Confira: Meça entre A0 e GND com o multímetro e compare com a tensão na tela; a diferença deve ficar em torno de 10–20 mV.
1// Potansiyometreyi ADC ile okuma / Reading a potentiometer with the ADC
2// Kenar bacaklar 5V ve GND'ye, orta bacak A0'a / Outer legs to 5V and GND, wiper to A0
3const int POT_PIN = A0;
4const float VREF = 5.0; // 5V pininde ölçtüğün gerilim / voltage you measured on the 5V pin
5
6void setup() {
7 Serial.begin(9600);
8}
9
10void loop() {
11 int raw = analogRead(POT_PIN); // 0-1023 arası sayı / number between 0-1023
12 float volts = raw * VREF / 1024.0; // sayıyı volta çevir / convert the number to volts
13 int percent = map(raw, 0, 1023, 0, 100); // yüzdeye ölçekle / scale to percent
14
15 Serial.print(F("ADC: "));
16 Serial.print(raw);
17 Serial.print(F(" Gerilim / Voltage: "));
18 Serial.print(volts, 3);
19 Serial.print(F(" V Yuzde / Percent: "));
20 Serial.println(percent);
21 delay(200);
22}analogRead() faz uma medição em cerca de 100 µs e devolve um inteiro entre 0 e 1023. O código primeiro converte esse número em volts com a fórmula e depois em porcentagem com map(). Como map() usa aritmética de inteiros, ela descarta a parte fracionária; se precisar de um resultado decimal, faça a conta você mesmo com float. Essa é uma medição raciométrica (ratiometric): como o potenciômetro e o ADC são alimentados pelos mesmos 5 V, a posição do botão, e portanto o valor do ADC, não muda mesmo que a alimentação caia para 4,9 V; só a tensão calculada muda. O mesmo vale para sensores lidos por meio de um divisor, como LDRs e NTCs. Por outro lado, quando você mede a tensão de uma bateria ou um sensor com saída fixa em mV, como o LM35, o valor real de Vref vai direto para o resultado.
Tensão de referência e analogReference
A tensão de referência (Vref) é o topo da escala do ADC: se a tensão de entrada for igual ou maior que Vref, o resultado trava no valor máximo (1023). Diminuir Vref estreita a faixa de medição, mas torna cada degrau menor, então você mede sinais pequenos com mais detalhe. No Arduino Uno, você escolhe a referência com a função analogReference(). Com a opção INTERNAL, Vref passa a ser 1,1 V e um degrau cai para 1,07 mV; você consegue ler um LM35 (10 mV/°C) em passos de cerca de 0,1 °C, mas em troca nada acima de 1,1 V, ou seja, 110 °C, pode ser medido. A própria referência interna de 1,1 V pode variar entre 1,0 e 1,2 V de um chip para outro, então projetos precisos exigem uma calibração única com multímetro. As primeiras leituras depois de trocar a referência podem sair erradas, como a própria documentação do Arduino observa, por isso descartar algumas leituras depois da troca é um bom hábito. A configuração de referência também afeta todos os pinos analógicos da placa ao mesmo tempo. As opções variam de placa para placa:
| Opção | Referência | Placas | Quando usar |
|---|---|---|---|
| DEFAULT | 5 V (3,3 V em placas de 3,3 V) | Uno, Nano, Mega, Leonardo | Sensores raciométricos em relação à alimentação, como potenciômetros, LDRs e joysticks |
| INTERNAL | 1,1 V (ATmega328P); 2,56 V no Leonardo | Uno, Nano, Leonardo (não existe no Mega) | Sensores de baixa tensão, como o LM35 |
| INTERNAL1V1 / INTERNAL2V56 | 1,1 V / 2,56 V | Só no Mega | Sinais pequenos no Mega |
| EXTERNAL | A tensão no pino AREF (0–5 V) | Uno, Nano, Mega | Usar sua própria referência de precisão (ex.: 2,5 V ou 4,096 V) |
| AR_INTERNAL | Cerca de 1,43 V (referência interna do chip) | Uno R4 Minima e WiFi | Sinais pequenos no Uno R4 |
Taxa de amostragem: quantas leituras um ADC faz por segundo?
A taxa de amostragem é quantas medições o ADC consegue fazer em um segundo. No Arduino Uno, o clock do ADC é ajustado em 125 kHz dividindo 16 MHz por 128, e uma conversão leva 13 ciclos de clock; é por isso que analogRead() leva cerca de 100 µs e você consegue fazer no máximo umas 10.000 leituras por segundo. Isso é mais que suficiente para grandezas que mudam devagar, como temperatura, luz ou tensão de bateria; muitas vezes até 10 leituras por segundo bastam. Para sinais rápidos, entra em cena a regra de Nyquist: para capturar um sinal sem perdê-lo, é preciso amostrar pelo menos duas vezes mais rápido que sua frequência mais alta, e na prática se prefere 5–10 vezes. Para ver o zumbido de 50 Hz da rede elétrica, você precisa de pelo menos 100 leituras/s, e para gravar voz até 4 kHz, de pelo menos 8.000 leituras/s. Se precisar de leituras mais rápidas no Uno, você pode diminuir o prescaler (divisor) do ADC: colocar ADCSRA = (ADCSRA & 0xF8) | 0x04; em setup() ajusta o divisor para 16, o clock do ADC sobe para 1 MHz e analogRead() cai para cerca de 16 µs, à custa de alguma exatidão. No ESP32, chamadas individuais de analogRead() permitem dezenas de milhares de leituras por segundo, e no modo contínuo com DMA (analogContinuous() no Arduino) você pode escolher uma taxa entre 20 kHz e 2 MHz; esse modo só funciona com pinos do ADC1. O ADC do Raspberry Pi Pico roda com seu próprio clock de 48 MHz, termina cada conversão em 96 ciclos, ou seja, 2 µs, e chega a 500.000 leituras por segundo; um laço em MicroPython não acompanha esse ritmo, e para a velocidade máxima você precisa do C SDK e de DMA.
ADC do ESP32: não linearidade, conflito do ADC2 com o Wi-Fi e atenuação
No papel, o ADC de 12 bits do ESP32 mede quatro vezes mais fino que o do Uno, mas na prática há três pontos de atenção. O primeiro é a não linearidade: perto de 0 V, o ADC do ESP32 lê 0 até cerca de 100–150 mV, e no topo ele satura em 4095 antes de a entrada chegar a 3,3 V; a curva entre os dois também não é uma reta perfeita. O segundo é a variação da referência: por projeto, a referência interna do ESP32 é de 1100 mV, mas segundo a Espressif ela varia entre 1000 e 1200 mV de um chip para outro, o que significa um erro de cerca de ±9% em leituras sem calibração. Por isso a Espressif grava dados de calibração nos eFuses dos chips durante a fabricação. A função analogReadMilliVolts() do Arduino usa esses dados para converter o valor bruto diretamente em milivolts calibrados e, na maioria dos casos, é muito mais exata do que calcular analogRead() × 3,3 / 4095. O terceiro é a atenuação (attenuation): o núcleo do ADC só consegue medir até cerca de 1 V, então tensões maiores são reduzidas por um atenuador ajustável na entrada. O padrão no Arduino é 11 dB, que permite leituras até cerca de 3,1 V, mas a faixa exata que a Espressif recomenda para essa configuração é 150–2450 mV. Para sinais pequenos, diminuir a atenuação melhora tanto a exatidão quanto a resolução:
| Atenuação | Constante no Arduino | Faixa exata | Uso |
|---|---|---|---|
| 0 dB | ADC_0db | 100–950 mV | Sinais pequenos, medição mais fina |
| 2,5 dB | ADC_2_5db | 100–1250 mV | Saídas de sensores em torno de 1 V |
| 6 dB | ADC_6db | 150–1750 mV | Sinais de nível médio |
| 11 dB (padrão) | ADC_11db | 150–2450 mV (as leituras continuam até cerca de 3,1 V) | Potenciômetros e sensores de 0–3,3 V |
1// ESP32 ADC: ham değer ve kalibre milivolt / ESP32 ADC: raw value and calibrated millivolts
2// Potansiyometre: 3V3, GND ve orta bacak GPIO 34 / Pot: 3V3, GND and wiper to GPIO 34
3const int POT_PIN = 34; // ADC1_CH6, Wi-Fi açıkken de çalışır / ADC1_CH6, works with Wi-Fi on
4
5void setup() {
6 Serial.begin(115200);
7 analogReadResolution(12); // 0-4095 (varsayılan / default)
8 analogSetPinAttenuation(POT_PIN, ADC_11db); // yaklaşık 3,1 V'a kadar / up to about 3.1 V
9}
10
11void loop() {
12 uint32_t rawSum = 0;
13 uint32_t mvSum = 0;
14 for (int i = 0; i < 16; i++) { // 16 ölçümün ortalaması / average of 16 readings
15 rawSum += analogRead(POT_PIN); // ham ADC değeri / raw ADC value
16 mvSum += analogReadMilliVolts(POT_PIN); // eFuse kalibrasyonlu mV / eFuse-calibrated mV
17 }
18 float raw = rawSum / 16.0;
19 float naiveV = raw * 3.3 / 4095.0; // basit formül / naive formula
20 float calibratedV = mvSum / 16.0 / 1000.0; // kalibre edilmiş / calibrated
21
22 Serial.printf("Ham / Raw: %4.0f Formul / Formula: %.3f V Kalibre / Calibrated: %.3f V\n",
23 raw, naiveV, calibratedV);
24 delay(500);
25}O código mostra dois resultados lado a lado: o valor bruto convertido com a fórmula simples e o valor calibrado por analogReadMilliVolts(). Conforme você gira o potenciômetro para uma das pontas, vai perceber a diferença aumentar, e lá embaixo, onde a fórmula mostra 0,000 V, o multímetro ainda mede cerca de 0,1 V. analogSetPinAttenuation() muda a atenuação de um único pino, enquanto analogSetAttenuation() muda a de todos os pinos. O ESP32 é bem mais ruidoso que o Uno, principalmente enquanto o Wi-Fi está transmitindo; a própria Espressif recomenda adicionar um capacitor de 100 nF na entrada e tirar a média de várias amostras, que é o que a média de 16 leituras do código faz. Chips mais novos, como o ESP32-S3 e o ESP32-C3, usam uma calibração mais avançada por ajuste de curva, mas os números dos pinos e as regras do ADC2 variam conforme o modelo, então confira sempre o mapa de pinos da sua placa (ferramenta Pinagem). Explicamos como montar um divisor para medir tensões acima de 3,3 V no guia de divisor de tensão.
ADC no Raspberry Pi Pico (MicroPython)
O Raspberry Pi Pico tem três entradas analógicas que você pode usar externamente: GP26 (ADC0), GP27 (ADC1) e GP28 (ADC2). O GP29 (ADC3) mede um terço da tensão de alimentação VSYS na placa, e o ADC4 está ligado ao sensor de temperatura interno do chip. A função read_u16() do MicroPython escala o resultado de 12 bits para a faixa 0–65535, para que o mesmo código funcione em placas diferentes, mas a resolução real continua sendo de 4096 degraus. O RP2040 não tem uma tensão de referência separada; ele usa a própria alimentação do ADC como referência. No Pico, essa alimentação (ADC_VREF, pino 35) vem da saída do regulador chaveado (SMPS) de 3,3 V, filtrada por um resistor de cerca de 200 Ω. O datasheet da placa da Raspberry Pi deixa claras três consequências: a exatidão dos 3,3 V é limitada, a alimentação é um pouco ruidosa e a corrente que o ADC consome cria um offset de cerca de 30 mV. As soluções estão no mesmo documento: colocar o GP23 em HIGH para passar o regulador ao modo PWM, com menos ondulação, ligar um canal do ADC sem uso ao AGND e subtrair sua leitura como offset e, para uma exatidão muito melhor, ligar uma referência de 3,0 V, como o LM4040, entre ADC_VREF e AGND (a faixa de medição passa a ser 0–3,0 V). O ADC do RP2040 também é conhecido por ter pequenos saltos (erros de DNL) nos valores 512, 1536, 2560 e 3584; tirar a média de várias leituras reduz o efeito deles. No Pico W, o GP23 é reservado ao chip sem fio e o modo do regulador é controlado pelo WL_GPIO1, então apague as linhas do GP23 no código abaixo se estiver usando um Pico W.
1from machine import ADC, Pin
2import time
3
4pot = ADC(26) # GP26 = ADC0 (pin 31)
5chip_temp = ADC(4) # dahili sıcaklık sensörü / internal temperature sensor
6VREF = 3.3 # ADC_VREF; multimetreyle ölçüp düzelt / measure and correct with a multimeter
7
8# Yalnız Pico ve Pico 2 (W değil): SMPS PWM moduna, daha az gürültü / Plain Pico and Pico 2 only (not W): SMPS to PWM mode, less noise
9smps_mode = Pin(23, Pin.OUT)
10smps_mode.value(1)
11
12
13def read_average(adc, samples=16):
14 total = 0
15 for _ in range(samples):
16 total += adc.read_u16() # 0-65535 (12 bit ölçeklenmiş / 12-bit scaled)
17 return total / samples
18
19
20while True:
21 raw = read_average(pot)
22 volts = raw * VREF / 65535 # sayıyı volta çevir / convert the number to volts
23 t_volts = read_average(chip_temp) * VREF / 65535
24 temp_c = 27 - (t_volts - 0.706) / 0.001721 # RP2040 veri sayfası formülü / RP2040 datasheet formula
25 print("ADC: {:5d} {:.3f} V Yonga / Chip: {:.1f} C".format(int(raw), volts, temp_c))
26 time.sleep(0.5)Formas de reduzir o ruído do ADC
Mesmo medindo uma tensão estável, é normal o valor do ADC oscilar um ou dois degraus; a quantização, a ondulação na alimentação, a interferência captada por fios longos e motores ou transmissões de Wi-Fi próximos contribuem para isso. No Uno, uma oscilação de ±1–2 degraus é considerada saudável; muito mais que isso geralmente indica um problema no circuito. Você pode combater o ruído tanto no hardware quanto no software:
- Adicione um capacitor: Um capacitor cerâmico de 100 nF entre o pino analógico e o GND filtra interferências rápidas e, com fontes de alta resistência, oferece uma carga pronta ao capacitor de amostragem e retenção.
- Mantenha os fios curtos: Se o cabo do sensor for longo, trance os fios de sinal e de GND; passe os fios de motores e relés longe das linhas analógicas.
- Faça o aterramento direito: Não deixe a corrente de retorno de cargas de alta corrente, como motores, relés e fitas de LED, passar pelo fio GND do sensor; junte os GNDs em um único ponto (aterramento em estrela).
- Use uma referência limpa: A alimentação USB é ruidosa; para medições de tensão absoluta, a referência interna ou um CI de referência externo dão resultados mais estáveis.
- Descarte a primeira leitura depois de trocar de canal: O multiplexador na entrada do ADC pode carregar resíduo do canal anterior; ao ler vários pinos em sequência, jogue fora uma leitura em cada pino.
- Tire a média: A média de N leituras reduz o ruído aleatório em cerca de √N vezes; 16 leituras reduzem o ruído a um quarto.
- Sobreamostragem (oversampling): Se você somar 4^n leituras e deslocar o resultado n bits para a direita, ganha n bits extras de resolução; deslocar a soma de 16 leituras em 2 bits transforma os 10 bits do Uno em 12. Para isso funcionar, o sinal precisa ter pelo menos um degrau de ruído natural.
- Filtros de mediana e exponencial: Um filtro de mediana elimina picos repentinos causados por motores, enquanto uma média móvel exponencial (EMA) gera uma curva suave usando pouquíssima memória.
1// Ham, ortalama ve EMA filtreli ADC değerleri / Raw, averaged and EMA-filtered ADC values
2// Serial Plotter ile izle / Watch with the Serial Plotter
3const int SENSOR_PIN = A0;
4const float ALPHA = 0.1; // EMA katsayısı (0-1) / EMA coefficient (0-1)
5float ema = 0;
6
7void setup() {
8 Serial.begin(115200);
9 analogRead(SENSOR_PIN); // ilk okumayı at / discard the first reading
10 ema = analogRead(SENSOR_PIN); // filtreyi başlat / seed the filter
11}
12
13void loop() {
14 int raw = analogRead(SENSOR_PIN); // ham değer / raw value
15
16 long sum = 0;
17 for (int i = 0; i < 16; i++) { // 16 ölçüm topla / sum 16 readings
18 sum += analogRead(SENSOR_PIN);
19 }
20 float average = sum / 16.0; // ortalama (0-1023) / average (0-1023)
21
22 ema += ALPHA * (raw - ema); // üstel hareketli ortalama / exponential moving average
23
24 Serial.print(F("ham:"));
25 Serial.print(raw);
26 Serial.print(F(" ortalama:"));
27 Serial.print(average);
28 Serial.print(F(" ema:"));
29 Serial.println(ema);
30 delay(20);
31}Quando você carregar o código e abrir o Plotter Serial no Arduino IDE, vai ver três linhas: o valor bruto treme, a média de 16 leituras fica visivelmente mais calma e a EMA é a curva mais suave, mas reage às mudanças um pouco mais tarde. O coeficiente ALPHA é escolhido entre 0 e 1: 0.1 significa que cada nova leitura contribui com 10% para o resultado, então, grosso modo, as últimas 10 leituras têm efeito; aumente o valor e a resposta fica mais rápida, mas o ruído cresce. Qual filtro escolher depende do sinal; uma EMA forte combina com uma temperatura que muda devagar, enquanto uma média curta é melhor para um joystick que precisa de resposta rápida. Comparamos médias móveis, filtros de mediana e histerese com exemplos reais de sensores no guia de filtragem de dados de sensores.
Uma breve introdução ao DAC: do digital para o analógico
Um DAC (conversor digital-analógico) faz o contrário de um ADC: recebe um número e produz uma tensão proporcional a ele. Escreva 0 em um DAC de 8 bits e você terá 0 V, escreva 255 e terá algo perto da tensão de alimentação, escreva 128 e terá cerca da metade. Os DACs mais simples são feitos com uma escada de resistores chamada R-2R. Vamos esclarecer aqui uma confusão comum: analogWrite() no Arduino Uno não é um DAC, ela gera PWM; na verdade o pino alterna rapidamente entre 0 V e 5 V. Isso funciona bem para brilho de LED e velocidade de motor, mas se você realmente precisa de uma tensão estável, tem que adicionar um filtro passa-baixa RC na saída PWM; você pode calcular a constante de tempo do filtro com a ferramenta Constante de tempo RC. Quanto às placas com DAC de verdade: o ESP32 tem dois DACs de 8 bits nos GPIO 25 e GPIO 26, usados com dacWrite(pino, valor), enquanto o ESP32-S3 e o ESP32-C3 não têm DAC. O Arduino Uno R4 tem um DAC de 12 bits no pino A0. Para o Uno R3, o Nano e o Pico, o caminho mais fácil é o módulo MCP4725 de 12 bits, ligado por I2C. Com um DAC você pode gerar som, produzir ondas senoidais ou triangulares e até ligar a saída do DAC a uma entrada de ADC para testar o ADC com tensões conhecidas:
1// ESP32 DAC ile sinüs dalgası / Sine wave with the ESP32 DAC
2// Çıkış GPIO 25'te, osiloskopla izle / Output on GPIO 25, watch it with an oscilloscope
3const int DAC_PIN = 25; // DAC1 = GPIO 25 (DAC2 = GPIO 26)
4const int STEPS = 64; // bir periyottaki nokta sayısı / points per period
5uint8_t sineTable[STEPS];
6
7void setup() {
8 for (int i = 0; i < STEPS; i++) {
9 sineTable[i] = 128 + 127 * sin(2 * PI * i / STEPS); // 1-255 arası tablo / table between 1-255
10 }
11}
12
13void loop() {
14 for (int i = 0; i < STEPS; i++) {
15 dacWrite(DAC_PIN, sineTable[i]); // 0 → 0 V, 255 → yaklaşık 3,3 V / 0 → 0 V, 255 → about 3.3 V
16 delayMicroseconds(150); // yaklaşık 100 Hz / roughly 100 Hz
17 }
18}Ideias de projetos com o ADC
- Voltímetro digital: Meça de 0 a 25 V com um divisor de tensão e mostre o resultado em um LCD; os passos estão no guia Como fazer um voltímetro com Arduino.
- Luz noturna automática: Leia a tensão de um LDR e acenda os LEDs quando escurecer.
- Vaso inteligente: Use a saída analógica de um sensor de umidade do solo para ligar uma bomba quando a terra secar.
- Robô controlado por joystick: Os dois eixos de um joystick são duas entradas analógicas separadas; transforme os valores em velocidade e direção dos motores.
- Medidor de corrente: Leia a tensão proporcional à corrente de um ACS712 para ver quanta corrente um aparelho consome.
- Medidor de nível sonoro: Amostre rapidamente a saída analógica de um sensor de som KY-038 e acenda uma barra de LEDs de acordo com o valor de pico.
- Indicador de bateria: Meça a tensão em um projeto alimentado por bateria e mostre a carga restante em porcentagem em um display.
Erros comuns e como corrigi-los
| Sintoma | Causa provável | Solução |
|---|---|---|
| O valor oscila aleatoriamente sem nada ligado | O pino está flutuando | Ligue o sensor; não leia pinos sem uso ou ligue-os ao GND |
| O valor trava em 1023 (4095 no ESP32) | A entrada está acima da referência ou INTERNAL está selecionado | Ajuste a referência ou a atenuação e reduza tensões altas com um divisor |
| No ESP32, analogRead() devolve 0 quando o Wi-Fi é ligado | O sensor está em um pino do ADC2 | Use os pinos do ADC1, GPIO 32–39 |
| O ESP32 mostra 0 para tensões pequenas e 4095 para tensões grandes | O ADC não é linear nas extremidades | Use analogReadMilliVolts() e mantenha o sinal entre 150–2450 mV |
| A tensão calculada difere do multímetro em 3–5% | Vref não é 5,00 V (alimentação USB) | Meça o pino 5V e coloque o valor em VREF, ou adicione um fator de calibração |
| Ao ler dois pinos em sequência, um valor afeta o outro | Multiplexador e resistência da fonte alta | Descarte a primeira leitura após trocar de canal, mantenha a fonte abaixo de 10 kΩ e adicione 100 nF |
| Os valores pulam quando um motor ou relé funciona | Ruído na linha de GND compartilhada, queda na alimentação | Dê às cargas um retorno de GND próprio, use capacitores e um filtro de mediana |
| As leituras ficaram erradas depois de aplicar tensão no AREF | O AREF foi usado sem chamar analogReference(EXTERNAL) | Selecione EXTERNAL primeiro ou ligue ao AREF por meio de um resistor de 5 kΩ |
| Depois de selecionar INTERNAL, o potenciômetro chega a 1023 na metade do curso | A referência de 1,1 V afeta todos os pinos analógicos | Volte para DEFAULT antes de ler sensores raciométricos e descarte algumas leituras |
| No Pico, a leitura fica acima de 0 mesmo com a entrada em GND | Offset do ADC e ruído no ADC_VREF | Ligue um canal ao AGND, meça o offset e subtraia; coloque o GP23 em HIGH |
O ADC é a ponte entre o mundo físico e o seu código: quando você conhece a resolução, a tensão de referência e a taxa de amostragem, também sabe o que cada número na tela representa e até que ponto pode confiar nele. No Uno, meça a referência direito; no ESP32, use os pinos do ADC1 e analogReadMilliVolts(); no Pico, leve em conta o offset e o ruído; depois acalme o resultado com médias e filtros. No app BlueGrays você encontra projetos baseados em leituras analógicas, como medir a intensidade da luz com LDR, um voltímetro digital com LCD, medição de temperatura com NTC e controle de servo e do brilho de LED com potenciômetro, cada um com esquema do circuito e código passo a passo.
Perguntas frequentes
O que é um ADC e para que serve?
Um ADC (conversor analógico-digital) é o circuito que transforma a tensão em um pino em um número que o microcontrolador pode processar. Ele é usado para ler componentes com saída analógica, como potenciômetros, LDRs e sensores de temperatura e umidade. No Arduino, o comando analogRead() aciona esse conversor.
Qual é a diferença entre sinal analógico e digital?
Um sinal analógico pode assumir qualquer valor dentro de uma faixa e varia continuamente, enquanto um sinal digital é formado apenas por níveis específicos, LOW e HIGH no Arduino. digitalRead() só diz se um pino está em 0 ou 1, enquanto analogRead() informa quanta tensão existe na forma de um número.
Por que o analogRead do Arduino devolve valores de 0 a 1023?
O ADC do Arduino Uno é de 10 bits e produz 2^10 = 1024 degraus diferentes, numerados de 0 a 1023. O valor 0 representa 0 V, e 1023 representa um degrau abaixo da tensão de referência (normalmente 5 V). Os ADCs de 12 bits do ESP32 e do Pico devolvem valores de 0 a 4095.
Como converter o valor do ADC em tensão?
Use a fórmula tensão = valor do ADC × tensão de referência / número de degraus. No Arduino Uno isso fica V = valor × 5,0 / 1024; no ESP32, analogReadMilliVolts() fornece diretamente milivolts calibrados. No Pico, use V = valor × 3,3 / 65535 para o valor de read_u16() do MicroPython.
Os pinos do ADC2 do ESP32 funcionam com Wi-Fi?
Não. No ESP32, o driver do Wi-Fi também usa a unidade ADC2, então não é possível ler os pinos do ADC2 (GPIO 0, 2, 4, 12–15, 25–27) enquanto o Wi-Fi está ligado. Em projetos com Wi-Fi, ligue os sensores analógicos nos pinos do ADC1 (GPIO 32–39).
O que é um DAC e qual a diferença para um ADC?
Um DAC (conversor digital-analógico) faz o contrário de um ADC: transforma um número em tensão. O ADC é usado para medir a tensão que vem de um sensor; o DAC, para produzir uma tensão, como som ou um sinal. O Arduino Uno não tem DAC e analogWrite() gera PWM; o ESP32 tem dois DACs de 8 bits nos GPIO 25 e 26, e o Uno R4 tem um DAC de 12 bits no A0.
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

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

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.

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.

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 de servo motor com potenciômetro
Conforme você gira o botão do potenciômetro, o braço do servo motor gira junto: uma extremidade do botão corresponde a zero grau, e a outra, a meia volta. O Arduino lê continuamente a posição do botão

Controle de LEDs com joystick
Empurre a alavanca do joystick até o fim em qualquer direção e o LED correspondente acende: são quatro cores diferentes para direita, esquerda, cima e baixo. Ao soltar a alavanca, ela volta ao centro

Luminária com mistura de cores e ESP32 (3 potenciômetros + LED RGB + OLED)
Uma luminária inteligente que permite misturar a cor que você quiser girando três potenciômetros com o ESP32! Ao girar os potenciômetros de vermelho, verde e azul, o LED RGB de cátodo comum muda de cor em tempo real. O display OLED SSD1306 mostra os valores de cada cor na faixa de 0–255, barras de preenchimento e o código HEX da cor para a web, como #FF8040.
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

