ADC Nedir? Analog Dijital Dönüşüm, Çözünürlük ve analogRead
ADC nedir, nasıl çalışır? Analog ve dijital sinyal farkı, 10 ve 12 bit çözünürlük, analogReference, volta çevirme formülü, ESP32 ADC2 ve gürültü azaltma.
ADC (Analog-Dijital Dönüştürücü), bir pine gelen ve sürekli değişebilen gerilimi mikrodenetleyicinin işleyebileceği bir sayıya çeviren devredir. Arduino'da analogRead() komutunu her çalıştırdığında arka planda bu dönüştürücü çalışır: Arduino Uno'nun 10 bitlik ADC'si 0–5 V arasındaki gerilimi 0 ile 1023 arasında bir sayıya, ESP32 ve Raspberry Pi Pico'nun 12 bitlik ADC'leri ise yaklaşık 0–3,3 V'u 0 ile 4095 arasında bir sayıya dönüştürür. Potansiyometre, LDR, toprak nem sensörü, joystick ve sıcaklık sensörü gibi analog çıkış veren her parçayı okuyabilmenin anahtarı ADC'dir.
Bu yazıda analog ve dijital sinyal arasındaki farkı, ADC'nin bir gerilimi adım adım nasıl sayıya çevirdiğini, çözünürlüğün ve referans geriliminin ölçümü nasıl etkilediğini öğreneceksin. Okunan değeri volta çeviren formülü, analogReference ile ölçüm aralığını değiştirmeyi, örnekleme hızını ve gürültüyü azaltmanın pratik yollarını gerçek sayılarla göreceğiz. ESP32'nin uçlarda doğrusal olmayan ADC'sini, Wi-Fi ile ADC2 çakışmasını ve attenuation (zayıflatma) ayarını, Raspberry Pi Pico'nun ADC'sini MicroPython ile kullanmayı da ele alacak, son olarak işin tersini yapan DAC'a kısa bir giriş yapacağız.

Analog ve dijital sinyal arasındaki fark nedir?
Analog sinyal, belirli bir aralıkta sonsuz sayıda değer alabilen ve zamanla kesintisiz değişen bir büyüklüktür. Bir potansiyometrenin orta bacağındaki gerilim 0 V'tan 5 V'a giderken 1,2 V, 1,21 V, 1,215 V gibi aradaki her değerden geçer; mikrofonun ürettiği ses dalgası, bir termistörün sıcaklıkla değişen gerilimi ya da pilin yavaşça düşen gerilimi de analogdur. Dijital sinyal ise yalnızca belirli seviyeleri tanır. Arduino'nun lojik dünyasında bu seviyeler iki tanedir: LOW (0) ve HIGH (1). Uno'da bir dijital giriş yaklaşık 1,5 V'un altını LOW, 3,0 V'un üstünü HIGH sayar; aradaki bölge tanımsızdır. digitalRead() bu yüzden bir pildeki 3,7 V ile 4,2 V arasındaki farkı göremez, ikisine de HIGH der. Dijital sinyalin gücü gürültüye dayanıklı olmasıdır: 4,6 V da 5,0 V da aynı HIGH anlamına gelir. Analog bir değeri ölçmek, saklamak ya da hesaplamaya sokmak için onu önce bir sayıya, yani dijital bir değere çevirmen gerekir; bu işi yapan parça ADC'dir.
ADC nedir, nasıl çalışır?
ADC'nin işi iki adımda özetlenebilir. İlki örneklemedir: dönüştürücü, ölçüm anında girişteki gerilimi küçük bir kondansatöre (örnekle-tut devresi) kopyalar ve dönüşüm bitene kadar sabit tutar; ATmega328P'de bu kondansatör yaklaşık 14 pF'tır. İkincisi nicemlemedir (kuantalama): tutulan gerilim, referans gerilimi eşit basamaklara bölen bir ölçekte en yakın basamağa yuvarlanır ve basamağın numarası sonuç olarak verilir. Arduino Uno, ESP32 ve Pico'daki ADC'lerin hepsi ardışık yaklaşım (SAR, Successive Approximation Register) tipindedir. SAR ADC bir sayı tahmin oyunu gibi çalışır: önce referansın yarısını dener, giriş bundan büyükse en yüksek biti 1 yapar, küçükse 0 bırakır; sonra kalan aralığın yarısını dener ve bunu her bit için tekrarlar. 10 bitlik bir ADC böylece yalnızca 10 karşılaştırmayla 1024 olasılık arasından doğru basamağı bulur. Aşağıdaki tabloda basitlik için 4 bitlik bir ADC'nin 5 V referansla 3,2 V'luk bir girişi nasıl ölçtüğünü görüyorsun:
| Adım | Denenen bit | Karşılaştırma gerilimi | Giriş (3,2 V) büyük mü? | Sonuç bitleri |
|---|---|---|---|---|
| 1 | Bit 3 (değeri 8) | 8 / 16 × 5 = 2,500 V | Evet → 1 | 1000 |
| 2 | Bit 2 (değeri 4) | 12 / 16 × 5 = 3,750 V | Hayır → 0 | 1000 |
| 3 | Bit 1 (değeri 2) | 10 / 16 × 5 = 3,125 V | Evet → 1 | 1010 |
| 4 | Bit 0 (değeri 1) | 11 / 16 × 5 = 3,4375 V | Hayır → 0 | 1010 |
| Sonuç | Tüm bitler bitti | 1010 = 10 → 10 × 5 / 16 = 3,125 V | Hata 0,075 V (bir basamak 0,3125 V) | 1010 |
Sonuçtaki 0,075 V'luk fark nicemleme hatasıdır ve hiçbir ADC bundan kaçamaz: gerçek gerilim iki basamağın arasındaysa ADC yalnızca basamaklardan birini söyleyebilir. Hata bir basamağın (LSB) altında kalır, bu yüzden basamak ne kadar küçükse ölçüm o kadar ince olur. Örnekle-tut kondansatörünün her ölçümde dolması gerektiği için ADC'yi besleyen kaynağın direnci de önemlidir: ATmega328P'nin veri sayfası kaynağın çıkış direncinin yaklaşık 10 kΩ ya da daha düşük olmasını önerir; daha yüksek dirençli bir gerilim bölücü kondansatörü zamanında dolduramaz ve okumalar kayar. Mikrodenetleyicilerdeki SAR tipinin dışında başka ADC türleri de vardır. Sigma-delta ADC'ler yavaş ama çok hassastır; tartı projelerinde kullanılan HX711 24 bit, I2C ile bağlanan ADS1115 modülü ise 16 bit çözünürlük sunar. Flash ADC'ler her basamak için ayrı bir karşılaştırıcı kullanır; çok hızlıdırlar ve osiloskoplarda bulunurlar.
ADC çözünürlüğü: 10 bit ve 12 bit ne demek?
Çözünürlük, ADC'nin ölçüm aralığını kaç basamağa böldüğünü söyler. N bitlik bir ADC 2^N basamak üretir: 10 bit 1024 basamak (0–1023), 12 bit 4096 basamak (0–4095), 16 bit ise 65.536 basamak demektir. Bir basamağın gerilim karşılığına LSB (en düşük anlamlı bit) denir ve LSB = Vref / 2^N formülüyle bulunur. Arduino Uno'da 5 V / 1024 = 4,88 mV, ESP32 ve Pico'da 3,3 V / 4096 = 0,81 mV olur. Yani Uno 4,88 mV'tan küçük değişimleri göremez; 10 mV/°C çıkış veren LM35 ile bu yaklaşık 0,5 °C'lik bir adım demektir. Ancak çözünürlük ile doğruluk aynı şey değildir. Bir ADC'nin gürültüsü, doğrusal olmayan davranışı ve referans hatası, kâğıt üzerindeki bitlerin bir kısmını işe yaramaz hale getirir. Bunu anlatan ölçüye etkin bit sayısı (ENOB) denir: Raspberry Pi Pico'daki RP2040'ın ADC'si 12 bitlik sonuç verir ama veri sayfasına göre etkin bit sayısı 8,7'dir. Üç kartın ADC özelliklerini yan yana koyalım:
| Özellik | Arduino Uno R3 | ESP32 (WROOM-32) | Raspberry Pi Pico |
|---|---|---|---|
| ADC çözünürlüğü | 10 bit (0–1023) | 12 bit (0–4095) | 12 bit (MicroPython'da 0–65535'e ölçeklenir) |
| Analog giriş | 6 (A0–A5; Nano'da A0–A7) | 18 kanal: ADC1'de 8, ADC2'de 10 | 3 pin (GP26–GP28) + VSYS/3 (GP29) + sıcaklık sensörü |
| Varsayılan ölçüm aralığı | 0–5 V | Yaklaşık 0–3,1 V (11 dB zayıflatma) | 0–3,3 V (ADC_VREF) |
| Bir basamak (LSB) | 4,88 mV | Yaklaşık 0,8 mV | 0,81 mV |
| Referans seçenekleri | DEFAULT (5 V), INTERNAL (1,1 V), EXTERNAL (AREF) | Zayıflatma: 0, 2,5, 6 ve 11 dB | ADC_VREF pinine harici referans |
| Örnekleme hızı | Yaklaşık 10.000 ölçüm/s | Sürekli (DMA) modda 20 kHz – 2 MHz | Donanımda 500.000 ölçüm/s |
| Doğruluk notu | Mutlak hata ±2 LSB | Uçlarda doğrusal değil, kalibrasyon gerekir | ENOB 8,7 bit, yaklaşık 30 mV ofset |
| Analog çıkış (DAC) | Yok (PWM kullanılır) | 2 kanal, 8 bit (GPIO 25 ve 26) | Yok (PWM kullanılır) |
Okunan ADC değerini volta çevirme formülü
ADC'nin verdiği sayı tek başına bir anlam taşımaz; onu gerilime çevirmek için referans gerilimini ve basamak sayısını kullanırsın: Gerilim = ADC değeri × Vref / 2^N. Arduino Uno'da bu V = değer × 5,0 / 1024 olur; analogRead() 512 döndürdüyse pindeki gerilim 512 × 5 / 1024 = 2,50 V'tur. Ters yönde, belirli bir gerilimin hangi sayıya karşılık geleceğini değer = V × 1024 / Vref ile bulursun: 3,3 V, Uno'da yaklaşık 675 olarak okunur. Birçok örnekte 1024 yerine 1023'e bölündüğünü görürsün. ATmega328P'nin veri sayfası ADC = Vin × 1024 / Vref formülünü verir; en büyük değer olan 1023, Vref'in bir basamak altını temsil eder. 1023'e bölmek en üst değeri tam 5,00 V gösterir ama bütün değerleri yaklaşık %0,1 kaydırır. Bu fark ADC'nin kendi ±2 LSB'lik hatasından küçüktür, yani ikisi de iş görür; önemli olan projede tutarlı olmaktır. Asıl büyük hata kaynağı Vref'in kendisidir: USB'den beslenen bir Uno'nun 5V pini çoğu zaman 4,7 ile 5,1 V arasındadır ve formüle 5,0 yazmak %5'e varan hata yaratır. Bu yüzden hassas ölçümlerde 5V pinini multimetreyle ölçüp gerçek değeri koda yaz. ESP8266'nın tek analog girişi (A0) de 10 bittir; yonganın kendisi 0–1 V ölçer, NodeMCU ve Wemos D1 Mini gibi kartlardaki dahili bölücü bu aralığı yaklaşık 0–3,2 V'a genişletir.
| Kart ve ayar | Okunan aralık | Volta çevirme | Örnek |
|---|---|---|---|
| Arduino Uno / Nano (DEFAULT, 5 V) | 0–1023 | V = değer × 5,0 / 1024 | 768 → 3,75 V |
| Uno, analogReference(INTERNAL) | 0–1023 | V = değer × 1,1 / 1024 | 512 → 0,55 V |
| ESP32 (11 dB) | 0–4095 | Kalibre: analogReadMilliVolts() / 1000; kaba: değer × 3,3 / 4095 | 1650 mV → 1,65 V |
| Raspberry Pi Pico (read_u16) | 0–65535 | V = değer × 3,3 / 65535 | 32768 → 1,65 V |
| ESP8266 NodeMCU / Wemos D1 Mini (A0) | 0–1023 | V = değer × 3,2 / 1024 | 512 → 1,60 V |
Potansiyometre bağlantısı: Arduino, ESP32 ve Pico
| Potansiyometre bacağı | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| Kenar bacak 1 | 5V | 3V3 | 3V3(OUT) (pin 36) |
| Orta bacak (sinyal) | A0 | GPIO 34 (ADC1_CH6) | GP26 / ADC0 (pin 31) |
| Kenar bacak 2 | GND | GND | AGND (pin 33) ya da GND |
| İsteğe bağlı gürültü kondansatörü | A0 ile GND arasına 100 nF | GPIO 34 ile GND arasına 100 nF | GP26 ile AGND arasına 100 nF |
Adım adım: Arduino ile ilk ADC okuması
- Devreyi kur: 10 kΩ'luk bir potansiyometrenin kenar bacaklarını 5V ve GND'ye, orta bacağını A0'a bağla.
- 5V pinini ölç: Multimetreyle 5V ile GND arasındaki gerilimi ölç ve koddaki VREF sabitine yaz (ör. 4.93).
- Kodu yükle: Aşağıdaki kodu Arduino IDE'de aç, kartı ve portu seçip yükle.
- Serial Monitor'ü aç: Hızı 9600 baud yap ve düğmeyi çevirdikçe ADC değerinin 0 ile 1023 arasında değiştiğini izle (ayrıntılar Serial Monitor rehberinde).
- Doğrula: Multimetreyle A0 ile GND arasını ölç ve ekrandaki gerilimle karşılaştır; fark 10–20 mV civarında kalmalı.
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() ölçümü yaklaşık 100 µs'de tamamlar ve 0–1023 arasında bir tam sayı döndürür. Kod bu sayıyı önce formülle volta, sonra map() ile yüzdeye çevirir. map() tam sayı aritmetiği kullandığı için kesirli kısmı atar; ondalıklı bir sonuç gerekiyorsa hesabı float ile kendin yap. Bu ölçüm oransal (ratiometric) bir ölçümdür: potansiyometre de ADC de aynı 5 V'tan beslendiği için besleme 4,9 V'a düşse bile düğmenin konumu, yani ADC değeri değişmez; değişen yalnızca hesaplanan gerilimdir. LDR ve NTC gibi bölücüyle okunan sensörlerde de durum aynıdır. Buna karşılık bir pilin gerilimini ya da LM35 gibi sabit mV çıkışlı bir sensörü ölçerken Vref'in gerçek değeri doğrudan sonuca yansır.
Referans gerilimi ve analogReference
Referans gerilimi (Vref), ADC ölçeğinin en üst noktasıdır: girişteki gerilim Vref'e eşitse ya da onu aşarsa sonuç en büyük değerde (1023) takılır. Vref'i küçültmek ölçüm aralığını daraltır ama her basamağı küçültür, yani küçük sinyalleri daha ince ölçersin. Arduino Uno'da referansı analogReference() fonksiyonuyla seçersin. INTERNAL seçeneğinde Vref 1,1 V olur ve bir basamak 1,07 mV'a iner; 10 mV/°C veren bir LM35'i yaklaşık 0,1 °C adımlarla okuyabilirsin, karşılığında 1,1 V'un, yani 110 °C'nin üstü ölçülemez. Dahili 1,1 V referansın kendisi yongadan yongaya 1,0 ile 1,2 V arasında değişebilir, bu yüzden hassas projelerde bir kez multimetreyle kalibre etmek gerekir. Referans değiştikten sonraki ilk birkaç okuma hatalı olabilir; Arduino'nun belgeleri de bunu belirtir, bu yüzden referansı değiştirdikten sonra birkaç okumayı atmak iyi bir alışkanlıktır. Ayrıca referans ayarı kartın bütün analog pinlerini birlikte etkiler. Seçenekler karta göre farklıdır:
| Seçenek | Referans | Kartlar | Ne zaman kullanılır? |
|---|---|---|---|
| DEFAULT | 5 V (3,3 V'luk kartlarda 3,3 V) | Uno, Nano, Mega, Leonardo | Potansiyometre, LDR, joystick gibi beslemeyle oransal sensörler |
| INTERNAL | 1,1 V (ATmega328P); Leonardo'da 2,56 V | Uno, Nano, Leonardo (Mega'da yok) | LM35 gibi küçük gerilimli sensörler |
| INTERNAL1V1 / INTERNAL2V56 | 1,1 V / 2,56 V | Yalnız Mega | Mega'da küçük sinyaller |
| EXTERNAL | AREF pinindeki gerilim (0–5 V) | Uno, Nano, Mega | Kendi hassas referansını (ör. 2,5 V ya da 4,096 V) kullanmak |
| AR_INTERNAL | Yaklaşık 1,43 V (yonganın iç referansı) | Uno R4 Minima ve WiFi | Uno R4'te küçük sinyaller |
Örnekleme hızı: ADC saniyede kaç ölçüm yapar?
Örnekleme hızı, ADC'nin bir saniyede kaç ölçüm alabildiğidir. Arduino Uno'da ADC saati 16 MHz'in 128'e bölünmesiyle 125 kHz'e ayarlanır ve bir dönüşüm 13 saat çevrimi sürer; analogRead() bu yüzden yaklaşık 100 µs alır ve saniyede en fazla 10.000 civarında ölçüm yapılabilir. Sıcaklık, ışık ya da pil gerilimi gibi yavaş değişen büyüklükler için bu fazlasıyla yeterlidir; saniyede 10 ölçüm bile çoğu zaman yeter. Hızlı sinyallerde ise Nyquist kuralı devreye girer: bir sinyali kaybetmeden yakalamak için en yüksek frekansının en az iki katı hızda örneklemen gerekir, pratikte 5–10 katı tercih edilir. 50 Hz'lik şebeke uğultusunu görmek için en az 100 ölçüm/s, 4 kHz'e kadar konuşma sesini kaydetmek için en az 8.000 ölçüm/s gerekir. Daha hızlı ölçüm gerekiyorsa Uno'da ADC'nin ön bölücüsünü küçültebilirsin: setup() içine ADCSRA = (ADCSRA & 0xF8) | 0x04; yazınca bölücü 16 olur, ADC saati 1 MHz'e çıkar ve analogRead() yaklaşık 16 µs'ye iner; bunun bedeli bir miktar doğruluk kaybıdır. ESP32'de tek tek analogRead() çağrıları saniyede on binlerce ölçüme izin verir, DMA kullanan sürekli modda (Arduino'da analogContinuous()) ise 20 kHz ile 2 MHz arasında bir hız seçilebilir; bu mod yalnızca ADC1 pinleriyle çalışır. Raspberry Pi Pico'nun ADC'si 48 MHz'lik ayrı bir saatle her ölçümü 96 çevrimde, yani 2 µs'de bitirir ve saniyede 500.000 ölçüme ulaşır; MicroPython'daki bir döngü bu hıza yetişemez, tam hız için C SDK ve DMA gerekir.
ESP32 ADC: doğrusal olmama, ADC2 ve Wi-Fi çakışması, attenuation
ESP32'nin 12 bitlik ADC'si kâğıt üzerinde Uno'dan dört kat ince ölçer, ama pratikte üç konuya dikkat etmen gerekir. Birincisi doğrusal olmama: ESP32'nin ADC'si 0 V'a yakın bölgede yaklaşık 100–150 mV'a kadar 0 okur, üst uçta ise giriş 3,3 V'a ulaşmadan 4095'e doyar; aradaki eğri de tam bir doğru değildir. İkincisi referans sapması: ESP32'nin iç referansı tasarımda 1100 mV'tur, ama Espressif'e göre yongadan yongaya 1000 ile 1200 mV arasında değişir; bu, kalibrasyonsuz okumada yaklaşık ±%9'luk bir hata demektir. Espressif bu yüzden yongalara üretimde kalibrasyon verisi (eFuse) yazar. Arduino'daki analogReadMilliVolts() fonksiyonu bu veriyi kullanarak ham değeri doğrudan kalibre edilmiş milivolta çevirir ve çoğu durumda analogRead() × 3,3 / 4095 hesabından çok daha doğru sonuç verir. Üçüncüsü zayıflatma (attenuation): ADC'nin çekirdeği yaklaşık 1 V'a kadar ölçebilir; daha yüksek gerilimler girişteki ayarlanabilir bir zayıflatıcıyla küçültülür. Arduino'da varsayılan ayar 11 dB'dir ve yaklaşık 3,1 V'a kadar okumaya izin verir, ama Espressif'in bu ayar için önerdiği doğru ölçüm aralığı 150–2450 mV'tur. Küçük sinyallerde zayıflatmayı düşürmek hem doğruluğu hem de çözünürlüğü artırır:
| Zayıflatma | Arduino sabiti | Doğru ölçüm aralığı | Kullanım |
|---|---|---|---|
| 0 dB | ADC_0db | 100–950 mV | Küçük sinyaller, en ince ölçüm |
| 2,5 dB | ADC_2_5db | 100–1250 mV | 1 V civarındaki sensör çıkışları |
| 6 dB | ADC_6db | 150–1750 mV | Orta seviye sinyaller |
| 11 dB (varsayılan) | ADC_11db | 150–2450 mV (okuma yaklaşık 3,1 V'a kadar sürer) | Potansiyometre ve 0–3,3 V sensörler |
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}Kod iki sonucu yan yana gösterir: ham değeri basit formülle çeviren hesap ve analogReadMilliVolts()'un kalibre ettiği değer. Potansiyometreyi uçlara doğru çevirdikçe aradaki farkın büyüdüğünü, en altta formülün 0,000 V gösterdiği yerde multimetrenin hâlâ 0,1 V civarı ölçtüğünü fark edeceksin. analogSetPinAttenuation() zayıflatmayı yalnız bir pin için, analogSetAttenuation() ise bütün pinler için değiştirir. ESP32'de gürültü Uno'dan belirgin şekilde fazladır, özellikle Wi-Fi yayın yaparken; Espressif'in önerisi de girişe 100 nF'lık bir kondansatör eklemek ve birden çok örneğin ortalamasını almaktır, koddaki 16 ölçümlük ortalama bunu yapar. ESP32-S3 ve ESP32-C3 gibi daha yeni yongalarda kalibrasyon daha gelişmiş bir eğri uydurma yöntemiyle yapılır, ama pin numaraları ve ADC2 kuralları modele göre değiştiği için kartının pin haritasına mutlaka bak (Pinout aracı). 3,3 V'tan yüksek gerilimleri ölçmek için bölücü kurmayı gerilim bölücü yazısında anlatıyoruz.
Raspberry Pi Pico ile ADC (MicroPython)
Raspberry Pi Pico'da dışarıdan kullanılabilen üç analog giriş vardır: GP26 (ADC0), GP27 (ADC1) ve GP28 (ADC2). GP29 (ADC3) kart üzerinde VSYS besleme geriliminin üçte birini ölçer, ADC4 ise yonganın içindeki sıcaklık sensörüne bağlıdır. MicroPython'daki read_u16() fonksiyonu 12 bitlik sonucu 0–65535 aralığına ölçekler; böylece aynı kod farklı kartlarda çalışır, ama gerçek çözünürlük yine 4096 basamaktır. RP2040'ın ayrı bir referans gerilimi yoktur, kendi ADC beslemesini referans alır. Pico'da bu besleme (ADC_VREF, pin 35), 3,3 V'luk anahtarlamalı regülatörün (SMPS) çıkışı yaklaşık 200 Ω'luk bir dirençle süzülerek elde edilir. Raspberry Pi'nin kart belgesi bunun üç sonucunu açıkça yazar: 3,3 V'un doğruluğu sınırlıdır, besleme biraz gürültülüdür ve ADC'nin çektiği akım yüzünden yaklaşık 30 mV'luk bir ofset oluşur. Çözümler de aynı belgededir: GP23'ü HIGH yaparak regülatörü daha az dalgalanan PWM moduna almak, kullanılmayan bir ADC kanalını AGND'ye bağlayıp okuduğun değeri ofset olarak çıkarmak ve çok daha iyi doğruluk için ADC_VREF ile AGND arasına LM4040 gibi 3,0 V'luk bir referans bağlamak (bu durumda ölçüm aralığı 0–3,0 V olur). Ayrıca RP2040'ın ADC'sinde 512, 1536, 2560 ve 3584 değerlerinde küçük sıçramalar (DNL hatası) olduğu bilinir; birden çok ölçümün ortalamasını almak bunların etkisini azaltır. Pico W'de GP23 kablosuz yongaya ayrıldığı için regülatör modu WL_GPIO1 üzerinden kontrol edilir; aşağıdaki kodda GP23 satırlarını Pico W'de sil.
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)ADC gürültüsünü azaltma yöntemleri
Sabit bir gerilimi ölçerken bile ADC değerinin bir iki basamak oynaması normaldir; nicemleme, besleme hattındaki dalgalanma, uzun kabloların topladığı parazit ve yakındaki motor ya da Wi-Fi yayınları buna katkı yapar. Uno'da ±1–2 basamaklık oynama sağlıklı sayılır; çok daha fazlası genellikle devrede bir sorun olduğunu gösterir. Gürültüyle hem donanımda hem yazılımda mücadele edebilirsin:
- Kondansatör ekle: Analog pin ile GND arasına konan 100 nF'lık seramik kondansatör hızlı parazitleri süzer ve yüksek dirençli kaynaklarda örnekle-tut kondansatörüne hazır yük sağlar.
- Kabloları kısa tut: Sensör kablosu uzunsa sinyal ve GND kablolarını birbirine sar; motor ve röle kablolarını analog hatlardan uzak geçir.
- Topraklamayı düzgün yap: Motor, röle ve LED şeridi gibi yüksek akım çeken yüklerin dönüş akımı sensörün GND kablosundan geçmesin; toprakları tek bir noktada birleştir (yıldız topraklama).
- Temiz bir referans kullan: USB beslemesi gürültülüdür; mutlak gerilim ölçümlerinde dahili referans ya da harici bir referans entegresi daha kararlı sonuç verir.
- Kanal değiştirince ilk okumayı at: ADC'nin girişindeki çoklayıcı (multiplexer) bir önceki kanalın yükünü taşıyabilir; birden çok pini sırayla okurken her pinde bir okumayı boşa harca.
- Ortalama al: N ölçümün ortalaması rastgele gürültüyü yaklaşık √N kat azaltır; 16 ölçüm gürültüyü dörtte birine indirir.
- Aşırı örnekleme (oversampling): 4^n ölçümü toplayıp sonucu n bit sağa kaydırırsan n bit fazladan çözünürlük kazanırsın; 16 ölçümün toplamını 2 bit kaydırmak Uno'nun 10 bitini 12 bite çıkarır. Bunun işe yaraması için sinyalde en az bir basamaklık doğal gürültü bulunmalıdır.
- Medyan ve üstel ortalama filtresi: Medyan filtresi motor kaynaklı ani sıçramaları atar, üstel hareketli ortalama (EMA) ise çok az bellekle yumuşak bir eğri verir.
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}Kodu yükleyip Arduino IDE'deki Serial Plotter'ı açtığında üç çizgi görürsün: ham değer titrer, 16 ölçümün ortalaması belirgin şekilde sakinleşir, EMA ise en yumuşak ama değişime biraz geç tepki veren eğridir. ALPHA katsayısı 0 ile 1 arasında seçilir: 0,1 her yeni ölçümün sonuca %10 oranında katıldığı, kabaca son 10 ölçümün etkili olduğu bir filtre demektir; değeri büyütürsen tepki hızlanır ama gürültü artar. Hangi filtreyi seçeceğin sinyale bağlıdır; yavaş değişen bir sıcaklık için güçlü bir EMA, hızlı tepki gereken bir joystick için kısa bir ortalama daha uygundur. Hareketli ortalama, medyan filtre ve histerezisi gerçek sensör örnekleriyle sensör verisi filtreleme yazısında karşılaştırıyoruz.
DAC'a kısa giriş: dijitalden analoğa dönüşüm
DAC (Dijital-Analog Dönüştürücü) ADC'nin tersini yapar: bir sayıyı alır ve onunla orantılı bir gerilim üretir. 8 bitlik bir DAC'a 0 yazarsan 0 V, 255 yazarsan besleme gerilimine yakın bir değer, 128 yazarsan bunun yaklaşık yarısını elde edersin. En basit DAC'lar R-2R adı verilen bir direnç merdiveniyle yapılır. Burada sık karıştırılan bir noktayı netleştirelim: Arduino Uno'daki analogWrite() bir DAC değildir, PWM üretir; pin aslında 0 V ile 5 V arasında hızla açılıp kapanır. LED parlaklığı ve motor hızı için bu yeterlidir, ama gerçekten sabit bir gerilim gerekiyorsa PWM çıkışına bir RC alçak geçiren filtre eklemen gerekir; filtrenin zaman sabitini RC zaman sabiti aracıyla hesaplayabilirsin. Gerçek DAC'ı olan kartlara gelince: ESP32'de GPIO 25 ve GPIO 26'da iki adet 8 bitlik DAC vardır ve dacWrite(pin, değer) ile kullanılır; ESP32-S3 ve ESP32-C3'te ise DAC yoktur. Arduino Uno R4'ün A0 pininde 12 bitlik bir DAC bulunur. Uno R3, Nano ve Pico için en kolay yol I2C ile bağlanan 12 bitlik MCP4725 modülüdür. DAC ile ses üretebilir, sinüs ya da üçgen dalga çıkarabilir, hatta DAC çıkışını bir ADC girişine bağlayıp ADC'yi bilinen gerilimlerle test edebilirsin:
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}ADC ile proje fikirleri
- Dijital voltmetre: Gerilim bölücüyle 0–25 V arasını ölçüp sonucu LCD'de göster; adımlar Arduino voltmetre yapımı yazısında.
- Otomatik gece lambası: LDR'nin gerilimini oku, ortam kararınca LED'leri yak.
- Akıllı saksı: Toprak nem sensörünün analog çıkışıyla toprak kuruyunca pompayı çalıştır.
- Joystick kontrollü robot: Joystick'in iki ekseni iki ayrı analog giriştir; değerleri motor hızına ve yönüne çevir.
- Akım ölçer: ACS712'nin akımla orantılı gerilimini okuyarak bir cihazın ne kadar akım çektiğini gör.
- Ses seviyesi göstergesi: KY-038 ses sensörünün analog çıkışını hızlı örnekle, tepe değerine göre bir LED çubuğu yak.
- Pil göstergesi: Pilli bir projede gerilimi ölç ve kalan şarjı yüzde olarak ekranda göster.
Sık yapılan hatalar ve çözümleri
| Belirti | Olası sebep | Çözüm |
|---|---|---|
| Hiçbir şey bağlı değilken değer rastgele oynuyor | Pin boşta (floating) | Sensörü bağla; kullanmadığın pinleri okuma ya da GND'ye çek |
| Değer 1023'te (ESP32'de 4095'te) takılı kalıyor | Giriş referansın üstünde ya da INTERNAL seçili | Referansı ya da zayıflatmayı ayarla, yüksek gerilimi bölücüyle indir |
| ESP32'de Wi-Fi açılınca analogRead() 0 dönüyor | Sensör bir ADC2 pinine bağlı | GPIO 32–39 arasındaki ADC1 pinlerini kullan |
| ESP32 küçük gerilimlerde 0, büyüklerde 4095 gösteriyor | ADC uçlarda doğrusal değil | analogReadMilliVolts() kullan, sinyali 150–2450 mV aralığında tut |
| Hesaplanan gerilim multimetreden %3–5 farklı | Vref 5,00 V değil (USB beslemesi) | 5V pinini ölçüp VREF'e yaz ya da kalibrasyon katsayısı ekle |
| İki pini sırayla okurken değerler birbirini etkiliyor | Çoklayıcı ve yüksek kaynak direnci | Kanal değişince ilk okumayı at, kaynağı 10 kΩ'un altında tut, 100 nF ekle |
| Motor ya da röle çalışınca değerler zıplıyor | Ortak GND hattında gürültü, besleme çöküyor | Yüklerin GND'sini ayrı hattan getir, kondansatör ve medyan filtre kullan |
| AREF'e gerilim verdikten sonra okumalar bozuldu | analogReference(EXTERNAL) çağrılmadan AREF kullanıldı | Önce EXTERNAL seç ya da AREF'e 5 kΩ'luk dirençle bağlan |
| INTERNAL seçtikten sonra potansiyometre yarıda 1023 oluyor | 1,1 V referans bütün analog pinleri etkiler | Oransal sensörleri okumadan önce DEFAULT'a dön ve birkaç okumayı at |
| Pico'da giriş GND'deyken bile 0'dan büyük değer okunuyor | ADC ofseti ve ADC_VREF gürültüsü | Bir kanalı AGND'ye bağlayıp ofseti ölç ve çıkar, GP23'ü HIGH yap |
ADC, fiziksel dünya ile kodun arasındaki köprüdür: çözünürlüğü, referans gerilimini ve örnekleme hızını bildiğinde ekranda gördüğün her sayının neyi temsil ettiğini ve ne kadar güvenilir olduğunu da bilirsin. Uno'da referansı doğru ölç, ESP32'de ADC1 pinlerini ve analogReadMilliVolts()'u kullan, Pico'da ofseti ve gürültüyü hesaba kat; sonra ortalama ve filtrelerle sonucu sakinleştir. BlueGrays uygulamasında LDR ile ışık şiddeti okuma, LCD ekranlı dijital voltmetre, NTC ile sıcaklık ölçümü, potansiyometreyle servo ve LED parlaklığı kontrolü gibi analog okumaya dayanan projeleri devre şemaları ve kodlarıyla adım adım bulabilirsin.
Sıkça sorulan sorular
ADC nedir ve ne işe yarar?
ADC (Analog-Dijital Dönüştürücü), bir pindeki gerilimi mikrodenetleyicinin işleyebileceği bir sayıya çeviren devredir. Potansiyometre, LDR, sıcaklık ve nem sensörleri gibi analog çıkış veren parçaları okumak için kullanılır. Arduino'da analogRead() komutu bu dönüştürücüyü çalıştırır.
Analog ve dijital sinyal arasındaki fark nedir?
Analog sinyal bir aralıktaki her değeri alabilir ve kesintisiz değişir; dijital sinyal ise yalnızca belirli seviyelerden, Arduino'da LOW ve HIGH'tan oluşur. digitalRead() bir pinin yalnızca 0 mı 1 mi olduğunu söyler, analogRead() ise gerilimin ne kadar olduğunu bir sayıyla verir.
Arduino analogRead neden 0 ile 1023 arasında değer verir?
Arduino Uno'nun ADC'si 10 bittir ve 2^10 = 1024 farklı basamak üretir; bu basamaklar 0'dan 1023'e numaralandırılır. 0 değeri 0 V'u, 1023 ise referans geriliminin (genellikle 5 V) bir basamak altını temsil eder. ESP32 ve Pico'nun 12 bitlik ADC'leri ise 0–4095 arası değer verir.
ADC değeri volta nasıl çevrilir?
Gerilim = ADC değeri × referans gerilimi / basamak sayısı formülünü kullan. Arduino Uno'da V = değer × 5,0 / 1024 olur; ESP32'de analogReadMilliVolts() doğrudan kalibre edilmiş milivolt verir. Pico'da MicroPython'un read_u16() değeri için V = değer × 3,3 / 65535 kullanılır.
ESP32 ADC2 pinleri Wi-Fi ile çalışır mı?
Hayır. ESP32'de ADC2 birimini Wi-Fi sürücüsü de kullandığı için Wi-Fi açıkken ADC2 pinlerinden (GPIO 0, 2, 4, 12–15, 25–27) okuma yapılamaz. Wi-Fi'li projelerde analog sensörleri ADC1 pinlerine (GPIO 32–39) bağla.
DAC nedir, ADC'den farkı ne?
DAC (Dijital-Analog Dönüştürücü) ADC'nin tersini yapar: bir sayıyı gerilime çevirir. ADC bir sensörden gelen gerilimi ölçmek, DAC ise ses ya da sinyal gibi bir gerilim üretmek için kullanılır. Arduino Uno'da DAC yoktur ve analogWrite() PWM üretir; ESP32'de GPIO 25 ve 26'da 8 bitlik iki DAC, Uno R4'te ise A0'da 12 bitlik bir DAC bulunur.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
Ldr İle Işık Şiddeti Okuma
Odanın ne kadar aydınlık olduğunu sayıyla görmek ister misin? Işığa duyarlı küçük bir parça olan LDR ortam ışığını ölçer ve Arduino bu değeri yarım saniyede bir bilgisayar ekranına yazar. Elinle üstün

LCD Ekran ile Dijital Voltmetre
Pilin ya da adaptörün ne kadar gerilim verdiğini kendi yaptığın ölçü aletiyle öğren. İki dirençten oluşan bir bölücü yüksek gerilimi kartın okuyabileceği seviyeye indirir, Arduino da gerçek değeri hes

ESP32 LDR Modülü ile Işık Şiddeti Okuma
LDR modülünün ham ADC değerini ve karanlık/aydınlık referanslarına göre hesaplanan göreli ışık yüzdesini Serial Monitor'da gerçek zamanlı izleme. Bu yüzde lux ölçümü değildir. Modülün kalibrasyon mantığını öğretir. Proje 10'un öncesinde yapılması ideal; çünkü eşik değerini belirlemek için kullanılır.

ESP32 Potansiyometre ile LED Parlaklık (Analog → PWM)
Bu projede bir potansiyometre ile LED parlaklığını analog olarak kontrol ediyoruz. ESP32'nin ADC pini potansiyometreden gelen 0-3.3V gerilimi okur, ardından bu değer PWM (Pulse Width Modulation) sinyaline çevrilerek LED'e gönderilir. Böylece potansiyometreyi çevirdikçe LED kademeli olarak parlar ve söner. Arduino Core 3.0+ ile analogWrite() doğrudan kullanılabilir; ESP32-S2/S3'te ADC çözünürlüğü 12-bit'e sabitlenir.

NTC ve 2x16 Lcd Ekran İle Sıcaklık Ölçümü
Ortamın sıcaklığını küçük bir boncuk gibi görünen sensörle ölç. NTC adlı bu parça ısındıkça elektriği daha kolay geçirir; Arduino bu değişimi okuyup bir formülle santigrat dereceye çevirir ve iki satı

Potansiyometre İle Servo Motor Kullanım
Potansiyometrenin düğmesini çevirdikçe servo motorun kolu da onunla birlikte döner; düğmenin bir ucu sıfır dereceye, öbür ucu yarım tura karşılık gelir. Arduino düğmenin konumunu sürekli okur ve servo

Joystick İle Led Kontrol
Oyun kolundaki küçük çubuğu hangi yöne sonuna kadar itersen o yöndeki LED yanar: sağ, sol, yukarı ve aşağı için dört ayrı renk var. Çubuğu bıraktığında ortaya döner ve bütün LED'ler söner. Robot araba

ESP32 Renk Mikser Lambası (3 Pot + RGB LED + OLED)
ESP32 ile 3 potansiyometre çevirerek istediğin rengi karıştıran akıllı bir renk mikser lambası! Kırmızı, yeşil ve mavi potansiyometreleri çevirdikçe ortak katot RGB LED anlık olarak renk değiştirir. SSD1306 OLED ekranda her renk için 0-255 aralığında değer, görsel dolgu barları ve HEX web renk kodu (#FF8040 gibi) canlı olarak gösterilir. Mini bir profesyonel renk stüdyosu — RGB renk teorisi, ADC analog okuma, PWM ile parlaklık kontrolü ve I2C ekran tasarımını tek projede öğretir. Grafik tasarımc
Diğer yazılar
BlueGrays uygulaması
Bu devreyi telefonunda adım adım kur
Devre şeması, kod ve parça listesi tek ekranda. 200'den fazla Arduino, ESP32 ve Pico projesi seni bekliyor.
Telefonunla tara
Kamerayı koda tut; telefonunun uygulama mağazası açılır.
ya da mağazada aç

