Sadece veri göstermek yetmez; bazen kullanıcıya ayar yaptırmak, mod değiştirmek veya bir işlemi başlatmak istersiniz. İşte burada devreye "Menü Algoritmaları" girer. Bu projede 3 butonla kontrol edilen profesyonel bir arayüz yapacağız.

1. Gerekli Malzemeler ve Bağlantı

LCD ekranı I2C ile (A4, A5), butonları ise dijital pinlere bağlayacağız. Breadboard karmaşasını önlemek için butonlarda harici direnç kullanmayacağız (Dahili PULLUP kullanacağız).

🔌 Pin Bağlantıları
  • LCD I2C: SDA->A4, SCL->A5
  • Yukarı Butonu: Pin 2 -> GND
  • Aşağı Butonu: Pin 3 -> GND
  • Seç (Enter) Butonu: Pin 4 -> GND
İpucu: Butonların diğer ucunu doğrudan GND'ye bağlıyoruz. 5V'a bağlamayın! Yazılımda "INPUT_PULLUP" kullanacağız.
🎛️

Navigasyon Sistemi

2. Menü Nasıl Çalışır? (İmleç Mantığı)

Menü sistemi aslında bir "Sayaç"tır. Aşağı bastıkça sayacı artırırız, yukarı bastıkça azaltırız. Sayacın değerine göre ekrana farklı yazılar yazarız.

> LED Yak Sicaklik Değişken sayfa = 1 ⬆️ sayfa-- ⬇️ sayfa++ OK İşlem Yap Butona basılınca sayaç değişir Sayaç ekranı günceller

3. Yazılım (State Machine)

Bu kodda 3 sayfalık bir menü oluşturacağız. Butonlara basıldığında sadece sayfa değişkenini değiştirip, menuGuncelle() fonksiyonunu çağıracağız.

Menu_Sistemi.ino C++
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// Buton Pinleri
const int btnYukari = 2;
const int btnAsagi = 3;
const int btnSec = 4;

// Menü Değişkenleri
int sayfa = 1;      // Hangi menüdeyiz?
int toplamSayfa = 3;

void setup() {
  // Butonları INPUT_PULLUP yapıyoruz (Direnç gerekmez)
  // DİKKAT: Basınca LOW (0), bırakınca HIGH (1) okunur.
  pinMode(btnYukari, INPUT_PULLUP);
  pinMode(btnAsagi, INPUT_PULLUP);
  pinMode(btnSec, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();
  menuGuncelle(); // İlk açılışta menüyü çiz
}

void loop() {
  // --- AŞAĞI BUTONU ---
  if (digitalRead(btnAsagi) == LOW) {
    if (sayfa < toplamSayfa) {
      sayfa++;
    } else {
      sayfa = 1; // Başa dön
    }
    menuGuncelle();
    delay(200); // Buton arkı (Debounce) için bekleme
  }

  // --- YUKARI BUTONU ---
  if (digitalRead(btnYukari) == LOW) {
    if (sayfa > 1) {
      sayfa--;
    } else {
      sayfa = toplamSayfa; // Sona git
    }
    menuGuncelle();
    delay(200);
  }

  // --- SEÇ BUTONU ---
  if (digitalRead(btnSec) == LOW) {
    aksiyonYap();
    delay(200);
  }
}

// Ekranı sadece sayfa değişince temizleyip yazar
void menuGuncelle() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("MENU SECIMI:");
  
  lcd.setCursor(0, 1);
  if (sayfa == 1) {
    lcd.print("> 1. LED Yak");
  } else if (sayfa == 2) {
    lcd.print("> 2. LED Sondur");
  } else if (sayfa == 3) {
    lcd.print("> 3. Bilgi");
  }
}

// Seç tuşuna basılınca ne olacak?
void aksiyonYap() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("ISLEM YAPILIYOR");
  lcd.setCursor(0, 1);
  
  if (sayfa == 1) {
    lcd.print("LED Yandi!");
    // digitalWrite(13, HIGH); kodu buraya
  } else if (sayfa == 2) {
    lcd.print("LED Sondu!");
  } else if (sayfa == 3) {
    lcd.print("Ver: v1.0");
  }
  delay(1500); // Mesajı göster ve bekle
  menuGuncelle(); // Menüye geri dön
}
        

4. Ekran Neden Titriyor? (Flickering)

Sorun: Birçok kişi menuGuncelle() fonksiyonunu doğrudan loop() içine yazar. Bu durumda Arduino saniyede binlerce kez ekranı silip (lcd.clear) tekrar yazar. Bu da ekranın titremesine ve silik görünmesine yol açar.

Çözüm: Kodda dikkat ettiyseniz menuGuncelle() sadece butonlara basıldığında çağırılıyor. Butona basılmadığı sürece ekran yenilenmez ve sabit kalır.

💡 Geliştirme Önerisi

> (Büyüktür) işaretini imleç olarak kullandık. Menüyü daha profesyonel yapmak için 2 satırı aynı anda gösterip, imleci yukarı aşağı kaydırabilirsiniz.