Analog sensörler (potansiyometreler, NTC sıcaklık probları, LDR ışık sensörleri veya pil voltaj bölücüleri) mikrodenetleyicilerde analog-dijital dönüştürücü (ADC) birimleri üzerinden okunur. Ancak ESP32’nin yerleşik SAR ADC birimi, 0V ve 3.3V uçlarında doğal bir lineersizliğe (doğrusal olmama) ve çip üretim farklılıklarından kaynaklanan referans gerilimi sapmalarına sahiptir. Bu nedenle endüstriyel doğrulukta gerilim ölçümü için ESP-IDF ADC kalibrasyon mekanizmasını (espadccal) ve zayıflatma (attenuation) yapılandırmasını eksiksiz uygulamak şarttır.
Bu rehberde; ESP32 ADC donanımını (ADC1 vs ADC2 farkı), zayıflatma parametrelerini, eFuse üzerinde saklanan fabrika kalibrasyon verilerini okumayı ve ham ADC değerlerini milivolt (mV) seviyesinde hassas gerilime dönüştürmeyi öğreneceğiz.
ESP32 ADC Donanım Mimarisi
ESP32 üzerinde 12-bit çözünürlüğe sahip iki adet bağımsız ADC birimi bulunur:
- ADC1: 8 kanal içerir (
GPIO32–GPIO39). Wi-Fi açıkken güvenle kullanılabilir. - ADC2: 10 kanal içerir (
GPIO0,GPIO2,GPIO4,GPIO12–GPIO15,GPIO25–GPIO27). Wi-Fi veya Bluetooth çalıştığında ADC2 sürücüsü kilitlenir ve kullanılamaz! Bu sebeple projelerinizde daima ADC1 kanallarını tercih edin.
Zayıflatma (Attenuation) ve Ölçüm Aralıkları
Dahili referans gerilimi yaklaşık 1.1V’tur. Daha yüksek gerilimleri ölçebilmek için giriş sinyali donanımsal bir gerilim bölücüden (attenuator) geçirilir:
| Zayıflatma Seviyesi | Giriş Gerilimi Aralığı | Önerilen Kullanım |
|---|---|---|
ADCATTENDB_0 (0 dB) | 100 mV ~ 950 mV | Düşük sinyalli hassas sensörler |
ADCATTENDB25 (2.5 dB) | 100 mV ~ 1250 mV | ~1.2V referanslı sensörler |
ADCATTENDB_6 (6 dB) | 150 mV ~ 1750 mV | ~1.5V aralığı |
ADCATTENDB_11 (11 dB) / 12 | 150 mV ~ 3100 mV | 3.3V sistemler, potansiyometre ve pil ölçümü |
Donanımsal Kalibrasyon: eFuse ve İki Nokta (Two Point)
Espressif, fabrikada her çipin ADC referans gerilimini ölçerek çipin tek seferlik yazılabilir eFuse hafızasına kaydeder:
- Two Point Kalibrasyonu: En hassas yöntemdir (150mV ve 850mV referansları saklanır).
- eFuse Vref: Çipin dahili 1100mV referansının gerçek değeri (örn: 1092mV) saklanır.
- Varsayılan Vref: eFuse yazılmamış eski çiplerde varsayılan 1100mV baz alınır.
espadccal_characterize fonksiyonu eFuse kayıtlarını otomatik okuyarak ideal transfer eğrisini (Look-Up Table / Polinom) çıkarır.
Adım Adım ADC Okuma ve Kalibrasyon Kodu
Aşağıdaki örnekte GPIO34 (ADC1 Kanal 6) üzerinden analog gerilim okuyup milivolt olarak ekrana basıyoruz:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_log.h"
#define ADC_CHANNEL ADC1_CHANNEL_6 // GPIO34
#define ADC_ATTEN ADC_ATTEN_DB_11 // 0 - 3.1V aralığı
#define ADC_WIDTH ADC_WIDTH_BIT_12 // 12-bit (0 - 4095)
#define NO_OF_SAMPLES 64 // Gürültüyü azaltmak için multisampling
#define DEFAULT_VREF 1100 // eFuse yoksa varsayılan mV
static const char *TAG = "ADC_CAL";
static esp_adc_cal_characteristics_t adc_chars;
static void check_efuse(void) {
// eFuse kalibrasyon desteğini kontrol et
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_EFUSE_TP) == ESP_OK) {
ESP_LOGI(TAG, "eFuse Two Point kalibrasyonu mevcut.");
} else if (esp_adc_cal_check_efuse(ESP_ADC_CAL_EFUSE_VREF) == ESP_OK) {
ESP_LOGI(TAG, "eFuse Vref kalibrasyonu mevcut.");
} else {
ESP_LOGW(TAG, "eFuse kalibrasyonu bulunamadı! Varsayılan Vref kullanılacak.");
}
}
void app_main(void) {
check_efuse();
// 1. ADC Çözünürlük ve Kanal Zayıflatmasını Ayarla
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN));
// 2. Kalibrasyon Karakteristiğini Çıkar
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN, ADC_WIDTH, DEFAULT_VREF, &adc_chars);
ESP_LOGI(TAG, "ADC Başlatıldı. Ölçüm döngüsü başlıyor...");
while (1) {
uint32_t adc_reading = 0;
// 3. Çoklu Örnekleme (Multisampling / Ortalama Alma)
// Analog parazitleri süzmek için 64 okuma yapıp ortalamasını alıyoruz
for (int i = 0; i < NO_OF_SAMPLES; i++) {
adc_reading += adc1_get_raw(ADC_CHANNEL);
}
adc_reading /= NO_OF_SAMPLES;
// 4. Ham Değeri Kalibre Edilmiş Gerilime (mV) Çevir
uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(adc_reading, &adc_chars);
ESP_LOGI(TAG, "Ham ADC Değeri: %lu / 4095 | Gerilim: %lu mV (%.3f V)",
adc_reading, voltage_mv, (float)voltage_mv / 1000.0f);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
Donanımsal Doğruluğu Artırma Taktikleri
- Parazit Filtreleme Kondansatörü: ADC pini ile GND arasına 0.1µF (100nF) seramik kondansatör bağlamak, RF devrelerinden ve Wi-Fi anahtarlamasından kaynaklanan yüksek frekanslı gürültüyü filtreler.
- Uç Nokta Sınırları: ESP32 ADC’si 0V ile 100mV arasında ve 3.1V ile 3.3V arasında doyuma (saturation) ulaşır. Bu aralıklarda hassasiyet kaybolur. Eğer 0V’a çok yakın değerler okuyacaksanız sensör çıkışına harici bir OP-AMP (işlemsel kuvvetlendirici) ekleyin.
- Multisampling Sayısı: Kodumuzdaki
NOOFSAMPLES = 64değeri gürültü dalgalanmalarını neredeyse tamamen yok eder.
Özet
ESP32 projelerinizde analog ölçüm yaparken Wi-Fi ile çakışmaması için mutlaka ADC1 kanallarını seçin. espadccalcharacterize ve espadccalrawtovoltage fonksiyonları ile çipin donanımsal sapmalarını kompanse ederek fabrika kalitesinde mV hassasiyeti elde edebilirsiniz.