Arduino ile Seri İletişim – 2


Önceki yazımızda Arduino ile seri iletişimin temellerini ve Arduino ile verileri nasıl göndereceğimizi görmüştük. Şimdi de Arduino’ya nasıl veri gönderebileceğimize bakacağız. Bunun için yine Serial Monitor’ü kullanacağız. Ancak Arduino’ya veri göndermek için elimizdeki tek araç bu değil. Bilgisayarımızda USB üzerinden oluşturulan ve ismi COMx şeklindeki seriporta erişebilen bütün programları Arduino’ya veri göndermek için kullanabiliriz. Seri iletişimdeki temel nokta verilerin baytlar serisi halinde gönderilmesidir. Baytlara bölebildiğiniz bütün verileri Arduino’ya rahatlıkla gönderebilirsiniz.

Serial Monitor ile Arduino’ya Veri Gönderme

Serial Monitor ile Arduino arasında veri alışverişi yapmak için Arduino geliştirme ortamından Serial Monitor butonuna basalım:

 Seria Monitor’ün üst bölümünde bir kutucuk ve sağ tarafta da “Send” butonu bulunuyor. Kutucuğa yazdığımız karakterler Send butonuna basıldığında sağ alt köşede seçilmiş olan hız değerinde Arduino’ya gönderilir. Arduino’dan bu verileri okumak için programımızda da aynı hız değerini kullanmalıyız.

 

Serial Monitor’den gönderdiğimiz veriler daha önce de bahsettiğimiz gibi baytlar halinde gönderilir. Yani kutucuğa “ARDUINO” yazdığımızda bunlar her bir karakterin ASCII karşılığı şeklinde gönderilecektir:

A 65
R  82
D  68
U 85
I  73
N 78
O 79

Bir karakterin ASCII tablosunda sayısal bir karşılığı olduğundan daha önce bahsetmiştik. Karakter dizilerinin desimal sayı karşılıklarını görüntülemek için http://easycalculation.com/ascii-hex.php adresindeki aracı kullanabilirsiniz.

Dolayısıyla Arduino’da

Serial.write(65);
Serial.write(‘A’);

komutları aynı işi yapacaktır. Tek fark birisinde karakterin sayısal karşılığını yazarken diğerinde kendisini yazıyoruz.

Seri iletişim yoluyla Arduino’ya gelen verileri okuma

Arduino’ya seri iletişim üzerinden gelen veriler belirli bir kapasitedeki bellekte (128 bayt) saklanır. Buna “tampon bellek” de denilebilir. Program içerisinde  okunana kadar veriler tampon bellekte tutulur. Bu belleğin kapasitesi sınırlı olduğundan veriler belirli bir süre içerisinde okunmazsa yeni gelen veriler eskisinin üzerine yazılabilir.

Belirli bir anda bellekte okunmayı bekleyen verilerin sayısını Serial.Avaliable() fonksiyonu ile öğrenebiliriz:

Serial.Avaliable() fonksiyonunun döndürdüğü değer sıfırdan farklı ise okunmayı bekleyen veriler var demektir.

Gelen verileri Serial.read() ile okuyabiliriz. Serial.read() fonksiyonu tampon bellekte bekleyen verilerden ilk gelmiş olanı bize verir. Yani tampon belleğe ilk gelen veri ilk okunur. Buna “ilk gelen ilk okunur – first in first out – FIFO) bellek” denilir.

Serial.read() fonksiyonu ile her seferinde bir bayt okunur ve bu bayt tampon bellekten silinir.

Şimdi örnek bir programda bu fonksiyonların kullanımını görelim:

int gelenVeri = 0;   // genel veriyi tutacak değişken
char gelenKarakter;
void setup() {
    // Seri haberleşmeyi başlatıyoruz (9600 bps hızında)
    Serial.begin(9600);
}

void loop() {

        // Veri gelmiş mi?
        if (Serial.available() > 0) {
                // gelen veriyi oku
                gelenVeri = Serial.read();
                gelenKarakter = gelenVeri;
                Serial.print("Gelen Veri: ");
                Serial.println(gelenVeri);
                Serial.print("Gelen Karakter: ");
                Serial.println(gelenKarakter);
        }
}

Programımızı Arduino’ya yükleyip ardından Serial Monitor’ü çalıştıralım. Üst bölümdeki kutucuğa “A” harfi yazıp “Send” butonuna tıkladığımızda Arduino bize aşağıdaki verileri yollayacaktır:

gelenVeri değişkeni int, gelenKarakter değişkeni ise char tipindedir. Serial.Print() ve Serial.Println() fonksiyonları kendilerine verilen parametrelerin cinsine göre çıktı üretmektedirler.

Yazıyla ilgili yorumlarını aşağıda yapabilirsiniz. Bir sonraki yazıda Arduino ile Seri haberleşme işlemlerini nasıl yapacağımızı görmeye devam edeceğiz…

Coşkun Taşdemir

Elektronik mühendisi, gömülü sistemler meraklısı, Arduino kitabı yazarı

28 comments

  1. Yalçın dedi ki:

    Meraba.Serial monitörden ne gönderirsem alttaki hatayı veriyor.Windows xp ve arduino leonardo kullanıyorum.Şimdiden yardımlarınız için teşekkür ediyorum.

    java.io.IOException: Input/output error in writeArray
    at gnu.io.RXTXPort.writeArray(Native Method)
    at gnu.io.RXTXPort$SerialOutputStream.write(RXTXPort.java:1124)
    at processing.app.Serial.write(Serial.java:517)
    at processing.app.Serial.write(Serial.java:540)
    at processing.app.SerialMonitor.send(SerialMonitor.java:200)
    at processing.app.SerialMonitor.access$100(SerialMonitor.java:32)
    at processing.app.SerialMonitor$3.actionPerformed(SerialMonitor.java:89)
    at javax.swing.JTextField.fireActionPerformed(JTextField.java:492)
    at javax.swing.JTextField.postActionEvent(JTextField.java:705)
    at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:820)
    at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
    at javax.swing.JComponent.processKeyBinding(JComponent.java:2851)
    at javax.swing.JComponent.processKeyBindings(JComponent.java:2886)
    at javax.swing.JComponent.processKeyEvent(JComponent.java:2814)
    at java.awt.Component.processEvent(Component.java:6040)
    at java.awt.Container.processEvent(Container.java:2041)
    at java.awt.Component.dispatchEventImpl(Component.java:4630)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:704)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:969)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:841)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:668)
    at java.awt.Component.dispatchEventImpl(Component.java:4502)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Window.dispatchEventImpl(Window.java:2475)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
    java.io.IOException: Input/output error in writeArray
    at gnu.io.RXTXPort.writeArray(Native Method)
    at gnu.io.RXTXPort$SerialOutputStream.write(RXTXPort.java:1124)
    at processing.app.Serial.write(Serial.java:517)
    at processing.app.Serial.write(Serial.java:540)
    at processing.app.SerialMonitor.send(SerialMonitor.java:200)
    at processing.app.SerialMonitor.access$100(SerialMonitor.java:32)
    at processing.app.SerialMonitor$3.actionPerformed(SerialMonitor.java:89)
    at javax.swing.JTextField.fireActionPerformed(JTextField.java:492)
    at javax.swing.JTextField.postActionEvent(JTextField.java:705)
    at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:820)
    at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
    at javax.swing.JComponent.processKeyBinding(JComponent.java:2851)
    at javax.swing.JComponent.processKeyBindings(JComponent.java:2886)
    at javax.swing.JComponent.processKeyEvent(JComponent.java:2814)
    at java.awt.Component.processEvent(Component.java:6040)
    at java.awt.Container.processEvent(Container.java:2041)
    at java.awt.Component.dispatchEventImpl(Component.java:4630)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:704)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:969)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:841)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:668)
    at java.awt.Component.dispatchEventImpl(Component.java:4502)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Window.dispatchEventImpl(Window.java:2475)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

    • Ahmet Alpat dedi ki:

      Compiler hataları genellikle Arduino’yu tanıtamamak ve IDE problemlerinden kaynaklanır. Arduino driverını doğru kurduğunuza emin olun. Aygıt yöneticisinden kontrol edebilirsiniz.

  2. Yalçın dedi ki:

    Cevabınız için teşekkür ediyorum.Ne yaptıysam olmadı.Windows 7 kurdum artık serial monitör kullanabiliyorum.

  3. hamzaoztas dedi ki:

    merabalar ahmet hocam, konuyla biraz alakasız olacak ama bişey sormak istiyorum bi proje için çift taraflı double servo kullanmama gerekiyor, bana önerecebileceğiniz arduino mega ve motor sürücü ile kullanacabileceğim çift taraflı servo varmı acaba? şimdiden teşekkürler..

    • Coşkun Taşdemir dedi ki:

      Sorularınızı forum bölümümüzde sorarsanız daha hızlı cevap alabilirsiniz. Teşekkürler.

  4. Cem dedi ki:

    Çoşkun hocam kitabınız için çok çok teşekkürler, sevgi vede ilgi ile okuyorum. ufak bir sorunum var yukarıda yazdığınız prog u leonardoma yükledim.

    mesela 1 gönderiyorum

    Gelen Veri: 49
    Gelen Karakter: 1

    veya a gönderiyorum
    Gelen Veri: 97
    Gelen Karakter: a

    sonuçları geliyor lakin 65 gönderiyorum

    Gelen Veri: 54
    Gelen Karakter: 6
    Gelen Veri: 53
    Gelen Karakter: 5

    gibi bir sonuç geliyor yani 6 ve 5 i teker teker algılıyor sizce sorun nedir?

    birde yeri bura değil ama sormak istediğim bir konu daha var. serial ekranını arduino çalıştığında açık halde tutmanın bir yolu yokmu, ufak bi program yazdım i=0, delay 1000ms i++ print i gibi, serial ekranını açabildiğimde i çoktan 5 veya 6 olmuş oluyor, serial açıkken resete basıyorum hiçbirşey göstermiyor, yeniden serial ekranını açıp kapamak gerekiyor, void setup kısmına delay koydum 10 sn hani o beklerken ben ekranı açarım diye onuda yemedi varmı bir çözüm? teşekkürler

  5. murat öztürk dedi ki:

    merhabalar ;
    seri haberleşme yazılarınızı okuyarak denemeler yaptım bunun için öncelikli tesekkür ederiö.
    Ama konu ile ilgili bir soru sormak istedim.
    pc den arduinoya gönderdiğim verileri tampon belleğer yazıyor ben bunları pc den 5 tane farklı değer gönderdikten sonra tek satırda sırası ile aynı anda okuyabılırmıyım.

    örneğin a, b,c ,d,e hrflerini ssırası ile arduinoya göndermek ve sonrasında biilgiyi tek satırda a,b,c,d,e olarak görmeni bir yolu varmı

    şididen tesekkur eerım.

  6. Ömer Koman dedi ki:

    bilginin satır olarak gelmesinin seri iletişimle alakası yok seri iletişim programınız a b c d e bilgilerini yollarken arkasından CRLF yani hex 0x13 0x10 karakterlerini yolluyordur bu kodlar terminalde satırbaşıona dön ve bir satır alta geç demektir. yolladığınız komut println ise mutlaka sonuna bu işaretlerini koymuştur ondan satır satır satır görüyorsunuz print komutunda ise bu bilginin sonuna crlf karakterleri konmaz. okuma programınızda bu karakterleri ayıklarsanız satırlar oluşmaz… Serial.print(‘\r\n’); komutu satır atla komutu yollarken Serial.println(‘abc’); komutu abc den sonra otomatik olarak kendi kendine koyar.

  7. hasan şişik dedi ki:

    benimde bi sorum olacak forum da sıkıntı var sanırım giremedim sorum bu konu ile alakalı oldupundan bu konuya yazacam led küp yaptım sıkıntısız çalışıyor fakat bilgisayardan gireceğim bi yazıyı yazdırabilirmiyim yani arduinoya tek tek yüklemeyecem örnek olarak bilgisayardaki textbox’a hasan yazacam led küpte hasan yazacak yani sıkıntım arduino ile pc yi online bağlamak farklı bi yazılım dili ile olursa onuda söylerseniz sevinirim kolay gelsin.

    • Ömer Koman dedi ki:

      sitede c# yazıları var onlardan faydalanabilirsiniz. bilgisayar seri portundan arduinoya c# ile veri yollayıp veri okuyabilirsiniz.

  8. Yasin Arslan dedi ki:

    Kolay gelsin hocam. Arduino ile Raspberry arasında bilgi göndermek istiyorum string gönderemiyorum yardımcı olur musunuz ?

    • Ömer Koman dedi ki:

      foruma gelin. arduinodan bir stingi serialmonitore gondermeyi deneyin arduino içindeki hello orneğini yapın çıktıyı görürseniz arduino rx pini raspi tx pinine ve arduino tx pini raspi rx pinine ve gnd ler hızlar aynı olduktan sonra haberleştirmemenız için sebep kalmıyor.

  9. selman dedi ki:

    Merhabalar benim iki sorum olacak
    ilki ben sensörden aldığım verileri serial monitörüne nasıl yazdırabilirim
    ikincisi aldığım bu verileri farklı bir dosyada tutabilir miyim
    Şimdiden teşekkürler. . .

  10. Ozan ERBASAN dedi ki:

    Hocam iyi akşamlar. Seri port ekranından örneğin “:)” yazınca tetiklenen bir fonksiyonu herhagi bir pinden “hıgh” gelmesine nasıl koşullarız? Yardımlarınız için şimdiden teşekkürler.

    • Ömer Koman dedi ki:

      once bir pini high yapan kodu yazın, daha sonra seriportu okuyan kodu da ekleyin daha sonra bu kodu forumda paylaşın.

  11. Mustafa Şahin dedi ki:

    Merhabalar,
    Şöyle bir soru sormak istiyorum,Bir gsm modül kullanıyorum ve seri port ile iletişim yapıyor. AT komutları ile haberleşme yapılıyor.örn ben AT komutu gönderdiğimde gsm modül OK olarak cevap veriyor.. fakat ben bu OK okumutu arduino ile okumak istediğimde muhtemelen buffer dan dolayı AT OK olarak hem gönderdiğim komutu hemde cevabı aynı anda alıyorum.data 2 yada daha fazla defa yolladığımda ise buffer dolana kadar yazılan tüm dataları okumuş oluyorum. okuma yaparken buffer i temizleme veya farklı bir varmı acaba ?

    • Ömer Koman dedi ki:

      gms ayarlarınızda local echo kapalı/disable olması lazım bununla ılgılı bır komut vardır modemın datasheetıne ve AT komutlarına bır bakın.
      modemler yolladıgınız komutun yanı sıra kendı cevaplarını da döndürür ve “OK” ile sonlandırır bu gelen karakterleri bir dizide biriktirip dönmesi gereken yada beklediğiniz veriyi buffer ıcınde arayarak işlem yapmanızda fayda var.

  12. hakan dedi ki:

    Benim projemde 16 adet cihazdan seri port üzerinden bilgi okumam gerekiyor.
    UNO ile nasıl yaparız?

    • Ömer Koman dedi ki:

      rs485 modul kullanın aynı anda 32 cihaza kadar ve uzun mesafe haberleşebilirsiniz. rs485 protokolu tum cihazların dınlemede oldugu ve her cıhazın mantıkı bır adrese sahip oldugu bır protokoldur. haberleşirken mesajın kımden kıme gıttıgı + mesaj+ mesaj sonu işareti veya mesaj dogruluk sağlama toplamı gibi bır şekılde haberleşebılırsınız.
      ornek
      01 02 aaaaaaaaaaa xx

      01:kimden
      02:kime
      aaaaaaaaaa:mesaj içeriği
      xx: mesaj sonu işareti gibi bir haberleşme yaratabilirsin
      dinlemedeki olan her cihaz mesajın kime kısmını dinleyecek ve kendisi ile ilgili olan mesajı varsa işlem, yapacaktır.

  13. hakan dedi ki:

    Ömer Bey,

    öncelikle cevabınız için teşekkür ederim. rs485 çok mantıklı gözüküyor. Peki fiziksel olarak 16 cihazın arkasından aldığım kabloyu UNO’ya nasıl sonlandırıcam? Buraya nasıl bir devre koymalı?

    • Ömer Koman dedi ki:

      RS485 olarak arama yaparsanız çok kaynak gelecektir.
      rs485 modulu aldıgınızda rx tx kısmını arduınoya bağlayacaksınız modulun çıkışında
      A-B çıkışları olacak tüm A lar ile tüm B ler ortak olacak birde bu ağın en başında veya master olarak çalışan çihazla en uzak yerdeki modulun A-B uçları arasına 120 ohmluk bir sonlandırma direnci mutlaka olmalıdır. tüm ağda toplam 2 direnç olacaktır.

  14. […] MEGA ve Arduino DUE’de daha fazla port yer alıyor. Bu konuyla ilgili başka yazılarımıza buradan ve buradan […]

  15. ahmet dedi ki:

    بِسْــــــــــــــــــــــمِ اﷲِارَّحْمَنِ ارَّحِيم
    öncelikle paylaşımlarınızı için teşekkür ederim. şu anda apartman zil sistemleri de artık seri iletişimi kullanıyor bu cihazların gönderdikleri verileri bilgisayardan veya arduino seri monitörden okumak için bir devre yapmak istiyorum. bu data hattına bir transistör bağlayıp yükseltmem gerekir mi 2400 bauld hızında olduğunu tahmin ediyorum. örnek bir proğram gösterebilir misiniz
    if (Serial.available() > 0) { komutunu tam anlayamadım açabilir misiniz? ilk data biti geldiğinde demek mi oluyor bu.

    • Ömer Koman dedi ki:

      serial port kullanıldıgında ve setup kısmında tanımlandıgında, serıportta bır karakterlik bılgı geldiğinde demek oluyor. ilk data biti demek değil bir karakter.

  16. fuat dedi ki:

    Selamlar Ömer Bey ,
    Arduio nun Com2 sinden sürekli gelen sayısal veriyi okuyorum.
    {1230.12,9999.10,4587.20} gibi. Bu okunan veriyi farklı değişkenlere atayıp Com1 portuna da yazıp okumak istiyorum, {Ch1:1230.12}, {Ch2:9999.10}, {Ch3:4587.20} şeklinde.
    Okuduğum veriyi nasıl yazmalıyım ki, sonrasında pars edebileyim.
    bazı denemeler yaptımsa da olmadı, fikir verebilirsniz memnun olurum.
    iyi çalışmalar.

    • Ömer Koman dedi ki:

      pars için birden fazla veri varsa veriden sonra ayırıcı bir işaret koyun bunu kendiniz belirleyebilirsiniz , ; * gibi şeyler olabilir yani yolladığınız verilerin içinde olmayan bir karakter veya karakterler grubu olabilir, veri grubunun başını da belirlerseniz pars etmeniz ve saymanız daha kolay olur veri başlangıcı içinde $ # ! gibi işaretleri deneyebilirsiniz.
      $ch1,12345.56;ch2,432,10*$ch2,555,66* gibi bir diziyi pars etmeniz daha kolay anlaşılır olabilir.

  17. LALE dedi ki:

    merhaba, hc-05 kullanırken AT komutlarına ulaşmadık. ekrana hiç bir şey basmıyor. Ama rx yanıyor o an. Sizce nasıl bir hata olmuş olabilir?

E-posta adresiniz gösterilmeyecek. Gerekli alanlar * ile işaretlidir.

*



Sosyal Ağlar