Fonte: O Autor

O conversor analógico-digital (ADC) do ESP32 é um dos periféricos mais utilizados em projetos de Internet das Coisas e sistemas embarcados. Seja para ler sensores de temperatura, umidade, luminosidade ou qualquer outro sensor analógico, o ADC é essencial. No entanto, existe um passo fundamental que muitos desenvolvedores acabam ignorando: a calibração do ADC. Neste artigo, vou explicar por que a calibração é tão importante, como ela funciona e como implementá-la tanto no framework Arduino quanto no ESP-IDF.

Durante meus anos trabalhando com ESP32, percebi que a falta de calibração do ADC é uma das principais causas de leituras imprecisas e inconsistentes em projetos. Muitos desenvolvedores ficam frustrados ao perceber que as medições variam significativamente entre diferentes placas ou que os valores lidos não correspondem à realidade. A boa notícia é que a solução para esse problema é relativamente simples: calibrar o ADC corretamente.

Por Que Calibrar o ADC?

O ADC do ESP32 foi projetado para usar uma tensão de referência de 1100 mV. No entanto, devido a variações no processo de fabricação, a tensão de referência real pode variar entre 1000 mV e 1200 mV em diferentes chips. Isso significa que dois chips ESP32 aparentemente idênticos podem produzir leituras diferentes para a mesma tensão de entrada.

Além disso, o ADC do ESP32 apresenta problemas de não-linearidade, especialmente quando se utiliza atenuação de 11 dB e tensões acima de 2,6V. Segundo dados da própria Espressif Systems, os chips ESP32 podem apresentar uma diferença de ±6% de um chip para outro nas medições. Essa variação pode ser crítica em aplicações que exigem precisão, como sistemas de monitoramento de bateria, medição de consumo de energia ou leitura de sensores analógicos calibrados.

A calibração do ADC minimiza esses efeitos ao ajustar as leituras com base em parâmetros armazenados na eFuse de cada chip durante a fabricação. Esses parâmetros contêm informações sobre a tensão de referência real e características de linearidade específicas daquele chip, permitindo que o driver de calibração compense as variações e forneça resultados mais precisos.

Como Funciona a Calibração do ADC

A Espressif Systems fornece drivers de calibração que implementam diferentes esquemas para corrigir as leituras do ADC. O esquema mais comum no ESP32 original é o Line Fitting (ajuste de linha), que utiliza parâmetros armazenados na eFuse para calcular uma função de correção linear.

Clique aqui para ver a documentação oficial da Espressif sobre o driver de calibração do ADC.

Valores Armazenados na eFuse

Durante a fabricação, cada chip ESP32 passa por um processo de caracterização onde parâmetros específicos são medidos e gravados na eFuse. Esses parâmetros incluem:

  • Tensão de referência real do ADC (que pode variar entre 1000-1200 mV)
  • Coeficientes de calibração para diferentes níveis de atenuação
  • Parâmetros de linearidade para compensar a não-linearidade do ADC

O driver de calibração lê esses valores da eFuse e os utiliza para criar uma função de conversão que transforma o valor bruto (raw) do ADC em uma tensão calibrada em milivolts.

Esquemas de Calibração

O ESP32 suporta principalmente o esquema Line Fitting, que cria uma função de ajuste linear baseada nos parâmetros da eFuse. Esse esquema é suficiente para a maioria das aplicações e oferece um bom equilíbrio entre precisão e simplicidade.

Já em chips mais recentes como o ESP32-S3 e ESP32-C3, a Espressif introduziu o esquema Curve Fitting (ajuste de curva), que oferece melhor compensação para a não-linearidade do ADC, especialmente em faixas de tensão mais amplas.

Se você quiser ver mais detalhes sobre os chips ESP32, consulte o ESPDocs, uma documentação não oficial do ESP32, de um desenvolvedor para desenvolvedores.

Implementando a Calibração no Framework Arduino

O framework Arduino para ESP32 facilita a implementação da calibração do ADC através de funções específicas da biblioteca esp_adc_cal.h . Vou mostrar um exemplo prático baseado em um projeto real de monitoramento de sensores.

Configuração Inicial

Primeiro, é necessário incluir as bibliotecas apropriadas e definir as constantes de configuração do ADC:

#include <esp_adc_cal.h>
#include <driver/adc.h>

// Definições do ADC
#define ADC_V_REF           1100
#define ADC_UNIT            ADC_UNIT_1
#define ADC_ATTENUATION     ADC_ATTEN_DB_12
#define ADC_WIDTH           ADC_WIDTH_BIT_12

Essas definições especificam:

  • ADC_V_REF: Tensão de referência nominal (1100 mV)
  • ADC_UNIT: Qual unidade ADC será utilizada (ADC1 ou ADC2)
  • ADC_ATTENUATION: Nível de atenuação (11 dB permite leituras até ~3,3V)
  • ADC_WIDTH: Resolução do ADC (12 bits = valores de 0 a 4095)

Criando as Características de Calibração

O próximo passo é criar a estrutura que armazenará as características de calibração e chamar a função que realiza a caracterização:

// Variável global para armazenar as características de calibração
esp_adc_cal_characteristics_t adc1_characteristics;

// Realizar a caracterização do ADC
esp_adc_cal_value_t adc1_value_type = esp_adc_cal_characterize(
    ADC_UNIT, 
    ADC_ATTENUATION, 
    ADC_WIDTH, 
    ADC_V_REF, 
    &adc1_characteristics
);

A função esp_adc_cal_characterize() lê os valores da eFuse e cria as características de calibração. O valor de retorno indica qual tipo de calibração foi utilizado:

  • ESP_ADC_CAL_VAL_EFUSE_TP: Calibração baseada em Two Point da eFuse (mais precisa)
  • ESP_ADC_CAL_VAL_EFUSE_VREF: Calibração baseada apenas na tensão de referência da eFuse
  • ESP_ADC_CAL_VAL_DEFAULT_VREF: Calibração usando o valor padrão (menos precisa)

Função de Leitura Calibrada

Com as características de calibração criadas, podemos implementar uma função que lê um canal do ADC e retorna o valor já calibrado em milivolts:

uint16_t readChannel(adc1_channel_t channel) {
    // Realizar múltiplas leituras para reduzir ruído
    uint32_t adc_reading = 0;
    for(int i = 0; i < 64; i++) {
        adc_reading += adc1_get_raw(channel);
    }
    adc_reading /= 64;
    
    // Converter valor bruto para tensão calibrada
    return esp_adc_cal_raw_to_voltage(adc_reading, &adc1_characteristics);
}

Exemplo Completo no Arduino

Aqui está um exemplo completo de como usar a calibração do ADC no Arduino para ler um sensor de umidade:

#include <esp_adc_cal.h>
#include <driver/adc.h>
#include <Arduino.h>

#define HUMIDITY_CHANNEL    ADC1_CHANNEL_0
#define ADC_V_REF           1100
#define ADC_UNIT            ADC_UNIT_1
#define ADC_ATTENUATION     ADC_ATTEN_DB_12
#define ADC_WIDTH           ADC_WIDTH_BIT_12

esp_adc_cal_characteristics_t adc1_characteristics;

void setup() {
    Serial.begin(115200);
    
    // Caracterizar o ADC
    esp_adc_cal_value_t adc1_value_type = esp_adc_cal_characterize(
        ADC_UNIT, 
        ADC_ATTENUATION, 
        ADC_WIDTH, 
        ADC_V_REF, 
        &adc1_characteristics
    );
    
    // Verificar tipo de calibração utilizado
    if (adc1_value_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        Serial.println("Calibração: Two Point eFuse");
    } else if (adc1_value_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        Serial.println("Calibração: eFuse Vref");
    } else {
        Serial.println("Calibração: Valor padrão");
    }
}

void loop() {
    uint16_t humidity_voltage = readChannel(HUMIDITY_CHANNEL);
    Serial.printf("Tensão do sensor: %d mV\n", humidity_voltage);
    delay(1000);
}

uint16_t readChannel(adc1_channel_t channel) {
    uint32_t adc_reading = 0;
    for(int i = 0; i < 64; i++) {
        adc_reading += adc1_get_raw(channel);
    }
    adc_reading /= 64;
    return esp_adc_cal_raw_to_voltage(adc_reading, &adc1_characteristics);
}

Implementando a Calibração no ESP-IDF

O ESP-IDF oferece uma API mais moderna e robusta para calibração do ADC, especialmente em chips mais recentes. Vou mostrar como implementar a calibração usando o esquema Curve Fitting, que é recomendado para ESP32-S3, ESP32-C3 e modelos mais novos.

Estrutura do Projeto

Para organizar melhor o código, vou dividir a implementação em dois arquivos: um header ( adc.h ) e um arquivo de implementação ( adc.c ).

Arquivo adc.h:

#pragma once

#include <esp_adc/adc_cali_scheme.h>
#include <esp_adc/adc_cali.h>
#include <driver/gpio.h>
#include <driver/adc.h>

// Definições do ADC
#define ADC_UNIT                    ADC_UNIT_1
#define ADC_ATTENUATION             ADC_ATTEN_DB_12
#define ADC_BITWIDTH                ADC_BITWIDTH_12
#define ADC_DEFAULT_VREF            1100

// Canais de exemplo
#define SENSOR_CHANNEL              ADC1_CHANNEL_0
#define SENSOR_PIN                  GPIO_NUM_1

// Variáveis globais
extern adc_cali_handle_t calibration_handle;
extern adc_cali_curve_fitting_config_t calibration_config;

// Protótipos de funções
void calibrateADC();
uint16_t getSample(adc1_channel_t channel);

Arquivo adc.c:

#include "main.h"

// Configuração da calibração
adc_cali_handle_t calibration_handle;
adc_cali_curve_fitting_config_t calibration_config = {
    .unit_id = ADC_UNIT,
    .atten = ADC_ATTENUATION,
    .bitwidth = ADC_BITWIDTH,
};

void calibrateADC() {
    // Configurar pinos como entrada
    gpio_set_direction(SENSOR_PIN, GPIO_MODE_INPUT);
    
    // Configurar largura de bits do ADC
    adc1_config_width(ADC_WIDTH_BIT_12);
    
    // Configurar atenuação do canal
    adc1_config_channel_atten(SENSOR_CHANNEL, ADC_ATTENUATION);
    
    // Criar o esquema de calibração Curve Fitting
    adc_cali_create_scheme_curve_fitting(&calibration_config, &calibration_handle);
}

uint16_t getSample(adc1_channel_t channel) {
    int sample = 0;
    
    // Ler valor bruto do ADC
    int raw_value = adc1_get_raw(channel);
    
    // Converter para tensão calibrada
    adc_cali_raw_to_voltage(calibration_handle, raw_value, &sample);
    
    return (uint16_t) sample;
}

Diferenças Entre Line Fitting e Curve Fitting

O esquema Curve Fitting utilizado no exemplo acima oferece melhor compensação para a não-linearidade do ADC em comparação com o Line Fitting. Ele é especialmente útil quando se trabalha com a faixa completa de tensão (0-3,3V) usando atenuação de 11 dB.

Para chips ESP32 originais que não suportam Curve Fitting, você pode usar o Line Fitting substituindo:

adc_cali_line_fitting_config_t calibration_config = {
    .unit_id = ADC_UNIT,
    .atten = ADC_ATTENUATION,
    .bitwidth = ADC_BITWIDTH,
    .default_vref = ADC_DEFAULT_VREF,
};

adc_cali_create_scheme_line_fitting(&calibration_config, &calibration_handle);

Verificando o Esquema Suportado

Você pode verificar qual esquema de calibração é suportado pelo seu chip antes de criar o handle:

bool line_fitting_supported = false;
bool curve_fitting_supported = false;

esp_err_t ret = adc_cali_check_scheme(&line_fitting_supported, &curve_fitting_supported);

if (ret == ESP_OK) {
    if (curve_fitting_supported) {
        // Usar Curve Fitting
        adc_cali_create_scheme_curve_fitting(&calibration_config, &calibration_handle);
    } else if (line_fitting_supported) {
        // Usar Line Fitting
        adc_cali_create_scheme_line_fitting(&calibration_config, &calibration_handle);
    }
}

Exemplo Completo no ESP-IDF

Aqui está um exemplo completo de aplicação que utiliza a calibração do ADC no ESP-IDF:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "adc.h"

void app_main(void) {
    // Inicializar calibração do ADC
    calibrateADC();
    printf("ADC calibrado com sucesso!\n");
    
    while(1) {
        // Ler sensor
        uint16_t voltage = getSample(SENSOR_CHANNEL);
        printf("Tensão lida: %d mV\n", voltage);
        
        // Aguardar 1 segundo
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Boas Práticas na Calibração do ADC

Ao trabalhar com o ADC do ESP32, algumas práticas podem melhorar significativamente a qualidade das medições:

1. Use Oversampling

Como mostrado nos exemplos, realizar múltiplas leituras e calcular a média reduz drasticamente o ruído. O número ideal de amostras depende da aplicação, mas valores entre 32 e 128 são comuns.

2. Adicione Capacitores de Bypass

O ADC do ESP32 é muito sensível a ruído. Adicionar um capacitor cerâmico de 100 nF entre o pino do ADC e o GND pode melhorar significativamente a estabilidade das leituras.

3. Escolha a Atenuação Adequada

O ESP32 oferece diferentes níveis de atenuação que determinam a faixa de tensão que pode ser medida:

AtenuaçãoFaixa de TensãoLinearidade
0 dB0 – 1,1VBoa
2,5 dB0 – 1,5VBoa
6 dB0 – 2,2VRazoável
11 dB0 – 3,3VRuim acima de 2,6V
Fonte: O Autor

Se possível, escolha uma atenuação menor que cubra sua faixa de medição, pois isso resultará em melhor linearidade.

4. Evite o ADC2 com Wi-Fi Ativo

O ADC2 não pode ser usado quando o Wi-Fi está ativo no ESP32. Se seu projeto utiliza Wi-Fi, sempre use canais do ADC1.

5. Verifique o Tipo de Calibração

Sempre verifique qual tipo de calibração foi utilizado (eFuse Two Point, eFuse Vref ou valor padrão). Isso ajuda a entender a precisão esperada das medições.

Impacto da Calibração na Precisão

Para ilustrar o impacto da calibração, considere um exemplo prático: medição de tensão de bateria. Sem calibração, dois chips ESP32 diferentes podem apresentar leituras com diferença de até 200 mV para a mesma tensão de entrada. Com calibração adequada, essa diferença pode ser reduzida para menos de 20 mV, uma melhoria de 10x na precisão.

Essa diferença é crítica em aplicações como:

  • Monitoramento de bateria: Onde pequenas variações afetam o cálculo de carga restante
  • Sensores analógicos calibrados: Onde a precisão é fundamental para medições corretas
  • Sistemas de medição de energia: Onde erros de leitura impactam diretamente os cálculos de consumo

Conclusão

A calibração do ADC é um passo fundamental que não deve ser ignorado em projetos com ESP32. Embora adicione algumas linhas de código, o ganho em precisão e consistência das medições é significativo. A diferença entre um projeto que funciona “mais ou menos” e um que funciona de forma confiável muitas vezes está justamente nesse detalhe.

Tanto o framework Arduino quanto o ESP-IDF oferecem APIs simples e eficientes para implementar a calibração. Não há desculpa para não utilizá-las. Se você está começando um novo projeto ou revisando um existente, reserve alguns minutos para implementar a calibração corretamente. Seus sensores (e seus usuários) agradecerão.

Para citar esse artigo:

GUERRA DA SILVA, L. R. Como Calibrar o ADC do ESP32 da Forma Correta. Ciência Embarcada. Recife. 08 nov. 2025. Disponível em: https://cienciaembarcada.com.br/publicacoes/como-calibrar-o-adc-do-esp32-da-forma-correta/. Acesso em: 19 nov. 2025.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Lucas Guerra

Autista e entusiasta do mundo da tecnologia. Criei esse blog para poder compartilhar conhecimentos e experiências de forma acessível, traduzindo esse infinidades de termos da tecnologia. Eu trabalho com o desenvolvimento de dispositivos IoT e Sistemas Web, indo do desenho de PCBs até a interface com o usuário, e sempre com foco em segurança e inovação.