Analog Okuma (analogRead)
Dijital pinler yalnızca “var / yok” bilgisi verir. Ancak gerçek dünya böyle çalışmaz: bir potansiyometrenin konumu, ortamın ışık şiddeti veya bir sensörün çıkışı sürekli değişen değerlerdir.
analogRead() fonksiyonu bu sürekli gerilimi sayıya çevirir.
ADC Nedir?
Arduino’nun içinde ADC (Analog-Digital Converter) adı verilen bir birim vardır. Görevi, pindeki gerilimi ölçüp sayısal bir değere çevirmektir.
Arduino Uno’nun ADC’si 10 bit çözünürlüklüdür:
2^10 = 1024 farklı değer → 0 ile 1023 arası| Pindeki gerilim | Okunan değer |
|---|---|
| 0 V | 0 |
| 1,25 V | ~256 |
| 2,5 V | ~512 |
| 3,75 V | ~768 |
| 5 V | 1023 |
Her birim yaklaşık 4,9 mV’a karşılık gelir (5 V / 1024).
Temel Kullanım
int deger = analogRead(A0); // 0 - 1023Analog pinler A0–A5’tir (Uno). Bunları giriş olarak kullanmak için pinMode() çağırmanız gerekmez.
const int SENSOR_PIN = A0;
void setup() {
Serial.begin(9600);
}
void loop() {
int deger = analogRead(SENSOR_PIN);
Serial.println(deger);
delay(200);
}Gerilime Çevirme
Ham değer bir sayıdır; gerçek gerilimi bulmak için ölçeklemek gerekir:
float volt = deger * (5.0 / 1023.0);void loop() {
int ham = analogRead(A0);
float volt = ham * (5.0 / 1023.0);
Serial.print("Ham: ");
Serial.print(ham);
Serial.print(" Gerilim: ");
Serial.print(volt, 3);
Serial.println(" V");
delay(200);
}
5.0yerine5yazarsanız tam sayı bölmesi yapılır ve sonuç sıfır çıkar. Ondalık nokta önemlidir.
Daha da doğru sonuç için gerçek besleme gerilimini ölçüp kullanın. USB ile beslenen bir Arduino’da 5V pini genellikle 4,7–4,9 V arasındadır; bu, ölçümde %5’e varan hata demektir.
map() ile Ölçekleme
Ham 0–1023 aralığını başka bir aralığa çevirmek için map() kullanılır:
map(deger, girisMin, girisMaks, cikisMin, cikisMaks)int pwm = map(analogRead(A0), 0, 1023, 0, 255); // LED parlakligi
int aci = map(analogRead(A0), 0, 1023, 0, 180); // servo acisi
int yuzde = map(analogRead(A0), 0, 1023, 0, 100); // yuzdemap() tam sayı aritmetiği kullanır; ondalık sonuç vermez ve küsuratı atar.
Ters ölçekleme de mümkündür:
int ters = map(analogRead(A0), 0, 1023, 255, 0); // deger arttikca azalirconstrain() ile Sınırlama
Sensör beklenen aralığın dışına çıkarsa map() aralık dışı değer üretir. constrain() bunu keser:
int yuzde = map(analogRead(A0), 300, 800, 0, 100);
yuzde = constrain(yuzde, 0, 100); // 0'in altina, 100'un ustune cikmasinKalibre edilmiş sensörlerde bu ikili neredeyse her zaman birlikte kullanılır.
Okuma Neden Titriyor?
Sabit bir gerilim uygulasanız bile okunan değer birkaç birim oynar. Bunun nedenleri elektriksel gürültü, besleme dalgalanması ve ADC’nin kendi hata payıdır.
Çözüm 1: Ortalama alma
int ortalamaOku(int pin, int adet) {
long toplam = 0;
for (int i = 0; i < adet; i++) {
toplam += analogRead(pin);
delay(2);
}
return toplam / adet;
}long kullanmak önemlidir; int ile 32 okumadan sonra taşma olur.
Çözüm 2: Üstel yumuşatma (EMA)
Bellek ve zaman açısından en verimli yöntemdir:
float filtreli = 0;
const float ALFA = 0.2; // kucuk deger = daha yumusak
void loop() {
int ham = analogRead(A0);
filtreli = ALFA * ham + (1.0 - ALFA) * filtreli;
Serial.println(filtreli, 1);
delay(50);
}Çözüm 3: Ölü bant
Küçük değişimleri yok sayın:
int sonDeger = 0;
void loop() {
int deger = analogRead(A0);
if (abs(deger - sonDeger) > 5) {
sonDeger = deger;
// sadece anlamli degisimde islem yap
}
}Çözüm 4: Donanımsal
Analog pin ile GND arasına 100 nF kondansatör koymak yüksek frekanslı gürültüyü temizler.
Ardışık Farklı Pinleri Okuma
Arduino’da tek bir ADC vardır ve pinler arasında bir çoklayıcı (multiplexer) ile geçiş yapılır. Yüksek empedanslı kaynaklarda, bir önceki pinin değeri sonrakine sızabilir (crosstalk).
Çözüm: aynı pini iki kez okumak ve ilkini atmak.
int temizOku(int pin) {
analogRead(pin); // ilk okumayi at (mux yerlessin)
delayMicroseconds(50);
return analogRead(pin);
}Bu, özellikle LDR ve toprak nemi gibi yüksek empedanslı sensörlerde gözle görülür fark yaratır.
5 V’tan Yüksek Gerilim Ölçmek
Analog pine 5 V’un üzerinde gerilim uygulamak mikrodenetleyiciyi bozar. Daha yüksek gerilim ölçmek için gerilim bölücü kullanılır.
Vgiris ──[ R1 ]──┬──[ R2 ]── GND
│
└── A0V_A0 = V_giris × R2 / (R1 + R2)Örnek: 12 V ölçmek
- R1 = 10 kΩ, R2 = 4,7 kΩ
- V_A0 = 12 × 4,7 / 14,7 = 3,84 V ✔ (5 V’un altında)
const float R1 = 10000.0;
const float R2 = 4700.0;
const float CARPAN = (R1 + R2) / R2; // 3.128
void loop() {
int ham = analogRead(A0);
float pinVolt = ham * (5.0 / 1023.0);
float gercekVolt = pinVolt * CARPAN;
Serial.print("Batarya: ");
Serial.print(gercekVolt, 2);
Serial.println(" V");
delay(1000);
}Bu, batarya seviyesi takibi yapmanın standart yöntemidir.
Dirençleri çok büyük seçmeyin (örneğin 1 MΩ). ADC’nin giriş empedansı yüzünden okuma kararsızlaşır. 10 kΩ mertebesi idealdir.
AREF ile Hassasiyet Artırma
Ölçtüğünüz sinyal 0–1 V arasındaysa, 0–5 V referansla okumak çözünürlüğün %80’ini boşa harcar.
analogReference(INTERNAL) ile Uno’nun dahili 1,1 V referansına geçebilirsiniz:
void setup() {
analogReference(INTERNAL); // 0 - 1.1 V araligi 0-1023'e olceklenir
Serial.begin(9600);
}
void loop() {
int ham = analogRead(A0);
float volt = ham * (1.1 / 1023.0);
Serial.println(volt, 4);
delay(200);
}Artık her birim ~1,07 mV’a karşılık gelir — beş kat daha hassas.
⚠ Bu modda pine 1,1 V’un üzerinde gerilim uygulamayın.
Okuma Hızı
Bir analogRead() çağrısı yaklaşık 100 mikrosaniye sürer. Yani saniyede en fazla ~10.000 okuma yapılabilir.
Çoğu proje için fazlasıyla yeterlidir, ancak ses işleme veya hızlı sinyal yakalama gerektiren uygulamalarda bu bir sınırdır. Bu durumda ADC prescaler ayarları değiştirilerek hız artırılabilir (doğruluk pahasına).
ESP Kartlarında Farklar
| Kart | ADC çözünürlüğü | Aralık | Not |
|---|---|---|---|
| Arduino Uno | 10 bit (0–1023) | 0 – 5 V | 6 kanal |
| ESP8266 | 10 bit | 0 – 1 V | Tek kanal (A0); NodeMCU’da kart üzerindeki bölücü ile 0–3,3 V |
| ESP32 | 12 bit (0–4095) | 0 – 3,3 V | 18 kanal, ancak doğrusallığı zayıf |
| Arduino Due | 12 bit (0–4095) | 0 – 3,3 V |
ESP32’nin ADC’si doğrusal değildir; hassas ölçüm için kalibrasyon tablosu veya harici ADC (ADS1115) kullanmak gerekir.
Özet
analogRead(), analog pindeki gerilimi 10 bit çözünürlükle 0–1023 arasında bir sayıya çevirir. Bu sayı map() ile istenen aralığa ölçeklenir.
Bu derste şunları öğrendik:
- 10 bit ADC ve 0–1023 aralığını
- Ham değeri gerilime çevirmeyi
map()veconstrain()kullanımını- Gürültüyü ortalama, EMA ve ölü bantla azaltmayı
- Farklı pinleri okurken çift okuma tekniğini
- Gerilim bölücü ile 5 V üstü ölçmeyi
analogReference(INTERNAL)ile hassasiyet artırmayı