Ana Sayfa · Akademi · Robotik ve Kodlama · Arduino · Buton Debounce Mantığı

Buton Debounce Mantığı

Buton titremesini (bounce) millis ile yazılımsal debounce yaparak güvenilir saymayı öğren.

DERS PUSULASI

Bu sayfayı ne için kullanacaksın?

Ana fikir

Bir butona bir kez bastığında Arduino bazen birden fazla basış görür; bu yanlış saymayı önlemek için millis() ile küçük bir zaman kontrolü ekleyerek butonu "yumuşatmayı" (debounce) öğreneceğiz.

Üretilecek kanıt

Amaç: Butona her basışta sayacı tam olarak bir artırmak ve sonucu Seri Ekran'a yazmak. Bağlantı Buton bir bacağı 5V 'a, çapraz bacağı hem 2 numaralı dijital pine hem de bir 10 kΩ direnç üzerinden GND 'ye. (Bu direnç, pin boştayken sinyali LOW'a çeker; buna pull-down denir.) Alternatif: Direnç kullanmadan INPUT_PULLUP modu; o zaman butonun diğer bacağı…

Kontrol tuzağı

Butonun içinde ne olur? Bir buton, iki metal temas noktasını birbirine bağlayan basit bir anahtardır. Bastığında bu iki nokta birleşir, bıraktığında ayrılır. Ama metal esnektir. Bastığın anda temas noktaları bir yayın ucundaki top gibi birkaç kez zıplar: Basış anı (zaman ->) Sinyal: 1 0 1 0 1 1 1 1 1 (kararsız…

Sonraki bağlantı

Servo Kontrolü: Bir servo motoru açıya göre nasıl döndürürüz ve butonla nasıl birleştiririz.

Modül kaynakları: Python Tutorial · Arduino Learn

SeviyeBaşlangıç
Yaş10–16
Süre30–45 dk
Ön koşulPWM
İçerikStandart ders · 1.459 kelime
Son güncelleme

Bir cümlelik özet

Bir butona bir kez bastığında Arduino bazen birden fazla basış görür; bu yanlış saymayı önlemek için millis() ile küçük bir zaman kontrolü ekleyerek butonu "yumuşatmayı" (debounce) öğreneceğiz.

Neden önemli?

Bir asansör düğmesine bir kez basarsın ve asansör bir kat çağrılır, iki kat değil. Bir oyun kolundaki zıplama tuşuna bir kez basarsın ve karakter bir kez zıplar. Bu doğal görünür, ama arkasında sessiz bir sorun vardır.

Mekanik butonlar metal parçaların birbirine değmesiyle çalışır. Parçalar bastığın anda tam temiz temas etmez; çok kısa bir süre titreşir, minik sıçramalarla açılıp kapanır. Buna bounce (sıçrama/titreme) denir. İnsan gözü bunu göremez çünkü bu titreme yalnızca birkaç milisaniye sürer. Ama Arduino saniyede milyonlarca kez kontrol yaptığı için bu titremenin her sıçramasını ayrı bir basış sanabilir.

Sonuç: Bir sayaç yazarsın, butona bir kez basarsın, ekranda sayı 1 yerine 3 olur. Kod yanlış değildir; buton fiziksel olarak "kekelemiştir". Debounce, bu kekemeliği yazılımla düzeltmenin adıdır ve gerçek dünyayla çalışan her projede karşına çıkar.

Bounce nedir ve neden yanlış sayar?

Butonun içinde ne olur?

Bir buton, iki metal temas noktasını birbirine bağlayan basit bir anahtardır. Bastığında bu iki nokta birleşir, bıraktığında ayrılır. Ama metal esnektir. Bastığın anda temas noktaları bir yayın ucundaki top gibi birkaç kez zıplar:

Basış anı (zaman ->)
Sinyal:  1 0 1 0 1 1 1 1 1   (kararsız titreme, sonra kararlı)
Süre:    ~1-10 milisaniye     sonra sabit

Gözünle tek bir "bas" görürsün. Arduino ise bu 5–6 değişimin hepsini ayrı bir olay olarak okuyabilir.

Neden basit sayaç şaşırır?

En yalın haliyle bir sayaç şöyle düşünülür: "Buton basılıysa sayacı bir artır." Ama loop() çok hızlı döner. Titreme boyunca buton birçok kez "basılı" görünür, bu yüzden sayaç bir yerine birkaç kez artar. Ayrıca butonu basılı tuttuğun sürece de sayaç sürekli artmaya devam eder. İki farklı sorun var: titreme ve basılı tutma.

Doğru sayım için iki şeye ihtiyacımız var: (1) titremeyi görmezden gelmek, (2) yalnızca "basılı değil → basılı" geçişini bir kez saymak.

Yazılımla debounce: zamanı ölçmek

Neden delay() iyi bir çözüm değil?

İlk akla gelen fikir: butonu görünce delay(50) koyup titremenin geçmesini beklemek. Küçük projelerde işe yarar ama delay() sırasında Arduino başka hiçbir şey yapamaz — LED'i güncelleyemez, başka sensör okuyamaz. Motor kontrolünde veya birden çok işi aynı anda yürüten projelerde bu donma sorun olur. Bu yüzden bloklamayan (non-blocking) bir yöntem tercih ederiz: millis().

millis() ile fikir

millis(), Arduino açıldığından beri geçen milisaniye sayısını verir. Onu bir kronometre gibi kullanırız. Butonun durumu her değiştiğinde zamanı not ederiz. Yeni bir değişiklik gördüğümüzde, "son değişiklikten bu yana en az 50 milisaniye geçti mi?" diye sorarız. Geçmediyse bu muhtemelen titremedir, görmezden geliriz. Geçtiyse gerçek bir değişimdir, kabul ederiz.

50 milisaniye insan için çok kısadır (parmağını bu kadar hızlı iki kez basamazsın), ama titremeden çok daha uzundur. Yani gerçek basışları kaçırmadan titremeyi eleriz.

Filtreleme fikriyle bağ

Bu tam olarak bir filtredir. Sensör derslerinde gürültülü bir ölçümü yumuşatmak için ortalama aldığımızı hatırla. Burada da butondan gelen "gürültülü" sinyali zamanla eleyip sadece gerçek olayı geçiriyoruz. Debounce, dijital dünyanın filtresidir: hızlı ve anlamsız değişimleri atar, yavaş ve gerçek değişimleri geçirir.

Mini uygulama

Amaç: Butona her basışta sayacı tam olarak bir artırmak ve sonucu Seri Ekran'a yazmak.

Bağlantı

Aşağıdaki sketch harici pull-down direncine göre yazılmıştır (basılınca HIGH).

const int butonPin = 2;
int sayac = 0;

int sonKararliDurum = LOW;   // butonun kabul edilmiş durumu
int sonOkuma = LOW;          // en son ham okuma
unsigned long sonDegisimZamani = 0;
const unsigned long bekleme = 50; // milisaniye

void setup() {
  pinMode(butonPin, INPUT);
  Serial.begin(9600);
}
void loop() {
  int okuma = digitalRead(butonPin);

  if (okuma != sonOkuma) {
    sonDegisimZamani = millis();   // titreme başladı, zamanı not et
  }

  if (millis() - sonDegisimZamani > bekleme) {
    if (okuma != sonKararliDurum) {
      sonKararliDurum = okuma;
      if (sonKararliDurum == HIGH) {  // yalnızca basma anında say
        sayac++;
        Serial.println(sayac);
      }
    }
  }

  sonOkuma = okuma;
}

Kodu yükle, Seri Ekran'ı (Serial Monitor) 9600 baud'da aç ve butona bas. Her basışta sayının tam bir arttığını göreceksin. İstersen bekleme değerini 5'e düşür ve titremenin yanlış saymayı nasıl geri getirdiğini gözlemle.

Uygulama laboratuvarı: Buton Debounce Mantığı

Buton Debounce Mantığı konusunu kalıcı hâle getirmenin en iyi yolu, kavramı küçük ve ölçülebilir bir göreve dönüştürmektir. Bu çalışmada Bounce nedir ve neden yanlış sayar? ile Neden basit sayaç şaşırır? arasındaki ilişkiyi kullanarak bağlantı şeması, derlenebilen Arduino kodu, seri monitör kaydı ve test sonucu hazırlayacaksın. Amaç yalnız sonucun çalışması değil; hangi kararı neden verdiğini, neyi test ettiğini ve hangi durumda tasarımı değiştireceğini açıklayabilmektir.

Görev senaryosu

Şu senaryoyu ele al: potansiyometreyle servo açısını sınırlar içinde değiştiren düzenek. Dersin ana hedefi “Buton titremesini (bounce) millis ile yazılımsal debounce yaparak güvenilir saymayı öğren” olduğuna göre önce problemi tek cümleyle tanımla. Ardından sistemin alacağı girdiyi, uygulayacağı işlemi ve üreteceği çıktıyı ayrı ayrı yaz. Bilmediğin bir ayrıntı varsa onu varsayım olarak işaretle; varsayımı gerçek bilgi gibi kullanma.

  1. Planla: Başlangıç durumunu, beklenen sonucu ve kullanacağın kavramları yaz.
  2. En küçük sürümü kur: Yalnız temel davranışı çalıştır; süsleme ve ek özellikleri sonraya bırak.
  3. Üç test hazırla: Normal bir durum, sınırda bir durum ve hatalı ya da beklenmeyen bir durum seç.
  4. Sonucu kaydet: Beklenen ile gerçekleşeni yan yana yaz; fark varsa olası nedeni belirt.
  5. Tek değişiklik yap: Aynı anda birçok şeyi değiştirmek yerine bir kararı düzeltip testi yeniden çalıştır.

Başarı ölçütleri

“Buton Debounce Mantığı” çalışmasını bitirdiğinde ürünü bir arkadaşına yalnız bölüm başlıklarıyla anlat. Arkadaşın potansiyometreyle servo açısını sınırlar içinde değiştiren düzenek senaryosundaki adımları ve karar nedenlerini takip edebiliyorsa anlatım yeterince açıktır. Anlaşılmayan noktayı daha fazla terim ekleyerek değil, Bounce nedir ve neden yanlış sayar? ve Neden basit sayaç şaşırır? ilişkisini daha küçük adımlara bölerek düzelt.

Sık yapılan hatalar

Zamanı yanlış yerde not etmek

sonDegisimZamani = millis(); satırı yalnızca okuma değiştiğinde çalışmalı. Her döngüde çağırırsan kronometre sürekli sıfırlanır ve millis() - sonDegisimZamani asla beklemeyi geçemez; buton hiç çalışmaz gibi görünür.

Basma yerine bırakmayı saymak

Eğer if (sonKararliDurum == HIGH) kontrolünü koymazsan, hem basma hem bırakma sayılır ve her basış sayacı iki artırır. Sadece bir geçiş yönünü saymalısın.

Pull-down veya pull-up direncini unutmak

Butonun boştaki bacağı hiçbir yere bağlı değilse pin "havada" kalır (floating) ve rastgele HIGH/LOW okur. Debounce kodu bile bu rastgeleliği düzeltemez. Mutlaka bir pull-down/pull-up direnci veya INPUT_PULLUP kullan.

delay() ile yavaşlatmaya çalışmak

delay(200) koyarak "yavaşlatınca düzelir" düşüncesi hem gerçek hızlı basışları kaçırır hem de diğer işleri durdurur. millis() çözümü hem daha doğru hem de bloklamaz.

Güvenlik notu

Ders özeti

Kontrol soruları

  1. Buton "bounce" (titreme) nedir ve neden olur?
  2. Basit bir sayaç, bir basışta neden bazen 2 veya 3 kez artar?
  3. Debounce için neden delay() yerine millis() tercih ederiz?
  4. Kodda sonDegisimZamani = millis(); satırı ne zaman çalışmalıdır?
  5. if (sonKararliDurum == HIGH) kontrolü olmasaydı sayaç nasıl davranırdı?

Cevaplar

  1. Bounce, butonun metal temas noktalarının basıldığı anda birkaç kez hızlıca açılıp kapanmasıdır; metal esnek olduğu için birkaç milisaniye titrer.
  2. Çünkü loop() çok hızlı döner ve titreme boyunca buton birçok kez "basılı" görünür; her görünüş ayrı sayılır.
  3. millis() bloklamayan bir zaman ölçümüdür; beklerken Arduino başka işler (LED, sensör, motor) yapmaya devam edebilir, delay() ise her şeyi durdurur.
  4. Yalnızca ham okuma bir önceki okumadan farklı olduğunda; yani sinyal her değiştiğinde kronometre yeniden başlatılır.
  5. Hem basma hem bırakma "durum değişimi" sayılacağı için her tam basış sayacı iki artırırdı.

Kaynak ve doğrulama notu

“Buton Debounce Mantığı” dersi için doğrulama odağı Bounce nedir ve neden yanlış sayar? ile Neden basit sayaç şaşırır? arasındaki ilişkinin örnekler üzerinde tutarlı çalışmasıdır. Arduino uyumlu kartlarda pin, gerilim ve akım sınırları modele göre değişebilir. Kod derlense bile devre güvenli olmayabileceğinden, motor ve servo gibi yükler uygun sürücü ve harici besleme ile kullanılmalıdır.

Sonraki ders

Servo Kontrolü: Bir servo motoru açıya göre nasıl döndürürüz ve butonla nasıl birleştiririz.

Quiz’i BaşlatArduino bölümüne dön
SORU HAVUZU

Bu dersi 10 soruyla pekiştir

Bu ders için 20 soruluk bir havuz hazırlandı. Her başlangıçta 10 soru ve seçenekler yeniden karıştırılır.