Arduino ile STONE LCD Kullanımı

Merhaba,

Bu konuda STONE marka LCD ekranların Arduino ile nasıl kullanıldığına değineceğiz. LCD’ nin resmi sayfasına bağlantıdan ulaşabilirsiniz. Bu ekranlar aynı Nextion ekranlarda olduğu gibi mikrodenetleyici ile UART yada RS232 üzerinden haberleşirler. Bir kıyaslama yapacak olursam Nextion ekrana göre bazı artıları ve eksileri bulunmakta. Bana göre en büyük eksisi editöründe dahili bir simülatör bulundurmaması. Simülatör olması özellikle animasyonların ve widget’ ların test edilmesinin hızlandıran bir özellik. Üretici firma henüz bu özelliği editöre eklememiş ancak belki gelecekte ekler. Bunun dışında ikinci bir eksi LCD’ nin programlanmasının seri haberleşme ile yapılamıyor olması olabilir. Bu özellikle Linux yada Windows tabanlı sistemler ile ekranı kullanırken sisteme müdahale etmeden uzaktan online güncelleme imkanı sağlamakta. Artılarına değinecek olursam STONE ekran modülü daha fazla widget’ a sahip. Kutu içeriği olarak daha zengin. Adresleme mantığı ile çalışıyor olması ve arka plansız bitmap destekliyor olması ise hoşuma giden en güzel özellikleri olabilir. Ayrıca ilk izlenimlerime göre STONE LCD’ nin haberleşmesi Nexiton’ a göre daha verimli çalışıyor. Nextion ekrana hızlı veri gönderirken aynı anda butonlara basmaya çalışmak soruna sebep olabiliyordu. STONE LCD’ de bu şekilde bir sorun ile karşılaşmadım. Ancak ücret olarak STONE marka ekranlar, Nextion ekran’ dan biraz daha fazla. Bu yüzden hobi amaçlı uygulamalar için Nextion daha iyi bir tercih olabilir.

Şimdi gelelim ekranın daha detaylı incelenmesine. Kutu içeriğinde gelen Flash Bellek içerisinde ihtiyacınız olan örnek uygulamalar, videolar ve gerekli programlar mevcut. Size gelen kutu içeriğinde olmaması yada daha güncel sürümlerini aramanız durumunda bağlantıdan gerekli birçok şeye ulaşabilirsiniz. “20191019-TOOL 2019” ismi ile belirtilmiş bağlantıdan ekran tasarımı için gerekli uygulamayı edinebilirsiniz. (İlerleyen tarihlerde bu isim değişmiş olabilir.) Uygulama açıldığında aşağıdaki gibi bir görüntü oluşur.

main_image_stone

Resimde de görüldüğü üzere çok karmaşık olmayan bir arayüze sahip. Kırmızı ile gösterilen kısım her uygulamada dosya ve düzen kısımları kısımları. Bunların hakkında fazla detaya inmeyeceğim. Turuncu olan kısımda en soldaki anahtar sembollü olan “screen configuration” butonu ekran ile alakalı ayarları içerdiğinden biraz önemli. Bu butona bastığınızda şu şekilde bir ekran karşınıza çıkacaktır.

stone_config

Bu ayar ekranı ile seri port haberleşme hızı ve seri port ile haberleşirken başlangıç byte’ larını belirleyebilirsiniz. Seri port haberleşme hızı hepimizin bildiği baud rate ayarı. Haberleşmenin düzgün şekilde olması için kullandığımız mikrodenetleyici yada host bilgisayar ile bu hızın aynı olması gerekir. R3 ve RA olarak belirtilen seri port frame buffer high ve low değerleri ise ekran üzerinde herhangi bir butona bastığınızda ekranın size göndereceği ilk değerler. Bu durum aynı şekilde siz ekrana bir şey gönderirken de mevcut. Örnek verecek olursam editörü kullanarak yaptığınız tasarımı ekrana yükleyip ekran üzerindeki seri port haberleşme özelliği olan bir widget’ i kullandığınızda seri port üzerinden “0xA5 0x5A 0x82 …” şeklinde bir veri göreceksiniz. Burada yine önemli bir nokta olarak, seri porttan gelen bu veriler ASCII karakter değildirler. Byte veridir. Bu yüzden Arduino seri port ekranı gibi sadece ASCII değer gösteren seri port arayüz uygulamaları ile bu değerleri görmeniz mümkün değildir. Size tavsiyem SSCOM yada REALTERM gibi bir uygulama kullanmanızdır. Yine bu ekran üzerinde “parameter configuration” başlığı altında ekran üzerindeki değişkenlerin başlangıç değerlerini sıfır yapabilirsiniz. Yada sol altta bulunan checkbox’  ı işaretleyerek ekrana her dokunmanızda ses çıkaran buzzer’ ı pasif hale getirebilirsiniz. Bunların yanı sıra yine önemli bir özellik olan “Boot page” değerini doğru girmek önemlidir. Orada şu an “0” değeri yazılır. Yani bu ekranın bir önceki resimde de görebileceğiniz soldaki “Pictures” kısmında bulunan “0” ismi ile başlayan resmi kullanarak  açılacağı anlamına gelir. Eğer bunu doğru girmezseniz ekrana güç verdiğinizde ekranda sadece bir hata kodu görürsünüz. Bu hata kodlarının anlamını içeren bir doküman henüz bulamadım. Eğer bulabilirsem bunu da sizinle paylaşacağım.

Bu kısmı hallettikten sonra gelelim “screen configuration” butonun iki sağındaki buton olan “Generate Configuration File” butonuna. Bu buton editörde yapılan tasarımı kullanarak ekrana yüklenebilir bir dosya üretir. Bunu yaparken küçük bir derleme işlemi yapar ve tasarımınızda herhangi bir hata olup olmadığını size söyler. Tasarımda yada ayarlarda yaptığınız herhangi bir değişikliğin ekrana yüklenebilir hale gelmesi için bu butona basmanız gerekir. Bu butona basmanız halinde proje dosyasının olduğu yere “VT_SET” isimli bir klasör oluşacaktır. Oluşturulan bu klasör içerisinde LCD’ ye yüklenmesi gereken tasarım dosyaları mevcuttur. Bu dosyaları ekrana yüklemenin iki yolu var. İlki bu klasörü komple bir USB belleğe takmak. İkincisi ise bir USB kablosu yardımıyla LCD’ ye bağlanmak. Ben hızlı hızlı deneme yapmak için bu yöntemi kullanıyorum. İlk tasarım aşamasında size de bu yöntemi öneririm. USB kablosu takılı iken ekrana tasarım yüklemek için “Generate Configuration File” butonun iki sağındaki “Download Online” butonuna basabilirsiniz. 

Şimdi sıra geldi tasarım kısmına. Bu kısımda daha önce kullandığımız Nextion ekran için yaptığımız tasarımı kullanacağım. Sadece 3. bir sayfa daha ekleyerek bir gauge widget’ ı da ekledim. İlk olarak proje oluşturalım. Bunun için “File” menüsü altındaki “New Project” butonuna basmalıyız. Açılan pencerede elinizdeki ekrana ait özellikleri seçmelisiniz. Aynı zamanda proje konumu ve proje ismini de bu ekranda belirleyebilirsiniz. 

stone_new_project

Öncelikle projemizde hem sayfaları hem de arka planı oluşturan resimleri ekleyelim. Bunun için en üstteki resimde görülen mor kısımdaki “Picture File” kısmına sağ tıklayıp “Add” seçeneğine tıklamalısınız. Böylece eklemek istediğiniz resimleri projenize eklemelisiniz. Dosya isimleriniz 1,2,3 gibi olması proje içerisindeki resim seçimlerinizi kolaylaştıracaktır. Projenin ilerleyen adımlarında bir resmi değiştirmek isterseniz resmin üzerinde sağ tıklayıp “Replace” de diyebilirsiniz. Ancak projeye eklediğiniz resimlerin çözünürlüğünün ekran çözünürlüğünü geçmemesine özen gösteriniz. Aksi taktirde hatalar ile karşılaşabilirsiniz. Benim oluşturduğum projedeki resimlerin görünümü aşağıdaki şekildedir.

stone_pictures

Daha sonra widget eklemeye bakalım. En üstteki resimde görülen yeşil ve sarı ile işaretli kutuların içerisindeki araçlar widget eklemeye yarayan araçlar. Tasarım editöründe birden fazla buton çeşidi mevcut. Her butonun farklı farklı amacı var. Yeşil kısımda en solda bulunan “Button” olarak geçen araç en basit buton ve sayfalar arası geçiş gibi temel işlemlerde kullanıma uygun. Bu editörde de Nextion Editör’ de olduğu gibi butona basılma efekti bulunmakta. Efekti kullanmak için buton eklediğinizde yada widget’ ın üzerine tıkladığınızda solda çıkan “Button effect” kısmına basıldığında hangi resmi kullanacağını girmelisiniz. Böylece üzerine bastığınızda o resmi kırpar ve üstte gösterir. Yeri gelmişken yine bahsetmekte fayda var. Bu editörlerde butona basılma efekti oluşturulabilmesi için aynı arka plan iki farklı şekilde yüklenir. İlk resimde butonların basılmamış normal hali bulunur. İkinci resimde ise butona basıldığında butonun görünmesini istenen şekli koyulur. Böylece buton özelliklerden ikinci resim seçilip her butona basılmasında diğer resimdeki butonun gösterilmesi sağlanabilir.

 stone_button

Yukarıdaki resim’ de bu ayarların editör üzerinde nasıl yapılacağı görülmekte.  Diğer ayarlarına daha fazla değinmeyeceğim. Bu buton tipi sadece sayfalar arası geçiş gibi basit işlemler için kullanıldığından çok fazla ayara sahip değil. Şimdi kullanacağımız buton’ da ise Arduino’ ya komut gönderip LED yakıp söndürme gerçekleştireceğiz. Önceki butondan farklı olarak bu buton hafızada bir adrese sahip. Siz butona bastığınızda bu adres bilgisini UART üzerinden gönderir. Alıcı tarafta ise gelen adres değerine bakarak hangi butona basıldığını anlayabilirsiniz. Bu butonu eklemek için ilk resimdeki yeşil alanda soldan ikinci “Return pressed key value” isimli aracı alıyoruz. Önceki buton’ da olduğu gibi tasarımda buton olmasını istediğimiz yer kapsayacak şekilde bir alan seçince resmin o kısmına buton özelliği vermiş olduk.  

stone_lcd_buttons

stone_button_variable

Resimde de görüldüğü üzere ben butona “16A1” numaralı bir adres verdim. Bu numara hexadecimal olup 16 bitliktir. Yani en fazla 0xFFFF şeklinde bir adres verebilirsiniz. Bir üstteki ekran tasarımının olduğu görüntüde 2 çeşit buton görülmekte. Yeşil olan “Button2” yani normal buton iken, sarı olanlar “Button key value return*” olarak isimlendirilmiş. Bu butonlar adrese sahip olan butonlar ve onlara tıkladığımızda UART üzerinde sahip olduğu adres değerini gönderecektir. 

İlk sayfayı bu şekilde basit olarak hallettik. İkinci sayfada textbox ve bir switch buton kullanalım. Switch buton Nextion ekrandan farklı olarak kullanımı biraz daha karmaşık. Karmaşık olmasının sebebi switch button için kullandığımız widget aynı anda farklı işlemlere de yarıyor olmasından. Biz diğer özelliklerini kullanamayacak olsak da gerekli ayarlamaları yapmamız gerekli. Diğer sayfanın görünümü aşağıdaki gibidir. 

stone_lcd_page2

Resimde de görüldüğü üzere switch butonun resminin olduğu kısımda “Incremental adjustmen0” isimli bir widget kullanılmış. Bu tek başına switch butonu işlevini gerçekleştirmek için yeterli değil. Onun altında birde “Variable Icon” mevcut. İlk widget üzerine tıklandığında bir sayacı arttırırken ikinci buton ise yeni değere göre icon değişme işlemini gerçekleştirecek. Bunu yapabilmesi için iki widget’ in de adresi aynı olmalı. Aynı butonda olduğu gibi bu araçların da bizim atadığımız adres değerleri var. Bu iki aracın özellikleri aşağıdaki resimde mevcuttur.

stone_inc_var

Soldaki resim “Incremental adjustmen0”, sağdaki resim ise “Variable Icon” un özelliklerine ait resimlerdir. Yukarıdaki resimde de görüldüğü gibi iki widget için de adres değeri “1992” olarak belirlenmiştir. İki widget’ ın da alt ve üst limitleri 0 ve 1 olacak şekilde ayarlandı ve soldaki widget’ ta her basılmada değerini 1 arttırması için “++” seçildi. Üst limiti daha fazla yaparak progressbar vb. tool’ lar yapmanız mümkündür. Progressbar yaparken o widget’ a ait farklı yüzde dilimlerindeki halinin görüntülerini kayıt etmeniz gerekecektir. Bizim yapacağımız switch’ de sadece açık ve kapalı olduğundan iki duruma ait görüntüleri kayıt etmek yeterli olacaktır. Son olarak icon dosyası. Burada önemli bir detay mevcut. Benim kullandığım ekran default olarak “png” vb arka planı olmayan resim desteklememekte. Ancak herhangi bir icon dosyasını arka planı siyah olacak şekilde buraya yüklerseniz siyah olan kısımları silip sadece icon’ un kendisi görünecek şekilde bırakacaktır. Güzel ve kullanışlı bir özellik olduğundan belirtmek istedim. Icon dosyalarına isim verirken “0,1,2,3..” gibi isimler kullanmanız switch yada progressbar tasarımı gibi işlemlerde işlerinizi kolaylaştıracaktır.

Text widget’ i için herhangi bir karmaşık durum bulunmamakta. Sadece veri gönderirken gönderdiğiniz text’ in uzunluğu önemli olacaktır. Text widget’ ının özellikleri açık ve anlaşılır. Bu kısımdan sıra geldi 3. ve son sayfaya. 3. sayfada bir gösterge kullandım ve Arduino kullanarak ölçtüğüm ADC değerini bu gösterge üzerinde göstereceğim. Tasarladığım 3. sayfanın ekran görüntüsü aşağıda mevcuttur.

stone_gauge

Resimde de görüldüğü gibi bir “Rotate Icon” ve “Data Variable” widget’ larını kullandım. Gösterge arka planı ise resim olarak arka plan üzerine photoshop kullanarak eklenmiştir. Yani ek bir widget kullanmadan butonda olduğu gibi resime eklenmiştir. Burada “Rotate Icon” widget’ ının bazı ayarları bulunmakta. Bu widget’ ın özelliklerinin bulunduğu resim aşağıda bulunmaktadır. Bu özellikler arasında “Icon Rotation Center” en önemli özellik. Döndürmek istediğiniz Icon görselini “Icon File” ile seçtikten sonra “Icon Rotation Center” kısmına tıklıyoruz. Açılan sayfada seçtiğimiz icon’ un resmi çıkacak. Bu resimde Icon’ un dönme merkezini seçmeliyiz. Böylece gelen değere göre icon o merkez etrafında dönecektir. Bu noktada yine ince bir detay olarak, tasarladığınız icon resmini 0 derecede nasıl durmasını istiyorsanız o şekilde kayıt etmelisiniz. Böylece 0 dereceyi deneyerek ayarlamak zorunda kalmazsınız. Yani icon’ u eklediğinizde nasıl durmasını istiyorsanız o şekilde kayıt edin.

stone_rotate_icon

Hemen alttaki data variable ise kullanımı basit bir widget. Herhangi bir ek ayar gerektirmiyor sadece özelliklerden kaç tane rakam yanyana göstermesi gerekiyorsa onu seçebilirsiniz. Bu kısımdan sonra donanım kısmına geldik. Donanım kısmı için gerekli bağlantıda kullandığınız LCD’ nin haberleşme protokolü oldukça önemli. Benim kullandığım model RS232 kullanarak dışarı ile haberleşmekte. O yüzden Doğrudan Arduino yada benzeri bir mikrodenetleyiciye bağlamak çok mümkün değil. Aslında RS232 uart’ dan çok farklı bir haberleşme değil. Ancak kullandığı gerilim seviyesi UART’ a göre oldukça yüksek seviyelere çıkmakta. Bu yüzden araya gerilim seviyesini değiştirmek için MAX232 entegresi yada onun işlevini yapan bir devre gerekli. Benim elimde MAX232 olmadığı için aşağıdaki bağlantı şemasını kullanarak sorunumu çözdüm. Elinizde MAX232 yoksa sorununuzu sizde bu şekilde çözebilirsiniz.

Resimde de görüldüğü üzere kurulan devre sadece lojik seviyeleri değiştirmek için gereklidir. Yani Arduino’ dan çıkan 5V gerilimi 12V’ a yükseltmek ve LCD’ den çıkan 12V gerilimi 5V’ a düşürmek için bu devreye ihtiyaç duyduk. Aslında MAX232 devresi de bundan çok farklı bir işlem yapmıyor. Devrede kullanılan Transistörler NPN olup soldan sağa doğru Emitter, Base ve Collector şeklinde pin yapısına sahiptir. Potansiyometrenin göstergeyi hareket ettirmek için olduğunu söylemiştik. Diğer 3 LED ise butonlar ile kullanım içindir. Bağlantı şemasını da verdiğimizi göre sıra geldi yazılım kısmına. Yazılım kısmı sadece seri iletişim ve data ayırma içermekte. Bu yüzden üstteki kısımlar kadar karmaşık değil. Yazılım kısmında dikkat edilmesi gereken en önemli şey veri formatı. STONE LCD’ lerin kullandığı veri formatı aşağıdaki gibidir.

[ Header1, Header2, Paket uzunluğu, Veri Tipi, Adres 1, Adres 2, Veri Uzunluğu, Veri1, Veri2 ]

  • Header1: Screen Parameter ekranında yazan Seri Haberleşme 16 Bit Header’ ın ilk kısmı
  • Header2: Screen Parameter ekranında yazan Seri Haberleşme 16 Bit Header’ ın ikinci kısmı
  • Paket Uzunluğu: Gönderdiğiniz yada aldığınız verinin uzunluğu. Eğer veri gönderiyorsanız, gönderdiğiniz veri uzunluğunu sayıp bu değere yazmalısınız.
  • Veri Tipi: Ekran kullanım kılavuzunda yazan komutun ne işe yaradığını gösteren kısım. Komutun yaptığı işe göre 0x80 ile 0x83 arasında değerler alabilir.
  • Adres 1: Ekran üzerindeki widget’ ların adreslerinin 16 bitlik olduğunu söylemiştik. Bu adres değerinin ilk 8 bitlik kısmı
  • Adres 2: Widget’ ın 8 bitlik ikinci kısmı
  • Veri Uzunluğu: Bu kısımdan sonra gelen verinin 16 bitlik paket olarak uzunluğu
  • Veri 1: Gönderilen yada alınan 16 bitlik olarak iletilmekte. Bu 16 bitlik verinin ilk kısmı
  • Veri 2: 16 bitlik verinin ikinci kısmı

 Bu veri formatı hem gönderirken hemde veri alırken gerçerlidir. Ancak bazı istisnalar bulunmakta. Örneğin veri kısmı eğer yazı gönderiyorsanız 16 bitlik değil, 8 bitlik dizi şeklinde olacaktır. Çünkü ASCII tablosundaki tüm değerler 8 bitlik bu yüzden de 16 bitlik veri göndermeye gerek yoktur. 

Yazılımda ekrandan veri aldığımız kısmı ilk olarak şu şekilde oluşturdum. Bu kısımda buffer’ da veri var mı diye kontrol ediyoruz. Eğer veri varsa bu seferde gelen verileri sırası ile kontrol edip formata uygun mu yani paketin başı mı diye kontrol ediyoruz. 

if (displaySerial.available())          //check Serial Port buffer
  {
    if (readSerialByte() == 0xA5)         //Check first data is 0xA5
    {
      if (readSerialByte() == 0x5A)       //Check second data is 0x5A
      {
        uint8_t dataLen = readSerialByte();       //Read packetlen from first byte
        uint8_t sendCmd = readSerialByte();       //read cmd from second byte
        uint16_t dataAdr = (readSerialByte() << 8) |        //read and merge 16 bit data from buffer
                           readSerialByte();

        uint8_t valLen = readSerialByte();        //dataLen get
        uint16_t mVal = 0;
        for (int i = 0; i < valLen * 2; i++)      //get all data from buffer with loop
        {
          mVal = mVal << 8;
          mVal |= readSerialByte();
        }

        parseCMD(dataAdr, mVal);                //toggle LED with incoming data
        Serial.print(dataLen);                  //debug values
        Serial.print(" ");
        Serial.print(dataAdr, HEX);
        Serial.print(" ");
        Serial.println(mVal);
      }
    }

  }

Yukarıdaki kod bloğunda geçen parseCMD fonksiyonu ayrılmış veriye göre işlem yapılmasını sağlayan fonksiyondur. Yani ekranda basılan butona göre hangi LED’ in yanacağına karar verdiğimiz kısım bu fonksiyon içerisinde yapılmıştır. Fonksiyon içerisinde bulunan switch-case ile basılan butonun adresine bakılarak işlem yapılmıştır.

void parseCMD(uint16_t mAdr, uint16_t mData)
{
  switch (mAdr)                  //check which button pressed with memory adress value
  {
    case 0x16A1:                //button1 adress
      digitalWrite(led2, !digitalRead(led2));
      break;
    case 0x16A2:                //button2 adress
      digitalWrite(led3, !digitalRead(led3));
      break;
    case 0x1992:                //switch adress
      digitalWrite(led1, mData);
      if(mData)                 //send string value according to switch status
      {
        displaySerial.write(arrOn, 15);       //send array on string value
      }else{
        displaySerial.write(arrOff, 15);      //send array off string value
      }
      break;
  }
}

Son olarak da göstergenin değerini değişmek için potansiyometre verisini okuyup seri porttan gönderelim. Bu kısımda dikkat edilmesi gereken nokta ADC verisinin 10 bitlik olmasıdır. UART ise iletişimi byte kullanarak gerçekleştirir. Bu yüzden ADC verisini iki byte bölerek göndermeliyiz. 

if (millis() - lastTime > 100)            //send data with 100 ms interval
  {
    adcVal = analogRead(A0);                  //read adc value
    adcVal = map(adcVal, 0, 1023, 0, 380);    //change ADC value limit to 0-380
    uint8_t sendValL = adcVal & 0xFF;         //get adc value LSB
    uint8_t sendValM = (adcVal & 0xFF00) >> 8;    //get ADC value MSB
    arr[6] = sendValM;
    arr[7] = sendValL;
    displaySerial.write(arr, 8);            //send adc value with Serial port
    lastTime = millis();
  }

Oldukça uzun bir konu oldu. Elimden geldiğince her şeyi anlatmaya çalıştım. 

Bu konuda kullandığım ekranın üreticisi olan Stoneitech şirketine, ekranı inceleyebilmem için gönderdiği için teşekkürler.

https://www.stoneitech.com/

Yazılımın tamamına bağlantıdan ulaşabilirsiniz.

One Comment

Add a Comment

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