28

Arayüz Üzerinden Python ile Arduino Haberleştirme

Bu yazıda Python ile yazdığım basit bir arayüz üzerinden Arduinoya(veya herhangi bir mikrodenetleyiciye) veri göndererek 4 adet ledi yakıp söndürme işleminden bahsedeceğim. Basit bir uygulama olsun diye sadece led yakıp söndürme işlemi yaptım. Ama farklı uygulamalarda yapılabilir.

Öncelikle Python tarafı daha  zor olduğu için anlatmaya oradan başlıyorum. Arayüz için Pythonda Pyqt5 modülünü kullanarak aşağıdaki basit bir arayüz yapmaya çalıştım. Bu arayüz üzerine COM port ve Baudrate hızını seçebilmek için iki adet “combobox” yerleştirilmiştir. Ayrıca seriport üzerinden bağlantı sağlayabilmek  ve gerektiğinde bağlantıyı kesebilmek için ve ledleri yakıp söndürebilmek için “pushbutton” lar eklenmiştir.

Arduino-Python Haberleşmesi

Arayüz ile seri port üzerinden veri göndermek veri almaya göre daha basit. Programın veri alma işlemini yapabilmesi için sürekli olarak seriportu dinlemesi gerekir. Bu dinlemeyi ise sonsuz bir döngü oluşturarak yapamıyoruz maalesef. Çünkü arayüz sınıfının içerisinde bir yerde sonsuz döngü kullanıldığı zaman arayüzde hiç bir şey görünmüyor. Peki seriporttan gelen verileri nasıl arayüze dahil edeceğiz. Bunun için yine Pyqt5 modülünün sınıflarından biri olan Qthread kullanılmıştır. Qthread basitçe belirlenen bir kaynaktan bir sinyal geldiğinde bunu programın algılaması işlemini yapıyor. Bir nevi RTOS daki task oluşturma işlemi diyebiliriz. Arayüz çalışırken aynı anda arkaplanda seriport dinlenmektedir. Qthread işlemi için ayrı bir “SerialThreadClass” isminde bir sınıf tanımlanmıştır.

Bu class içersinde sürekli olarak seriport dinlenmekte ve bir mesaj geldiğinde arayüz sınıfının içerisinde başka bir fonksiyona program dallanmaktadır. Bu fonksiyon içerisinde de gelen mesaj arayüzdeki “gelen mesaj” kısmında ekrana yazdırılmaktadır.

Arduinoya veri göndermek için arayüz sınıfının içerisinde “leds” isimli bir fonksiyon oluşturulmuştur. Led butonlarından hangisine tıklanırsa tıklansın program bu fonksiyonun içine girer daha sonra hangi butona tıklandığı belirlenir ve arduinoya karakter olarak bir sayı gönderilir.

Arduino Kodları

Arduino tarafında 8,9,10,11 nolu pinlere ledler bağlanmıştır. Serial.begin(9600) ile baudrate ayarı seçilmiştir. Arayüz tarafında da baudrate ayarının aynı olması gerekmektedir. Arayüzden 1 ile 8 arası karakterlerler gelmektedir. Bu karakterlere göre ledler yakılıp söndürülmüştür.

Python Kodlarının Tamamı

Yazının başında da dediğim gibi bu projede sadece led yakıp söndürdüm. Siz istediğiniz bir uygulamayı yapabilirsiniz. Eğer sormak istediğiniz sorular var ise yorumlarda sormaktan çekinmeyin. Vakit buldukça yorumlarınızı cevaplayacağım. Ayrıca bu uygulamanın acemice çekilmiş videosunu aşağıda bulabilirsiniz. Başka bir yazıda görüşmek üzere.

Herkese iyi çalışmalar..

Mehmet Topuz

28 Comments

  1. Merhabalar Mehmet Bey,
    Öncelikle proje örneklerinizi paylaştığınız için teşekkür ederim. PyQt kütüphanesi ile arayüz yapıyorum. Yaptığım basit bir devrenin akım ve voltajını sensörler yardımıyla ölçüp Arduino aracılığıyla Python’a aktarıyorum. İki ayrı messageBox’a voltaj ve akım olarak volt ve amper değerlerini yazdırma konusunda sıkıntı yaşıyorum. Yardımcı olabilir misiniz?

    • Merhaba
      Bu sorun birçok sebepten kaynaklanabilir.
      1. Serialden veri okuyabilmeniz için Qthread kullanmanız gerek. Yukarıdaki kodlarda “serialThreadClass” isimli sınıfı inceleyebilirsiniz.
      2. Baud rate ayarları tutmuyor olabilir. Arduino ile Python baudrate ayarı aynı olmalı.Yoksa arduino bilgisayara veri göndermez.
      Bu saydıklarımda hata yok ise kodlarınızı https://paste.ubuntu.com/
      Sitesine kopyalayın sonra linkini tekrar bu yoruma yazın kodları bir inceleyeyim.

  2. https://paste.ubuntu.com/p/DYb47MsZNB/

    Aslında sizin arayüzünüzde değişikler yapıp ek olarak diğer messageBox’lar oluşturup onlara veri çekme işlemini yaptım. Bu kod bilgisayarımda sorunsuz şekilde verileri çekip yazdırıyor fakat raspberry pi üzerinde çalıştırdığımda ise veri çekme esnasında hata veriyor. Hata da def run(): fonksiyonunda gösteriyor. Araştırma yapmama rağmen açıkçası pek kaynak bulamadım bu hata ile ilgili.

    Yorumuma geri döndüğünüz için çok teşekkür ederim 😀

    • Rica ederim. Bir faydam dokunduysa ne mutlu bana.
      Öncelikle run() fonksiyonunun içindeki print(“HATA\n”) satırını silip pass yazıp bir daha deneyin. Raspberry pi da konsola yazı yazdırmada hata veriyor olabilir. Ayrıca hata mesajını görebiliyorsanız yoruma yazarsanız sevinirim.

      • Raspberry’de python kodlarını çalıştırabileceğim 3 yer bulunuyor.
        -Python3 IDLE’da çalıştırdığımda arayüz ekranı geldi ama veri alamadım.
        -CMD’den yaptığıms no module named PyQt5 hatası verdi
        -Thonny Python’dan denediğimde ise yine arayüz ekranı geldi fakat bağlan butonuna tıkladığımda;
        Fatal Python error:Aborted
        Current thread 0x69d9a470(most recent call first):
        Thread 0x76efe010 (most recent call first):
        File “/home/pi/Desktop/urban yeni/pyqt.py”, line 179 in

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 588 in execute_source

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 427 in _execute_source_ex

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 374 in _execute_file

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 155 in _cmd_Run

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 119 in handle_command

        File “/usr/lib/python3/dist-packages/thonny/shared/thonny/backend.py”, line 97 in mainloop

        File “/usr/lib/python3/dist-packages/thonny/shared/backend_launcher.py”, line 41 in

        Hatasını aldım

        • Hata Qthread’ tan kaynaklı gibi görünüyor ama çözümü nedir bilmiyorum. Eğer aynı kod bilgisayarda çalışıyorsa sorun raspberry tarafında olmalı diye düşünüyorum. Python dosyaları eksik yüklenmiş olabilir.

          • Kütüphaneleri yeniden yüklemeyi deneyeceğim. Vakit ayırdığınız için teşekkür ederim. İyi günler dilerim.

    • Merhaba paşlaşinlariniz icin cok tesekkur ederiz. Ben trafik levhalarini taniyabilen otonom bir araç gelistiriyorum. Makine ogrenmesi ile web cam den trafik isaretlerini taniyabiliyor. Ama bunh arduinoya nasil aktaracagimi bilmiyorum.bir oneriniz var mi

      • Merhaba, Rica ederim.
        Öncelikle makine öğrenmesi ve webcam işlemlerini nasıl bir ortamda yapıyosunuz. Bilgisayar mı yoksa gömülü linux koşturan bir kart mı?(raspberry pi, beaglebone vb.). Eğer raspberry falan kullanıyorsanız neden bir daha arduinoya ihtiyaç duydunuz? Tam olarak projenizde elektronik olarak hangi ekipmanlar var biraz daha açık bahsedebilir misiniz?

  3. Hocam öncelikle emeğinize sağlık çok güzel bir çalışma olmuş. Benim bir sorum olacak. Bu python ekranında butona tıklama yerine klavye tuşlarıyla aynı işlemi nasıl yapabiliriz? Mesela birtanede başlat butonu ekleyip, Bağlan dedikten sonra Başlat butonuna tıkladıktan sonra 1′ e bastığımızda led1 yansın, 2′ ye bastığımızda led1 sönsün. Klavyeden değer gönderme işini fonksiyon altında bir türlü yapamadım. Program kilitlenip kalıyor. Yardımcı olabilirseniz sevinirim iyi günler iyi çalışmalar

    • Yanlış anlamadıysam klavyeden hangi tuşa basıldığını algılayabiliyorsun. Başlat butonuna bastıktan sonra arayüz kodlarında sonsuz döngü kullanıyorsan programı kitler. Böyle döngüleri thread’ler içine kullanman gerek. Eğer kodları paylaşmanda sakınca yok ise bana https://paste.ubuntu.com/ sitesine kodları yazıp linki gönderebilirsin.

  4. Merhaba kolay gelsin ben kendi çapımda bir proje yapıyorum fakat bir sorunla karşılaştım. Proje ekranın sağ altındaki rengi algılayıp arduinoya 0 ile 255 arasında değer gönderiyor. Arduinoda bunu aynı şekilde alıp o rengi yakıyor bunda sorun yok. Fakat şöyle bir sorun var Arduinoya gönderdiğim bilgi çok yavaş gidiyor, yani Kırmızı renk 255 iken arduino 2 saniye sonra kırmızı rengi yakıyor bunu nasıl çözebilirim ?

    • Merhaba, burada sorun python tarafından mı kaynaklanıyor yoksa arduino tarafından mı belirmeniz gerek. Bilgisayardan giden verileri usb-ttl ile seri port ekranından izlemenizi tavsiye ederim. Eğer veriler geç geliyorsa sorun python tarafındadır. Tam sorunu bulabilmek için kodları incelemem lazım. Kodları bana https://pastebin.ubuntu.com/ sitesine kopyalayıp yorum olarak veya mail olarak gönderebilriseniz bir incelerim.

      • https://pastebin.ubuntu.com/p/BzN9JTZMKJ/
        Arduino tarafındada normal olarak mesajları alan ve analogWrite olarak yazmayı düşünüyorum siz kodunuzda digitalWrite kullanmıştınız analogWrite ve digitalWrite ile alakası olabilirmi bu gecikmenin ?(Arduino kodunda herhangi bir delay yok)

        • Bu kodda window_capture() fonksiyonunda gecikme kullanmasanda içinde kullandığın fonksiyonlar sebebi ile gecikme yaşanıyor olabilir. 67. satırdaki time.sleep(0.5) kodunu kaldırıp deneyin veya fonksiyon içine girdiğiniz değeri düşürün. Ayrıca recursive fonksiyonların belli bir limiti vardır. Bu kod bir süre sonra runtime error verir. Tavsiyem recursive fonksiyon yerine sonsuz döngü kullanmanız.

        • Serial.readString() fonksiyonunun bir timeout süresi varmış. Yani bir string okumak için belli bir süre bekliyor. Sorun buradan kaynaklanıyor olabilir. Bu fonksiyon yerine Serial.readBytesUntil() fonksiyonu ile deneyin. Bu fonksiyon belli bir karakteri görene kadar okur(enter karakteri gibi). Python tarafında da gönderdiğiniz string’in sonuna enter karakteri eklemeniz gerek veya hangi karakteri görünce okumayı durdursun istiyorsanız onu ekleyebilirsiniz.
          https://www.arduino.cc/reference/tr/language/functions/communication/serial/readbytesuntil/

  5. Merhaba, önecelikle emeğinize sağlık çok öğretici bir içerik olmuş.
    Ben aynı kodu çalıştırmak istediğim zaman -“import serial
    ModuleNotFoundError: No module named ‘serial””- hatası alıyorum, nedeni nedir acaba, yardımcı olabilir misiniz?

    • Merhaba, serial modülü bilgisayarınızda olmayabilir. İndirmek için komut satırına “pip install serial” yazıp indirebilirsiniz.

  6. Tasarladığım Qt arayüz programı üzerinde sayfalar arası geçiş yapmak için veya scrollbar’ı aktif etmek için butona tıkladığımda arayüz kapanıyor. Bu problemi nasıl çözebilirim?

    • Öncelikle hatanın nereden kaynaklandığını bulmak gerek. Bunun için debug altında çalıştırın ve programın kapandığı yerde konsol çıktısını inceleyin. Çalışma esnasında bir hata olduğunda program hemen kapanır. Bu hatalar programlarken IDE tarafından algılanamayabilir. Bu yüzden bu tarz kapanmalar olduğunda debug altında çalıştırır ve hatanın kaynağını bulmaya çalışırım.

  7. Merhaba Mehmet Bey
    Arduino’ya ESP32 CAM bağlayıp oradan aldığımız görüntüyü aynı bu projedeki gibi arayüz tasarlayıp görüntüyü de o arayüzde gösterebilir miyiz ?

    • Merhaba Emirhan,

      Bahsettiğin gibi yapılabilir. Hatta Arduinoya gerek kalmadan ESP32 ile wifi üzerinden de gönderebilirsiniz. Arduino ile gönderecekseniz seri port üzerinden göndermek çok yavaş kalabilir. Bunun yerine bilgisayara ethernet üzerinden veya başka bir protokol ile göndermek daha hızlı olacaktır. Arayüz tarafında ise Pyqt5 veya C++ ile Qt framework kullanarak yapılabilir. Bence ESP32 var ise görüntüyü wifi üzerinden göndermek daha iyi bir çözüm olacaktır. Tabi wifi ile gönderimde de gecikmeler olabilir.

  8. Merhaba,
    Ben adafruit gps’i arduino’ya bağladım. Aldığım gps verileri ile otonom araca ilerleme komutu vereceğim. Bu kodu arduino example üzerinden mi yazmam gerekiyor, visual studio code’da python üzerinden mi yazmam gerekiyor? Yardımcı olabilirseniz sevinirim.

    • Merhaba,
      Otonom işleri işlem kapasitesi gerektiren işler. Bu yüzden arduino yetersiz kalır. Tavsiyem otonom tarafını bilgisayarda yazıp arduinoya sadece yön ve hız gibi komutlar göndermeniz. Hangi programlama dilini kullanacağınız hakkında birşey diyemem. Böyle bir çalışmam olmadı daha önce. Ben böyle bir çalışma yapsaydım dediğim gibi yüksek işlem gerektiren kısımları bilgisayar tarafında yapardım.

  9. Merhaba hocam içerik için teşekkürler, ben bir soru soracaktım. Arduino üzerinde takılı olan bir buton ile pyqt tasarımı üzerindeki bir butonu bağlayabilir miyim ? Yani arayüz ile tıkladığım butonda başlattığım bir işlem var. Bu işlem arayüzde ve aynı zamanda arduino butonuna tıklandığında yapılmalı. Yani ikisi de aynı işlevi görecek ekrandaki tasarımda butona tıklanırsa veya arduinoya bağlı butona tıklanırsa aynı threadi başlatmak istiyorum. Ben arduino buton kontrolünü while döngüsü ile beklediğim zaman arayüz yüklenmesine geçmiyor doğal olarak while içinde kalıyorum. Bunu Pyqt5 signal tarzında bir bağlantı ile Pyqt5 ve arduino butonu bağlantısı yapabilir miyim ?

    • Merhaba Emrullah,
      Arayüzde buton kontrolünü while döngüsü içinde yapamazsın bunun için thread oluşturman gerekebilir fakat ben olsam söyle yapardım. Zaten serial için çalışan bir thread’in var. Arduino tarafında butona basıldığında arayüze bir paket gönderebilirsin serial threadi içinde bu paketi yakalayıp, arayüzde butuna tıklandığında hangi fonksiyonu çağırmak istiyorsan bu paket yakalanınca çağırabilirsin. Yine aynı şekilde arayüzdeki butona tıklandığında bir signal slot mekanizması ile çağrılan fonksiyon içerisinde arduinoya bir paket gönderebilirsin. Arduino tarafında bu paketi okuyup ona göre işlemler yapabilirsin. Böyle bir yöntem uygulanabilir gibi. Belki daha iyi bir yolu vardır bilemiyorum.

      • farklı bir thread açarak sinyal bekleyip sürekli olarak bu işlemi çözdüm. Cevabınız için teşekkür ederim. Fakat böyle yaptığımda buton için delay koymam gerekti çünkü ard arda bir kaç kere işlem başlatılıyor butonda küçük sürelerde elimizi tuttuğumuz zaman, bu sefer de 1 saniyeden fazla butonda basılı kaldığımızda yine birden çok başlatılıyor işlem.

Mehmet Topuz için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak.