Interrupts (Kesmeler) ve Debounce Sorunsalı
Bir kargo beklediğinizi düşünün. İki yönteminiz var:
Polling (Sorgulama): Her 10 saniyede bir kapıya gidip "Kargo geldi mi?" diye bakmak. (Çok yorucu ve verimsiz, değil mi?)
Interrupt (Kesme): Koltuğunuzda oturup işinize bakmak ve sadece kapı zili çaldığında kapıya gitmek.
İşte mikrodenetleyicilerde (Arduino, STM32 vb.) Interrupt, o kapı zilidir. İşlemci ana döngüde (loop) ne yaparsa yapsın, kesme sinyali geldiği anda elindeki işi bırakır, o acil görevi yapar ve kaldığı yerden devam eder. Harika görünüyor değil mi? Ama bu hızın ölümcül bir tuzağı var.
Mekanik Gürültü ve Işık Hızı
Interruptlar inanılmaz hızlıdır. Bir sinyalin yükseldiğini veya düştüğünü nanosaniyeler içinde yakalarlar. Eğer bir butonu interrupt pinine bağlarsanız ne olur? Siz butona "bir kere" bastığınızı sanırsınız. Ama mekanik kontakların sıçrama (bounce) yaptığını unutmayın. O metal levhalar birbirine değerken mikrosaniyeler içinde 10-20 kez açılıp kapanır. Normal kodda (digitalRead) bu çok sorun olmayabilir çünkü döngü yavaştır. Ama Interrupt pini için bu bir felakettir. İşlemci o 10 ms'lik sıçrama süresinde 20 kez işini bırakıp interrupt fonksiyonuna (ISR) gitmeye çalışır.
Sonuç: Sistem kilitlenir, sayaç 1 yerine 50 artar veya ekran donar.
ISR (Interrupt Service Routine) Kuralları
Kesme anında çalışacak fonksiyona ISR denir. Burada kurallar vardır:
Çok Kısa Olmalı: İçeri gir, bayrağı kaldır, değişkeni artır ve hemen çık. Orada uzun matematik işlemleri yapılmaz.
Delay Yasak: ISR içinde delay() çalışmaz. Çünkü delay fonksiyonu da interrupt kullanır ve siz zaten interrupt içindesinizdir. Sistem kilitlenir.
Serial Print Yasak: Seri haberleşme yavaştır. ISR içinde ekrana yazı yazdırmaya çalışırsanız işlemciyi boğarsınız.
Volatile Kullanımı: ISR içinde değiştireceğiniz değişkeni volatile int sayac; şeklinde tanımlamalısınız. Yoksa derleyici "Bu değişkeni kimse kullanmıyor" diyip silebilir.
Çözüm: Donanım mı, Yazılım mı?
Interrupt kullanırken debounce (sıçrama önleme) yapmak zordur. Çünkü delay kullanamazsınız. Peki ne yapacağız?
Yöntem A: Donanımsal Çözüm (En İyisi): Sinyali işlemciye gelmeden temizlemek. Butonun bacaklarına paralel küçük bir Kapasitör (100nF) ve bir Schmitt Trigger eklemek. Bu, işlemciye giden sinyali jilet gibi keskin ve pürüzsüz yapar. Interrupt bir kez tetiklenir, kafanız rahat eder.
Yöntem B: Yazılımsal Çözüm (Zaman Damgası): Eğer donanım ekleyemiyorsanız, ISR içinde zamanı kontrol etmelisiniz. Mantık şudur: "Son kesmeden bu yana 200ms geçti mi? Geçmediyse bu bir gürültüdür, işlem yapma."
İşte o C++ kod bloğu:
void butonKesmesi() {
static unsigned long sonZaman = 0;
unsigned long simdikiZaman = millis();
if (simdikiZaman - sonZaman > 200) { // 200ms Debounce Süresi
sayac++; // İşlemi yap
sonZaman = simdikiZaman;
}
}
İyi Çalışmalar Dilerim...

