Bugünkü makalemde, Wio Terminal’inizi veya herhangi bir TFT Ekranlı Arduino Kartınızı özelleştirilebilir bir mutfak zamanlayıcısına nasıl dönüştürebileceğinizi göstereceğim!
Arduino kodu makalenin sonunda sağlanacak, böylece Wio Terminal’iniz / Arduino’nuz ile hemen kullanmak için olduğu gibi indirebilirsiniz. Ayrıca, kodun farklı bölümlerini de açıklayacağım, böylece yeni başlayanlar kolayca anlayabilir ve ihtiyaçlarına göre uyarlayabilir!

Mutfak Zamanlayıcı Projesine Giriş
Merak ediyorsunuzdur – zamanlayıcının ne anlamı var? Mutfak zamanlayıcıları günümüzde gerçekten de çok uygun fiyatlı değil mi?
Haklısınız! Ama bu sıradan bir mutfak zamanlayıcısı değil.
“Maggie Maker” ile tanışın!
Maggie Maker, bir yemek kitabı / zamanlayıcıdır. Varsayılan olarak, zamanlayıcıyı, adını aldığı gibi, yumurtalı basit bir instant ramen yapmayı gösterecek şekilde programladım (bkz. Wikipedia – Maggi).
İşte özelleştirilebilir zamanlayıcının bazı özellikleri:
- Pişirme için adım adım talimatlar
- Zaman hassasiyeti gerektiren talimatlar için yerleşik zamanlayıcı (örneğin mükemmel yumurtayı haşlamak için!)
- Ana sayfadan açma/kapama alarm ayarı
Bugünkü eğitimi takip ederek, elinizdeki herhangi bir Wio Terminal veya TFT LCD ekranlı Arduino ile bunu 5 dakikadan fazla olmadan çalışır hale getirebilirsiniz! Ayrıca, bu zamanlayıcıyı en sevdiğiniz tarife göre özelleştirebilirsiniz – ve şimdi size nasıl yapacağımı göstereceğim.
Zamanlayıcıyı Nasıl Kullanırım?
Bilgisayar programlama konusunda hiç deneyiminiz olmasa bile, yazdığım kodu kolayca kullanabilirsiniz. Bu adımları takip edin!
Eğer Wio Terminal kullanmıyorsanız…
Kod, 320×240 LCD ekran çözünürlükleri ile çalışacak şekilde yazılmıştır, ancak Wio Terminal dışındaki platformlarda test edilmemiştir. Farklı boyutta bir ekranınız varsa, bazı öğelerin doğru görüntülenmesi için çizimleri ayarlamanız gerekebilir.
Zamanlayıcıyı kontrol etmek için Wio Terminal’in yerleşik buton girişlerini kullanacağız. Eğer başka bir Arduino kartı kullanıyorsanız, tam program işlevselliğinden yararlanmak için en az iki ek butona ihtiyacınız olacak. Ayrıca, Arduino kodunun setup() fonksiyonunda giriş pinlerini yeniden yapılandırmanız gerekecek.
1. Arduino IDE’yi İndirin
Wio Terminal / Arduino kartımızı programlamak için kapsamlı Arduino IDE’yi kullanacağız. Öncelikle işletim sisteminize uygun indirmeyi buradan seçin.
Ardından, kurulum için aşağıdaki talimatları takip edebilirsiniz: Windows / Mac OSX / Linux
2. Zamanlayıcı Kodunu İndirin ve Kütüphaneleri Kurun
Sonraki adımda, GitHub’dan zamanlayıcı kodunu bir bütün klasör olarak indirin. Kodun çalışması için depodaki tüm dosyalara ihtiyacımız olacak.
Eğer Wio Terminal’inizi ilk kez kullanıyorsanız, başlangıç ayarınızı yapmak için Seeed Wiki sayfasını ziyaret edin.
Diğer Arduino kartları için, Arduino’nun Başlarken sayfasını ziyaret edin ve talimatlarınız için sağdaki kaydırılabilir navigasyon panelinden kartınızı seçin.
Bu işlemler tamamlandığında, TFT_eSPI grafik kütüphanesini kurmamız gerekecek. Bu, LCD ekranımıza şeylerin çizilmesini sağlar.
Kütüphaneyi kurmak için, Arduino IDE’de kütüphane yöneticisini açın ve “tft_eSPI” için arama yapın. Kütüphaneyi kurun.
3. Zamanlayıcı Kodunu Özelleştirin
Şimdi eğlenceli kısım. MaggieMaker.ino dosyasını açın ve en alta kadar kaydırın.
Aşağıda gösterilen loop() fonksiyonunu görmelisiniz (veya bunun bir varyasyonunu).

Bunu dijital bir yemek kitabı olarak düşünebilirsiniz. Öncelikle, ön kapak için 0 ve arka kapak için 1 alan cover() fonksiyonuna sahibiz.
Ön kapak() iki ek String girişi ile özelleştirilebilir. Örneğin, “Pankek nasıl yapılır” yazmasını istiyorsanız, şöyle yazmalısınız:
cover(0, “Nasıl Yapılır”, “Pankek Yapın”);
Bunun ardından, sihrin gerçekleştiği yer – page(). page() fonksiyonu, bu sırayla birkaç parametre alır:
- Adım Numarası – Mevcut sayfanın adım numarasını gösterir.
- Başlık – Bu sayfanın ana talimatıdır.
- Süre – Bu adım için zamanlayıcı ne kadar süre çalışmalı? Zamanlayıcıya ihtiyaç yoksa 0 girin (örneğin, malzemeleri hazırlamak veya eklemek için).
- Notlar1 – Notların ilk satırı. Adımı veya ek talimatları tanımlayın.
- Notlar2 – Notların ikinci satırı. Opsiyonel giriş
- Notlar3 – Notların üçüncü satırı. Opsiyonel giriş.
En iyi kısım, istediğiniz kadar sayfa ekleyebilmenizdir, böylece bunu gerçekten her türlü yemek kitabına dönüştürebilirsiniz. Eğlenin!
4. Wio Terminal’e / Arduino’ya Yükleyin
Tarifenizi özelleştirmeyi tamamladıktan sonra, Arduino IDE’deki onay işaretinin yanındaki ok butonuna tıklayarak Wio Terminal’imize veya Arduino kartımıza yüklememiz gerekecek.
Daha fazla bilgi için, lütfen bu sayfadaki Adım 5’e bakın. Bu talimatlar diğer tüm Arduino kartları için de geçerlidir.
Bir hata ile karşılaşırsanız, konsolun ne söylediğine bakın (bu, alttaki siyah penceredir):
Eğer “geçersiz dönüşüm” görüyorsanız…
Bu, yanlış yerde yanlış türde bir girdi girdiğiniz anlamına gelir. page() fonksiyonunun belirli bir sırada 4 zorunlu ve 2 isteğe bağlı girdi aldığını unutmayın! Metin girdileri “…” ile kapsanmalıdır, oysa sayı girdileri düz bir şekilde yazılabilir.
Eğer “beklenen ‘;’ önce” görüyorsanız…
Bu, bir noktalı virgül atladığınız anlamına gelir! Noktalı virgül veya ‘;’ karakteri, satırın sonunu belirtir. IDE, bu sorunla ilişkili satırı vurgulamalıdır, bu nedenle eksik noktalı virgül kolayca bulunabilir.
“`html
Kodunuz başarıyla yüklendiyse ama LCD ekran boşsa …
Bu, yüklediğiniz TFT_eSPI kütüphanesinde bir çakışma olduğu anlamına gelebilir. Sorunu çözmek için, Arduino/Kütüphaneler klasörünüze gidin ve oradaki TFT_eSPI kütüphane klasörünü silin. Kodunuzu yeniden yükleyin ve ekran şimdi çalışmalıdır!
Bu noktadan itibaren uygulamaya geçeceğiz!
Platform Tanıtımı: Wio Terminal
Eğer bu noktaya Wio Terminal olmadan geldiyseniz, tebrikler! Çünkü Arduino kartları, GPIO pinleri dışında hiçbir çevre birimi olmadan oldukça sade gelir, bu nedenle çoğu, hatta tüm donanım yapılandırmalarını kendiniz çözmek zorunda kalmış olabilirsiniz.
Bu nedenle, bu proje için Wio Terminal’i seçtim. Wio Terminal, Arduino ve MicroPython’u destekleyen tamamen entegre bir mikrodenetleyici geliştirme platformudur. Bluetooth, Wi-Fi bağlantısı taşır ve LCD ekran, yerleşik IMU, mikrofon, buzzer, ışık sensörü ve kızılötesi verici ile birlikte gelir.
Tek yapmam gereken, yaygın bir USB Type-C kablosunu takmak ve kodumu yazmaya başlamaktır. Ayrıca, bunu batarya şasisi ile birleştirirsem, zaten ihtiyacım olan mobil mutfak zamanlayıcı form faktörüne sahip olacağım!
Bir Wio Terminal’i Seeed Online Store‘dan alabilirsiniz.
Yemek Tarifi Programı Şeması
Bu bölümde, programlamada kullanılan Arduino kodunu inceleyeceğim. Eğer proje kodunu indirmediyseniz, bunu buradan yapabilirsiniz.
Kodun zamanlayıcının özelliklerini nasıl desteklediğini öğrenebileceksiniz – böylece kendi ihtiyaçlarınıza göre kolayca ayarlamalar yapabilirsiniz!
Ancak, kütüphane sözdizimini ele almayacağım, bu nedenle ilerledikçe belgeleri için aşağıdaki bağlantılara başvurabilirsiniz. Ayrıca, tam Arduino kodunu yanınızda bulundurmak isteyeceksiniz, böylece neyin nereye uyduğunu bilirsiniz!
Tüm Arduino programında 2 ana ‘modül’ vardır – cover() ve page().
Cover()
cover() fonksiyonu iki basit amaca hizmet eder – kapak metnini görüntülemek ve alarm sesinin açılıp kapatılmasına izin vermek.
Öncelikle metni görüntülüyoruz, ardından clicker_state 0 olduğu sürece devam eden bir while döngüsüne giriyoruz. Bu döngüde birden fazla “if” ifadesi var. Temelde, programdan bu butonların sürekli olarak basılı olup olmadığını kontrol etmesini istiyoruz.
while (clicker_state == 0) {
// <<ALARM TOGGLE CODE>>
if (digitalRead(WIO_KEY_C) == LOW) {
// ALARM DEĞİŞTİR
}
// BUTONA BASILDIĞINDA DÖNGÜDEN ÇIK
if (digitalRead(WIO_5S_PRESS) == LOW) {
clicker_state = 1;
delay(500);
alarm_text.deleteSprite();
}
}
İlk koşul alarm_state 0 ve 1 arasında geçiş yapacak ve ses göstergesini buna göre görüntüleyecektir.
// << ALARM DEĞİŞTİR KODU>>
if (digitalRead(WIO_KEY_C) == LOW) {
if (alarm_state == 1) {
alarm_state = 0;
tft.fillRect(300, 0, 50, 50, TFT_BLACK);
delay(500);
} else if (alarm_state == 0) {
alarm_state = 1;
alarm_logo();
delay(500);
}
}
İkinci koşul, ana butona basılmasını bekliyor, bu da clicker_state’i 1 olarak ayarlayacak. Bu, döngüden çıkacak ve fonksiyon sona erecek. Program otomatik olarak bir sonraki fonksiyona geçecektir, bu genellikle page()’dir.
Page()
page() fonksiyonu biraz daha karmaşıktır. Öncelikle şemaya bir göz atalım.
page() çağrıldığında, hemen sayfada görüntülenecek metin için sprite’ları oluşturur, ardından bunları LCD’de görüntülenmek üzere gönderir. Ardından, kullanıcıdan girdi beklediğimiz bir döngüye giriyoruz.
Süre 0 değilse …
Sıfır olmayan bir süre, kullanıcının bu noktada <duration> saniye boyunca zamanlayıcıyı etkinleştirmek istediği anlamına gelir. Zamanlayıcıyı bu Seeed’in Hackster’daki Wio Terminal Zamanlayıcısı‘na referansla oluşturdum.

Zamanlayıcı kodunu detaylı bir şekilde inceleyelim, çünkü ilk bakışta biraz bunaltıcı olabilir.
long start_millis = millis();
int progress, t_min, t_sec;
long seconds_elapsed = 0;
long seconds_remain;
while(seconds_elapsed<duration && clicker_state == 0) {
seconds_elapsed = (millis() - start_millis)/1000;
seconds_remain = duration - seconds_elapsed;
t_min = seconds_remain/60;
t_sec = seconds_remain%60;
ttext.setCursor(0, 0);
ttext.setTextColor(0xFFE0, 0);
ttext.setTextSize(3);
ttext.printf("%02d:%02d", t_min, t_sec);
ttext.pushSprite(220,200);
progress = 200*seconds_elapsed/duration;
tft.fillRoundRect(10, 210, progress, 10, 4, TFT_WHITE);
if (digitalRead(WIO_5S_PRESS) == LOW) {
clicker_state = 1;
skipped_timer = true;
}
}
clicker_state = 0;
Zamanı Tutmak:
- Zamanlayıcıyı başlatmadan önce millis() ile çalışma süresini kontrol edin ve boş ilerleme çubuğunu görüntüleyin.
- Yeni bir millis() çağrısı ile orijinal zaman arasındaki farkı alarak geçen zamanı kontrol etmek için bir while döngüsü oluşturun.
- Clicker_state 1 olduğunda veya zamanlayıcı süresi tamamlandığında zamanlayıcı durur.
while(seconds_elapsed<duration && clicker_state == 0) {
seconds_elapsed = (millis() - start_millis)/1000;
seconds_remain = duration - seconds_elapsed;
if (digitalRead(WIO_5S_PRESS) == LOW) {
clicker_state = 1;
skipped_timer = true;
}
}
clicker_state = 0;
İlerlemeyi Görüntüleme:
- Kalan dakikaları / saniyeleri, kalan saniye sayısının 60’a bölünmesiyle elde edilen bölüm / kalan ile görüntüleyin.
- Tamamlanan zamanın oranını (geçen zaman / süre) ilerleme çubuğu uzunluğu / toplam uzunluk olarak alın. Her döngüde, çubuğun “hareket etmesi” için yeni uzunlukla bir ilerleme çubuğu yeniden çizin.
t_min = seconds_remain/60;
t_sec = seconds_remain%60;
ttext.setCursor(0, 0);
ttext.setTextColor(0xFFE0, 0);
ttext.setTextSize(3);
ttext.printf("%02d:%02d", t_min, t_sec);
ttext.pushSprite(220,200);
progress = 200*seconds_elapsed/duration;
tft.fillRoundRect(10, 210, progress, 10, 4, TFT_WHITE);
Zamanlayıcıyı Atlamak:
Koşullu ifade: Eğer clicker basılırsa, clicker_state’e 1 değeri atayın, böylece bir sonraki yinelemede while döngüsünden çıkılır.
if (digitalRead(WIO_5S_PRESS) == LOW) {
clicker_state = 1;
skipped_timer = true;
}
Alarmı Çalma:
Alarm, süre dolduktan sonra ve alarm_state 1 olduğunda çalar. Öte yandan, eğer zamanlayıcı kesintiye uğradıysa veya alarm_state 0 ise, alarm atlanacaktır.
“`
if (skipped_timer == false && alarm_state == 1) {
alarm();
} else if (skipped_timer == false && alarm_state == 0) {
delay(2000);
} else {
skipped_timer = false;
delay(500);
}
Sonunda, bir sonraki adıma geçmeden önce kullanıcıyı uyarmak için tam bir sayfa gösterilir; burada girdi bekleme işlemi benzer bir while döngüsü ile uygulanır.
Süre 0 ise …
Tam sayfanın farklı bir versiyonu basitçe gösterilir ve kullanıcı hazır olduğunda devam etmek için tıklayabilir.
Arduino Kodu: Dikkat Edilmesi Gerekenler
Grafik Kütüphanesini Kullanma (Çizim, Güncelleme, Silme)
LCD ekran programlamasına yeniyseniz, temel kavramları anlamak için Seeed Wiki’deki bu 5 dakikalık okumayı ziyaret etmenizi öneririm.
LCD & Sprite’ler
TFT_eSPI ile, tanımladığınız LCD sınıfındaki fonksiyonları çağırarak doğrudan ekrana çizebilirsiniz. Ancak, farklı metin boyutları veya renkleri ile nesneler çizmek istiyorsanız, her parametreyi kodunuzda bir satır ile belirtmeniz gerekecek. Ayrıca, aynı nesnenin birden fazla kopyasını görüntülemek istiyorsanız, kod satırlarınızı çoğaltmanız gerekecek, bu da durumu oldukça karmaşık hale getirebilir.
Burada sprite’ler devreye giriyor. Sprite’leri RAM’de saklanan ikincil ekranlar olarak düşünebilirsiniz.
Sprite’ler bir kez yazılabilir ve LCD’ye birden fazla kez itilebilir – her itme için koordinatları tanımlamanız yeterlidir. Her sprite, bellekte kendi tanımlı parametrelerini de saklayacaktır, böylece birden fazla sprite’ı ardışık olarak itmeye çalışırken formatlamamızı yeniden belirtme sorunundan kaçınabiliriz.
Ancak, aynı sprite üzerinde farklı bir metin itmek istiyorsanız, deleteSprite() fonksiyonunu çağırmanız ve sprite’ınızı sıfırdan yeniden çizmeniz gerekecek! Aksi takdirde, yeni metninizin istenildiği gibi görüntülenmediğini görebilirsiniz.
Ekran İçeriğini Silme
Wio Terminal veya Arduino kartları gibi mikrodenetleyicilerle LCD ekranlarla çalışırken, silme fonksiyonunun kullanımını asla görmeyeceksiniz. Bunun yerine, görüntülenen nesneleri arka plan rengi ile örtme sihrini kullanacağız!
Örneğin, arka plan rengi siyah olan tüm ekranımızı silmek istiyorsak, şunu kullanabiliriz:
TFT.fillScreen(TFT_BLACK);
Alternatif olarak, ekranımızın belirli bölümlerini silmek için siyah, dolu dikdörtgenler de çizebiliriz; ekranın altındaki zamanlayıcı bölümünü silmek için yaptığım gibi:
TFT.fillRect(0, 200, 400, 40, TFT_BLACK);
Kompleks sprite’lerle çalışıyorsanız ve dikdörtgen yükü ile silme yapma lüksünüz yoksa, mevcut kod satırlarınızın bir kopyasını oluşturup, elemanların rengini arka plan renginize değiştirebilirsiniz.
Örneğin, alarm simgesi aşağıdaki kod ile çizilir:
void alarm_logo() {
sp.createSprite(12,13);
sp.fillTriangle(5,0,5,13,0,6,0xFFFF);
sp.fillRect(0,4,2,5,0xFFFF);
sp.drawFastVLine(8,5,3,0xFFFF);
sp.drawFastVLine(11,5,3,0xFFFF);
sp.drawFastVLine(10,3,2,0xFFFF);
sp.drawFastVLine(10,8,2,0xFFFF);
sp.drawLine(8,1,10,3,0xFFFF);
sp.drawLine(8,11,10,9,0xFFFF);
sp.drawPixel(7,4,0xFFFF);
sp.drawPixel(7,8,0xFFFF);
sp.pushSprite(300, 5);
}
Bunu silmek için, tüm bileşenleri siyah olarak çizilmiş bir erase_alarm_logo() fonksiyonu oluşturabilir ve ardından aynı koordinatlara itebilirsiniz. Siyah, eski sprite’ımızı tam olarak o piksellerde üzerine yazarak temiz bir şekilde siler!
Engellemeyen Gecikmeler & Durumlar
Paylaşmaya değer bulduğum bir kavram, engellemeyen gecikmeler ve durum kavramıdır.
Bu programda birçok while döngüsü kullandık, ancak bunların hiçbiri ana döngüde delay() fonksiyonunu kullanmıyor!
Mikrodenetleyici programlamasında döngüler içinde gecikme kullanımı genellikle kaçınılması gereken bir durumdur, özellikle de o döngü içinde kullanıcı girişi için “beklemek” istiyorsak.
Problem: Gecikmeler
Diyelim ki, bir kullanıcı bir düğmeye basana kadar her saniyede bir LED’i yanıp söndürmek istiyoruz. Kodumuzu şu şekilde yazabiliriz:
while ( digitalRead(BUTTON_PIN) == LOW ) {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
Problemi görüyor musunuz? ‘Düğmeye basıldı’ durumu yalnızca her döngünün başında kontrol ediliyor!
Genellikle, döngüdeki kod o kadar hızlı çalışır ki bu önemli değildir. Kullanıcı, koşul kontrol edildikten hemen sonra düğmeye bastıysa bile, kontrol hızlı bir şekilde tekrar ortaya çıkacaktır – genellikle düğme bırakılmadan önce bile!
Gecikmelerle, koşulun yalnızca her 2 saniyede bir kontrol edildiği bir anlık süre vardır! Artık bu döngüden çıkmak neredeyse imkansız.
Çözüm: Millis() ve Durum
Gecikme kullanımından kaçınmak için, zamanımızı takip etmek üzere millis() fonksiyonunu kullanacağız. Ayrıca, LED’in mevcut durumunu takip etmek için LED_on değişkenini de kullanacağız.
long currTime = millis();
int LED_on = 0;
Sonra, while döngümüze giriyoruz.
while (button_state == 0) {
if ( (millis() - currTime) > 1000 ) {
currTime = millis();
if (LED_on == 0) {
LED_on = 1;
digitalWrite(LED_PIN, HIGH);
} else {
LED_on = 0;
digitalWrite(LED_PIN, LOW);
}
}
if (digitalRead(BUTTON_PIN) == HIGH) button_state = 1;
}
Bir saniye geçtiğinde, işaretçiyi mevcut millis() çıktısına sıfırlıyoruz. Eğer LED şu anda kapalıysa, onu açacağız ve LED_on durumunu 1 olarak işaretleyeceğiz. Böylece, koşul 1 saniye sonra tekrar tetiklendiğinde, LED kapatılacaktır.
Artık döngümüzde gecikmeler yok ve bunun istediğimiz gibi çok daha tutarlı çalıştığını göreceksiniz! Engellemeyen gecikmeler ve durumlar hakkında daha fazla bilgi edinmek isterseniz, bu sayfayı Arduino Forumlarında ziyaret etmenizi öneririm.
Diğer Grafik Kütüphaneleri
Grafik kütüphaneleri, LCD ekranlarımızda grafik görüntülemek için güçlü kaynaklardır. Bu projede TFT_eSPI kütüphanesini kullandım, ancak LVGL veya LovyanGFX kütüphanelerini de kullanabilirsiniz. Ne çizeceğinize bağlı olarak, bazıları kendi projeleriniz için daha uygun olabilir!
Özet
Uff! Bugün mutfak zamanlayıcı projesine ve bunu Wio Terminal veya Arduino kartınızda LCD ekran ile nasıl kullanabileceğinize baktık. Ayrıca, çok fazla programlama yapmadan nasıl özelleştirebileceğinizi de gösterdim.
Ayrıca, program yapısını derinlemesine inceledik ve Arduino kodunu parçalara ayırdık, böylece zamanlayıcının davranışını kolayca değiştirebilir veya diğer programlarınıza uyarlayabilirsiniz!
Umarım bu eğitim sizin için faydalı olmuştur ve kendi projenizi almanızı teşvik ediyorum – öğrenmenin en iyi yolu gerçekten bu!
Daha fazla Arduino veya Wio Terminal örneği için, buraya tıklayın.
