Arduino İle 16×2 LCD Ekranda Menü Çalışmaları

Merhaba arkadaşlar Arduino ile LCD ekranda farklı farklı menüler oluşturmak isteyebiliriz. Bazen ise aklımızda olan menüyü yapabilmek için bir çok araştırma yapmak gerekir. Bu yapılan araştırmalarda ise internette farklı farklı yöntemlerle yapılmış birçok LCD menü çalışmasını görebilirsiniz.

Açıkçası böyle bir menü çalışmasına benim de ihtiyacım doğdu ve internette detaylı bir araştırma yaptım. Bu araştırmaların kaybolmaması ve ihtiyacı olan arkadaşların da yararlanması için tüm bu çalışmaları tek bir kaynakta toplamayı yararlı hale geleceğini düşündüm. İşte gerekli kaynaklarla beraber oluşturulmuş Menü oluşturma çalışmaları.

1. Üç Butonla Menu İtemleri Şeklinde Menü Oluşturma

https://www.youtube.com/watch?v=DuAG98P9Seo Bu kaynaktan yararlandığım menü çalışmasına göre Alman mühendisin üç butonla menu itemler oluşturarak (bunları daha sonra kendiniz isimlendirebilirsiniz) basit bir menü çalışmasını yaptığını görmekteyiz. Alt alta 8 kategorilik menü listesi var ve her menüye tıkladığınızda sizlere 2 saniyelik bir print fonksiyonu açıyor (buraya kendi yaptırmak istediğiniz işlemleri yapabilirsiniz.) Kodlarına ve çalışmasına geçelim

Video’yu izlerseniz bağlantıları I2C ile gerçekleştirdiğini görürsünüz ama bu LCD’yi klasik bağlantılarla da çalıştırsanız herhangi bir fark etmeksizin çalışacaktır.

Not: Ekstra olarak ihityacımız olan tek kütüphane Wire.h kütüphanesi


#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(6, 7, 2 , 3, 4, 5);


int upButton = 8;
int downButton = 9;
int selectButton = 10;
int menu = 1;
int deger = 0;


void setup() {
  lcd.begin(16, 2);
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  updateMenu();
}

void loop() {
  if (!digitalRead(downButton)){
    menu++;
    updateMenu();
    delay(100);
    while (!digitalRead(downButton));
  }
  if (!digitalRead(upButton)){
    menu--;
    updateMenu();
    delay(100);
    while(!digitalRead(upButton));
  }
  if (!digitalRead(selectButton)){
    executeAction();
    updateMenu();
    delay(100);
    while (!digitalRead(selectButton));
  }
}

void updateMenu() {
  switch (menu) {
    case 0:
      menu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.print("MenuItem1");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem2");
      break;
    case 2:
      lcd.clear();
      lcd.print(" MenuItem1");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem2");
      break;
    case 3:
      lcd.clear();
      lcd.print(">MenuItem3");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem4");
      break;
    case 4:
      lcd.clear();
      lcd.print(" MenuItem3");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem4");
      break;
      case 5:
      lcd.clear();
      lcd.print(">MenuItem5");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem6");
      break;
    case 6:
      lcd.clear();
      lcd.print(" MenuItem5");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem6");
      break;
    case 7:
      lcd.clear();
      lcd.print(">MenuItem7");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem8");
      break;
    case 8:
      lcd.clear();
      lcd.print(" MenuItem7");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem8");
      break;
      
    case 9:
      menu = 8;
      break;
  }
}

void executeAction() {
  switch (menu) {
    case 1:
      action1();
      break;
    case 2:
      action2();
      break;
    case 3:
      action3();
      break;
    case 4:
      action4();
      break;
    case 5:
      action5();
      break;
    case 6:
      action6();
      break;
    case 7:
      action7();
      break;
    case 8:
      action8();
      break;
  }
}

void action1() {
  lcd.clear();
  lcd.print(">Executing #1");
  //delay(1500);
}
void action2() {
  lcd.clear();
  lcd.print(">Executing #2");
  delay(1500);
}
void action3() {
  lcd.clear();
  lcd.print(">Executing #3");
  delay(1500);
}
void action4() {
  lcd.clear();
  lcd.print(">Executing #4");
  delay(1500);
}
void action5() {
  lcd.clear();
  lcd.print(">Executing #5");
  delay(1500);
}
void action6() {
  lcd.clear();
  lcd.print(">Executing #6");
  delay(1500);
}
void action7() {
  lcd.clear();
  lcd.print(">Executing #7");
  delay(1500);
}
void action8() {
  lcd.clear();
  lcd.print(">Executing #8");
  delay(1500);
}

Dilediğiniz kadar menüyü genişletebilir ve daraltabilirsiniz. Aynı zamanda menü içinde void action alt programları içinde o menüye tıklandıgında hangi işlerin gerçekleşeceğini değiştirebilirsiniz.

Çalışması

NOT: Ben diğer menülerle çalıştığım için, 4. buton burada fazlalık.

2. Üç Butonla Farkı Değerlerle Çalışan LCD Menü Çalışması

Açıkçası benim ihtiyacım olan devrede herhangi bir sensör kullanımı yoktu. Bu yüzden kendi devremde stabil olarak çalıştıramadım. Ancak ihtiyacım olana yakın olan bir menü çalışması olduğu için ve algoritma olarak bu araştırmada size yardımcı olması için bu kaynağı da ekliyorum. Aynı zamanda Türkçe olması ayrı bir kolaylık . Kaynak: https://devreyakan.com/arduino-ve-lcd-ile-menu-yapimi/#Aciklamalar

Bu programı çalıştırmadan önce mutlaka bu üç kütüphaneleri indirmeniz gerekiyor

Kütüphaneleri arduino’nun kendi sitesinden en güzel haliyle elde etmeniz mümkün https://www.arduino.cc/en/reference/libraries

Kodlar:

#include <Pushbutton.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal lcd(7,8,9,10,11,12);
const int buttonPin = 2;
const int okPin = 3;
char ch;
int a = 0, e1 = 0, e2 = 0, ufo = 0, e3 = 0, saat = 0, daak = 0, cas = 0, count = 0,sicaklik,cont = 100;
int hedef = 53;
Pushbutton pbutton1(buttonPin);
Pushbutton pbutton2(okPin);

void setup() {
  cas = 0;
  pinMode(buttonPin, INPUT);
  pinMode(okPin, INPUT);
  //eğer potansiyemetre yoksa bununla parlaklık ayarlıyorum analogWrite(6, cont);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0); lcd.print("devreyakan.com");
  lcd.setCursor(2, 2); lcd.print("arduino menu");
  delay(10000);
  lcd.clear();
  lcd.setCursor(5, 0); lcd.print("Versiyon");
  lcd.setCursor(5, 2); lcd.print("A0.1");
  delay(1000);
  lcd.clear();

}

void loop() {
  updateDisplay();
  if (pbutton1.getSingleDebouncedPress()) {
    cas++;
    if (cas > 3)
    {
      cas = cas * 0;
    }
  }

  if (cas == 0)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HAZIR PROGRAMLAR");
    lcd.setCursor(0, 1);
    lcd.print("60C'de 60 dakika");

  }
  else if (cas == 1)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HAZIR PROGRAMLAR");
    lcd.setCursor(0, 1);
    lcd.print("10C'de 10 dakika");
  }
  else if (cas == 2)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HAZIR PROGRAMLAR");
    lcd.setCursor(0, 1);
    lcd.print("20C'de 30 dakika");
  }
  else if (cas == 3)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Manuel PROGRAMLA");
    lcd.setCursor(0, 1);
    lcd.print("Deger giriniz...");
  }

  if (pbutton2.getSingleDebouncedPress()) {

    if (cas == 0) {
      saat = 1;
      hedef = 60;
      saatci();
    }
    if (cas == 1) {
      saat == 1;
      hedef == 60;
      saatci();

    }
    if (cas == 2) {
      saat == 1;
      hedef == 60;
      saatci();

    }
    if (cas == 3) {
      saat == 1;
      hedef == 60;
      saatci();

    }

  }


  delay(100);

}

void saatci()
{
  delay(1000);
  e2 = daak;
  e3 = 0;

  for (e1 = saat; e1 >= 0; e1--)
  {
    for (e2; e2 >= 0; e2--)
    {
      for (e3; e3 >= 0; e3--)
      {
        lcd.clear();
        lcd.print("");
        lcd.print("Sure:");
        lcd.print(" ");
        lcd.print("Hedef:");
        lcd.print(hedef);
        lcd.print("C");
        lcd.setCursor(0, 1);
        lcd.print("");
        lcd.print(e1);
        lcd.print(":");
        lcd.print(e2);
        lcd.print(":");
        lcd.print(e3);
        lcd.setCursor(13, 1);
        sensors.requestTemperatures();
        sicaklik = sensors.getTempCByIndex(0);
        lcd.print(sicaklik);
        lcd.print("C");
        delay(1000);

        if (sicaklik < hedef)
        {
          digitalWrite(2, LOW);
        }
        else if (sicaklik > hedef)
        {
          digitalWrite(2, LOW);
        }


        if (e1 + e2 + e3 <= 0)
        {
          lcd.clear();
          lcd.print("Kaynatma Bitti");
          daak = saat = 0;
          hedef = 30;
        }

      }
      e3 = 59;
    }
    e2 = 59;
  }
}
void termo()
{
  while ( a <= 50)
  {
    a = a + 1; 
    delay(200); 
    lcd.setCursor(13, 1);
    sensors.requestTemperatures();
    sicaklik = sensors.getTempCByIndex(0);
    lcd.print(sicaklik);
    lcd.print("C");
  }
}
void updateDisplay() {
  lcd.setCursor(0, 0);
}

3. Arduino LCD Menü Çalışması

Gelelim benim algoritma açısından hayran kaldığım ve programcılık dehası menü çalışmasına. Bu araştırmayı yaklaşık 5 ay önce yaptığım için kaynağı kaybettim ekleyemiyorum ama bulduğumda hemen eklicem.

Kaynağı buldum ekliyorum : https://www.youtube.com/watch?v=Q58mQFwWv7c

Programımız 4 adet butola, 8 farklı parametrenin değerini değiştirmemize yarayan bir menü.

Program kodlarımız bu şekilde. Herhangi bir kütüphane eklemenize gerek yoktur

#include <LiquidCrystal.h>
LiquidCrystal lcd(6, 7, 2 , 3, 4, 5);

//Input & Button Logic
const int numOfInputs = 4;                              //inputların başladığı numara
const int inputPins[numOfInputs] = {8, 9, 10, 11};      //inputların tanımlamalar string.
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW, LOW};
bool inputFlags[numOfInputs] = {LOW, LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0, 0};
long debounceDelay = 5;

//LCD Menu Logic
const int numOfScreens = 10;
int currentScreen = 0;
String screens[numOfScreens][2] = {{"Motor Voltage", "Volts"}, {"Motor Current", "Amps"},
  {"Motor Rated HP", "HP"}, {"Overload Temp.", "degC"}, {"Accel Time", "Secs"}, {"Restart Time", "Mins"},
  {"Analog Out. Curr.", "mA"}, {"Input Temp.", "degC"}, {"Run Time", "Hours"}, {"Start Times", "times"}
};     // parametrele üstte yazan ve altında yazan
int parameters[numOfScreens];

void setup() {
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  //Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  setInputFlags();      //chattring olayını engellemek için
  resolveInputFlags();   // geçişlerde sıkıntı olmaması için
}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    if (inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input) {
  if (input == 0) {
    if (currentScreen == 0) {
      currentScreen = numOfScreens - 1;
    } else {
      currentScreen--;
    }
  } else if (input == 1) {
    if (currentScreen == numOfScreens - 1) {
      currentScreen = 0;
    } else {
      currentScreen++;
    }
  } else if (input == 2) {
    parameterChange(0);
  } else if (input == 3) {
    parameterChange(1);
  }
}

void parameterChange(int key) {    // 0. Butona basarsan parametreyi artır, 1. butona basarsan azalt
  if (key == 0 && parameters[1] <= 10) {
    parameters[currentScreen]++;
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

void printScreen() {            //her işlemden sonra bunu yazarız, ki yaptığımız işlemler ekrana yansısın
  lcd.clear();
  lcd.print(screens[currentScreen][0]);   //hangi ekrandaysa oraya gider ve oradaki değişkeni değiştirir. aslında muhteşem bir programcılık örneği
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}

Videoyu izler ve kodlama aşamalarını adım adım takip ederseniz gerçekten program algoritmasına hayran olmamanız elde değil. Burada string ve matrislerin kullanımının ne denli önemli olduğunu görüyoruz. Özellikle matrisler gerçekten harika kullanılmış. Tabi bu programcının sağlam bir yazılım altyapısına sahip olduğunu gösterir.

Yukarıdaki menü çalışmasını için benim yapmam gereken değişiklik şuydu. Her ne kadar güzel bir program olsa da, her parametreye istedğiniz kadar değer girebiliyorsunuz. Burada ben bu değerlere sınır koydum aslında sadece bir paragrafta değişiklik yaptım diyebilirim. Görebilirsiniz.

Öncelikle parametreler matris olarak yazıldığı için hangi değerin hangi parametreye geldiğini bilmemiz lazım. Yani parametres[0] aslında Motor Voltage parametresine karşılık geliyor. Biz istiyoruz ki kişi 10 volttan fazla voltaj belirleyemesin.

İkinci olarak, bu parametrelerden hangisine sınır koyacaksam kodlardaki uygun yere değişiklikleri yapıyorum

Yazı olarak bu şekilde

void parameterChange(int key) {     //bu fonksiyon kolay. 0. Butona basarsan parametreyi artır, 1. butona basarsan azalt diyor.
  if(key == 0) {
    parameters[currentScreen]++;
void parameterChange(int key) {     //bu fonksiyon kolay. 0. Butona basarsan parametreyi artır, 1. butona basarsan azalt diyor.
  if (key == 0 ) {
    parameters[currentScreen]++;
     if (parameters[0] == 11){parameters[0] = 10;}if (parameters[2] == 3){parameters[2] = 2;}
     if (parameters[3] == 6){parameters[3] = 5;}
  } else if (key == 1) {
    parameters[currentScreen]--;
  }
}

Burada Motor Voltage max 10, paramteres[5] yani Restart time max 5 gibi sınırlamalar koyduk. Aynı şekilde parametre2 ye karşılık gelen değerimiz ise max 2 olacak şekilde ayarlandı. Aynı şekilde dereceyi de max 5 olarak seçebilsin diye ayarladık.

Aynı şekilde eğerki 0’ın altına düşmesini istemiyorsak else if (key === 1) bloğu altına istediğimiz parametrenin belirli bir değerin altına düşmemesini sağlayabiliriz. Bu değişiklikleri yaptıktan sonra prgramımız bu şekilde çalışıyor

İyi çalışmalar !

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir