Arduinoda Basit Menü Tasarımı
Bazı projelerde sistem çalışırken parametrelerde değişiklik yapmamız gerekebilir. Böyle durumlarda projemiz için bir menü hazırlamak işimizi oldukça kolaylaştırır.
Bu örnekte 16*2 LCD ekran ve tuş takımı kullanarak basit bir menü hazırlayacağız. Ben tuş takımı olarak eski bir bilgisayar faresi kullandım. Normalde arduino PS/2 klavye ve farelerle haberleşebiliyor, ilgili kütüphaneyi ve bu projede kullandığımız kütüphaneleri kütüphane arşivinde bulabilirsiniz. Bu projede farenin sadece tuşlarını kullanacağımız için diğer kısımları kesip çıkardım.
Tuşların birer uçlarını graunda bağladıktan sonra diğer uçlarını da arduinonun dijital pinlerine bağlıyoruz.
Fare tekeri aslında döner bir enkoderdir, bunun için teker hareketini encoder kütüphanesini kullanarak okuyacağız.
Resimdeki gibi 3 bacaklı bir şey. Bu bacakların biri arduinonun grounduna diğer ikisi dijital pinlere bağlayacağız ama hangisini nereye…
Graund bacağını baskı devredeki yollara bakarak tahmin edebiliriz ya da deneme yanılma yöntemiyle bulacağız, diğer iki bacağın bağlama sırası çok önemli değil. Ters bağlarsak tekeri çevirme yönünü ters okur. Bağlantıların doğruluğunu kontrol etmek için encoder kütüphanesinin örnek kodlarını kullanabilirsiniz.
LCD nin VO (kontrast) ını arduinun PWM pinine, arka ışığı da bir transistör aracılığıyla arduinoya balıyoruz. LCD nin geri kalan bağlantılarını da yaptıktan sonra kod kısmına geçebiliriz.
Kütüphaneler ve tanımlamalar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <ShiftLCD.h> //Shift register ile LCD sürmek için //bu projede kullandığımız komutlar //Arduinonun LiquidCrystal kütüphanesindeki //komutlarla bire bir aynı. #include <saat.h> #include <Encoder.h> #include <Button.h> #include <EEPROM.h> //LCD için shift register bağlantıları ShiftLCD lcd(2, 4, 3); //Encoder bağlantıları Encoder enc(5, 6); //Tuş bağlantıları Button sag_tus = Button(8,PULLUP); Button sol_tus = Button(7,PULLUP); Button orta_tus = Button(9,PULLUP); byte tr_pin = 11; //LCD nin arka ışık transistörünü kontrol edeceğimiz pin byte saat=0; byte dk=0; boolean aydinlatma=0; byte m=20; byte e_m, e_em; byte em = 20; boolean yeni_ekran; boolean ayarli; byte arkaisik_suresi; byte kontrast; const byte kontrast_adres=0; //EEPROM da kontrast değerini kaydedeceğimiz adres const byte aydinlatma_adres=1; //EEPROM da arka ışık süresini değerini kaydedeceğimiz adres unsigned long t; |
Void Setup()
1 2 3 4 5 6 7 8 |
void setup() { pinMode(tr_pin, OUTPUT); pinMode(10, OUTPUT); kontrast=EEPROM.read(kontrast_adres); //Kaydedilmiş değerler arkaisik_suresi=EEPROM.read(aydinlatma_adres); //değişkenlere atanıyoruz analogWrite(10, 140-kontrast*7); //PWM sinyali analog sinyal gibi kullanıp kontrastı ayarlıyoruz lcd.begin(16, 2); } |
Void Loop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
void loop(){ isik(); //Arka ışığı kontrol eden fonksiyon, ileride inceleyeceğiz if (e_m != m){ //m değişkenini değiştirerek menüde dolaşacağız yeni_ekran=1; //bu değeri kontrol ederek ekrana yeni şeyler yazmadan e_m=m; //önce ekranı temizleyeceğiz } if ( m != 20 && sag_tus.isPressed()){ //Menüdeyken sağ tuşa bastığımızda m=20; //menüden çıkmamışı sağlayacak. m in em=20; //değeri ana ekrandayken 20 } //tuşa basıldığında Button kütüphanesinde //isPressed() true değerini verir if (m==0) m=4; //Menüde baştan sona sondan başa geçiş yapabilmek için if (m==5) m=1; //Menü oluşturan döngü switch (m){ //Ana ekran case 20: if (yeni_ekran){ //Ekrana yeni şeyler yazılacağı zaman ekranı temizler lcd.clear(); yeni_ekran=0; } if (orta_tus.uniquePress()){ //m değerini 1 yaparak menüye girmemiz sağlar m=1; } saat_goster(0, 1, hour(), minute()); //Ana ekranda saati gösteren fonksiyon, ileride inceleyeğiz break; //boş menü case 1: m += -teker(); //m değerini değiştirerek menüde dolaşıyoruz, fonksiyonu ileride inceleyeceğiz yaz("menu 1"); //Menü başlığını break; //boş menü case 2: m += -teker(); yaz("menu 2"); break; //saat ayarı case 3: m += -teker(); yaz("Saati Ayarla"); if (orta_tus.uniquePress()){ ayarli=0; } if (ayarli){ saat_goster(0, 1, hour(), minute()); //sadece saati gösterir } else{ saat_ayarla(0,1); //saati ayarlar, ilerde... } break; //alt menüsü olan menü case 4: if (e_em != em){ // yeni_ekran=1; //Bu kısım ana ekranla e_em=em; //aynı mantıkla çalışıyor } // if (em==0) em=2; // if (em==3) em=1; // //alt menü fonksiyonu, ilerde... ekran(); break; } } |
Arka ışık Fonksiyonu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
void isik(){ //Herhangi bir tuşa basıldığında sayacı sıfırlıyor //Benzer şeyleri 2 kere yazmamın sebebi button kütüphanesiyle ilgili //bu konuya şimdi girmeyeceğiz if (aydinlatma==1 && sag_tus.stateChanged()){ t=millis(); } if (aydinlatma==1 && sol_tus.stateChanged()){ t=millis(); } if (aydinlatma==1 && orta_tus.stateChanged()){ t=millis(); } if (aydinlatma==0 && sag_tus.isPressed()){ t=millis(); } if (aydinlatma==0 && sol_tus.isPressed()){ t=millis(); } if (aydinlatma==0 && orta_tus.isPressed()){ t=millis(); } //Sürenin dolup dolmadığını kontrol ediyor if (aydinlatma==0 & millis()-t<1000UL*arkaisik_suresi){ digitalWrite(tr_pin, 1); aydinlatma=1; } else if (aydinlatma==1 & millis()-t>1000UL*arkaisik_suresi) { digitalWrite(tr_pin, 0); aydinlatma=0; } } |
Saati gösteren fonksiyon
1 2 3 4 5 6 7 8 9 |
void saat_goster(byte x, byte y, byte saat, byte dk){ //x ve y saatin ekrandaki konumu static byte e_dk=0; if (dk != e_dk){ //her dakika ekrandaki saat bilgisini güncelliyor basamak_kaydir(x,y,saat);//10 dan küçük değerlerin başına 0 koyarak yazar lcd.print(":"); basamak_kaydir(x+3,y,dk); e_dk = dk; } } |
Basamak kaydırma
1 2 3 4 5 |
void basamak_kaydir(byte x, byte y, byte dgr){ lcd.setCursor(x,y); if(dgr < 10) lcd.print("0"); lcd.print(dgr); } |
teker fonksiyonu fare tekerinin hareketini kontrol ederek -1, 0 ve +1 değerleri gönderir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int teker(){ static int konum, a; if (konum==enc.read()){ a=0; } else if (konum<enc.read()){ a=1; t=millis(); //Arka ışık sayacını sıfırlar } else if (konum>enc.read()){ a=-1; t=millis(); } konum=enc.read(); return a; } |
yaz fonksiyonu ekranı temizleyip istenilen yazıyı yazar
1 2 3 4 5 6 7 |
void yaz(char* ad){ if (yeni_ekran){ lcd.clear(); lcd.print(ad); yeni_ekran=0; } } |
Saati ayarlayan fonksiyon
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
void saat_ayarla(byte x, byte y){ //x,y ekrandaki konum boolean i=0; ayarli=0; saat=hour();//hour() saat kütüphanesinin fonksiyonu, saat değerini verir dk=minute();//minute() saat kütüphanesinin fonksiyonu, dakika değerini verir while (!ayarli){ if (sol_tus.isPressed()){ i=0; } if (sag_tus.isPressed()){ i=1; } if (orta_tus.uniquePress()){ //ayarlama işlemini bitirir ayarli=1; } switch (i){ //saat ayarı case 0: saat += teker(); if (saat>23 && saat<33) saat=0; //saat değişkenini byte olarak tanımlamıştık if (saat>55) saat=23; //0 dan küçük değer verdiğimizde 255 den başlar yanson(x,y,saat); //değerin ekranda görünüp kaybolmasını sağlar lcd.print(":"); basamak_kaydir(x+3,y,dk); break; //dakika ayarı case 1: dk += teker(); if (dk>59 && dk<77) dk=0; if (dk>77) dk=59; basamak_kaydir(x,y,saat); lcd.print(":"); yanson(x+3,y,dk); break; } } setTime(saat, dk); //ayarladığımız değerlere göre saati ayarlar (saat kütüphanesinin fonksiyonu) } |
yanson fonksiyonu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void yanson(byte x, byte y, byte dgr){ boolean g; byte e_dgr; if(e_dgr!=dgr){ g=1; e_dgr=dgr; } if((millis()/300)%3 == 0){ //yazının 200ms görünüp 100ms kaybolmasını sağlıyor g=0; } else{ g=1; } if(g==0){ lcd.setCursor(x,y); lcd.print(" "); } else{ basamak_kaydir(x,y,dgr); } } |
Ekran ayarlarının olduğu menü fonksiyonu.
Mantığı ana menüyle aynı ana menünün altına yerleştirdiğimiz için alt menü olarak çalışıyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
void ekran(){ switch (em){ case 20: m += -teker(); if (yeni_ekran & em==20){ lcd.clear(); lcd.print("Ekran"); lcd.setCursor(0,1); lcd.print("Ayarlari"); yeni_ekran=0; } if (orta_tus.uniquePress()){ em=1; } break; case 1: em += -teker(); yaz("Kontrast Ayari"); if (orta_tus.uniquePress()){ ayarli=0; } if (sol_tus.uniquePress()){ em = 20; } if (ayarli){ basamak_kaydir(0,1,kontrast); } else{ while(!ayarli){ if (orta_tus.uniquePress()){ ayarli=1; } kontrast += teker(); yanson(0,1,kontrast); kontrast=constrain(kontrast,1,20); analogWrite(10, 140-kontrast*7); } EEPROM.write(kontrast_adres, kontrast); //ayarladığımız kontrast değerini EEPROM a kaydediyor } break; case 2: em += -teker(); yaz("AydinlatmaSuresi"); if (orta_tus.uniquePress()){ ayarli=0; } if (sol_tus.uniquePress()){ em = 20; } if (ayarli){ basamak_kaydir(0,1,arkaisik_suresi); } else{ while(!ayarli){ if (orta_tus.uniquePress()){ ayarli=1; } arkaisik_suresi += 5*teker(); yanson(0,1,arkaisik_suresi); arkaisik_suresi=constrain(arkaisik_suresi,5,60); } EEPROM.write(aydinlatma_adres, arkaisik_suresi); } break; } } |
Paylaşımız için çok teşekkürler. Oldukça net, açıklayıcı ve faydalı bir paylaşım olmuş. Yaklaşık 2 aydır arduino ile uğraşıyorum. Yurtdışından sipariş verdiğim mlz ler henüz elime geçmediği için şimdilik öğrenmek ve mlz lere zarar vermemek adına proteusda simulasyon ile uğraşıyorum. Üzerinde çalıştığım projem için benzer bir menu yapmam gerekiyor. Bredboard için elimdeki mouse un encoderini söksem 3 ad normal buton ile benzer bir menu yapılabilir mi ?
Button sag_tus = Button(8, PULLUP); buradaki “PULLUP” nedir? pullup dirençlerinin değeri falan mı yoksa bir değişken mi olacak ?
Merhabalar, kullanmadığınız mouseden çıkan parçaları bu tarz uygulamalarda kullanabilirsiniz.Button sag_tus = Button(8, PULLUP); kısmında ise arduino üzerinde sabit belirlenmiş olan bir pullup direnci kullanılıyor.
Sayın Yalçın Pak, ilginize çok teşekkür ederim. Programı linkte verilen kütüphaneler ile bir türlü çalıştıramadım. Saygılarımla
Arkadaşlar güzel bir paylaşım yapmışsınız. Bu konuda çok kod inceledim. Fakat çoğunu anlayamadım. Sizin hazırladığınız menü gayet hoş bir şekilde yapılmış ve anlaşılması kolay. Teşekkür ederim. Dört satırlı ekranlar içinde bir kod paylaşırsanız çok sevinirim. Birde bir şey sormak istiyorum : -teker() fonksiyonu önündeki eksi işaretini bazı yerlerde kullanmış bazı yerlerde kullanmamışsınız. Anladığım kadarıyla fonksiyonun geri dönüş değerini ters çeviriyor. Doğrumu? Kısa bir açıklama yaparsanız sevinirim. Selamlar.
Sizin de tahmin ettiğiniz gibi fonksiyondan gelen değerin negatifini almak için…
4 satırlı ekran konusuna gelirsen, bunun için ayrı bir anlatıma gerek yok. Ekran kullanımı konusunda kendinizi biraz daha geliştirirseniz bunu kendi kendinize rahatlıkla yapabilirsiniz. İyi çalışmalar
Mouse yerine Joistik kullanırsak nasıl yaparız?
joystickin verebildiği en yüksek değerleri saptayıp o değerlerde menünün değişmesini sağlayabilirsiniz. Mousede enkoder okuma yerine yapılabilir.
shiftlcd bağlantı sürmek için shift register entegre gerekmiyor mu
Evet, gerekiyor.