Seri haberleşme Arduino ile başka bir cihaz arasında çift yönlü iletişim kurulması demektir. Arduino üzerinde bulunan seri haberleşme ünitesine UART adı verilir. Kullanılan Arduino modeline göre bir veya daha fazla UART terminali bulunabilir. UNO üzerinde 1 adet, MEGA modeli üzerinde 3 adet UART bulunmaktadır. Haberleşme için gönderici pini TX(transmitter), alıcı pini RX(receiver) olarak adlandılır.
UNO üzerinde; TX pini 1, RX pini 0 nolu pinlerdir.
MEGA üzerinde;
TX0 1, RX0 0 nolu pinler,
TX1 18, RX 19 nolu pinler,
TX2 16, RX2 17 nolu pinler,
TX3 14, RX3 15 nolu pinlerdir.
Bu pinlerden istediğiniz çifti haberleşme olarak kullanabilirsiniz.
Seri haberleşmeyi kurmak için ilk yapmamız gereken;
Serial.begin()
Bu komut ile Seri ara birimi kullanmak için hazır hale getirmiş oluruz. Kullanım şekli Serial.begin(baud rate); şeklindedir. Peki baud rate nedir?
Baud Rate
Bu terim haberleşme hızını belirtmektedir. Birimi bps yani saniye başına bit’dir. Her bayt için 10 bit gönderildiğinden, gönderilen bayt miktarı bu değerlerin 10’a bölümüyle bulunur. Örneğin; 9600 bps hızında saniyede en fazla 960 karakter yollanabilir.
Baud rate değerleri olarak; 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 ve 115200 kullanılabilir. Gönderici tarafta baud rate hangisi ise alıcı tarafta aynı değer kullanılmak zorundadır. Aksi halde iletişim sağlanır ancak giden veriler alıcı tarafta yanlış okunur. Standart olarak basit bir iletişim kurup haberleşme yapmak için 9600 bps kullanılır.
1 2 3 4 |
void setup() { Serial.begin(9600); } |
setup() fonksiyonunun içine Serial.begin(9600) yazarak seri ara birim başlatılır.
Veri Gönderme Komutları;
Seri porttan veri göndermek için 2 komut vardır. Serial.print(), Serial.write() komutlarıdır.
Serial.print(“veri”)
Arduino’dan ASCII karakter dizileri göndermek için kullanılır. print() ve println() olmak üzere 2 tip kullanım şekli vardır.
Serial.print(“veri”) –> gönderdiğiniz verileri sade olarak sonuna karakter eklemeden gönderilir. Karşı tarafta alınan veri yan yana gelmiş olur.
Serial.println(“veri”) –> gönderdiğiniz verilerin sonuna ‘\n’ yani enter karakteri eklenir. Buda karşı tarafta alınan verilerin alt alt gelmesini sağlar.
1 2 3 4 5 6 |
Serial.print("Mikro"); Serial.print("Core"); // Çıktı MikroCore Serial.println("Mikro"); Serial.print("Core"); // Çıktı Mikro // (alt satır) Core |
Serial.write(“veri”)
Bu gönderme biçiminde ise veriler ikili formatta gönderilir. İkili formatta gönderim, ASCII formata göre biraz daha farklıdır. Ancak kullanım şekli print ile tamamen aynıdır.
Serial.write(“veri”);
Veri Alma Komutları;
Seri porttan veri almak için serial sınıfının read komutu kullanılır.
Serial.read()
Arduino içerisindeki seri porttan gelen veriler bayt bayt alındıktan sonra seri haberleşme için ayrılmış olan tampon bellek bölgesine yazılır. Programa gelen veriyi okumak içinde Serial.read() fonksiyonu ile tampon bellek okunur. Okunduğu anda tampon bellek silinir.
1 2 3 |
String gelen = ""; gelen = String(Serial.read()); Serial.print(gelen); |
Basit olarak bu program gelen adında içeriği boş olan bir String değişken tanımlanmıştır. Serial portdan veriler bayt olarak okunur, atayacağımız değişken String olduğu için gelen verinin String türüne dönüştürülmesi gerekir. String(Serial.read()) komutu ile gelen bayt veriler String türüne dönüştürülüp gelen değişkenine atanmıştır. Serial.print(gelen) komutu ile ekrana yazdırılmaktadır.
Seri portdan “abc” verisi gönderildiğini varsayalım. Arduino veriyi okuduğu anda ekrana yan yana 979899 yazmaktadır. Peki gelen veri “abc” de Arduino niye bunu 979899 olarak yazdırdı?. Çünkü gelen veriler ASCII formatda gelmektedir. Arduino bunu okuyup dönüşüm yapmadan direk ekrana yazdırdı. Bunun için gelen ASCII verinin karakter tipine dönüştürülmesi lazım ki gelen veri okunabilir olsun. Dönüştürme char(veri) komutu ile yapılır.
1 2 3 |
String gelen = ""; gelen = String(char(Serial.read())); Serial.print(gelen); |
Program bu şekilde düzeltilirse ekranda “abc” çıktısı okunabilir.
Serial.available()
Bu komut tampon bellekte bulunan okunmamış verilerin saysını döndürür. Bellekte veri yok ise 0 dönderir. Tampon bellek boyutu sınırlı olduğu için gelen veriler belirli bir zaman aralığında okunmalıdır. Aksi takdirde gelen veriler eskilerin üzerine yazılır.
Genel kullanım şekli;
1 2 3 4 |
if (Serial.available() > 0) { karakter = Serial.read(); } |
Veri geldiyse gelen verinin uzunluğu kadar tampon boyutu artar. Koşulda 0’dan büyük olduğu için gelen veri karakter değişkenine atanır.
Denetleyici yoğun bir iş yapıyorsa ve veri belirsiz zamanlarda geliyorsa veriyi okumak için veri geldi mi diye sürekli kontrol etmesi gerekir. Buda programın yavaşlamasına sebep olur. Bunu engellemek için Arduino üzerindeki ATMEGA328 entegresinin donanımsal seri port kesmesi vardır. Kesme demek programa dışarıdan bir sinyal geldiği zaman o anda yürütülen programı durdurur ve gidip sinyali okur. İşi bittikten sonra hemen programa kaldığı yerden devam eder. Bu kesme programın akışının bozulmamasını ve sürekli olarak bir işi denetlemekten kurtarır.
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 |
String veri = ""; boolean durum = false; void setup() { Serial.begin(9600); } void loop() { if (durum) { Serial.print(veri); veri = ""; durum = false; } } void serialEvent() { while (Serial.available()) { char gelen = char(Serial.read()); veri += gelen; if (gelen == '\n') { durum = true; } } } |
Programda gelen veriyi tutması için veri adında içeriği boş olan bir String değişken ve çıktı olarak sürekli veri göndermemesi için durum adında bir kontrol değişkeni vardır. Arduino’ya dışarıdan veri geldiği anda kesme oluşur ve program direk olarak serialEvent() fonksiyonunu çağırır. Program fonksiyon içine girerek tamponu kontrol eder veri geldiği için tampon 0’dan büyük olmuş olur. Bayt tipinde gelen veriler okunabilmesi için karakter tipine dönüştürülür ve veri değişkenine yan yana dizilir. Veri gönderiminin bittiğini belirtmek için dışarıdan gelen verinin sonuna yeni satır yani ‘\n’ karakteri eklenmesi gerekir. Aksi takdirde verinin bitip bitmediğini anlayamadığımız için gelen veriyi ana fonksiyona gönderemeyiz. Veri bittiğini anladığı anda durum adlı değişken true yapılır. Program kesmeden çıkarak kaldığı loop fonksiyonuna gider. Durum değişkeni olumlu olduğu için koşul içine girer ve print ile gelen veri seri port ekranına çıktı olarak yazılır. veri içeriğinin temizlenmesinin nedeni yeni gelen veri tekrar veri değişkenine yazılacağı için veriler üst üste biner ve hataya sebep olur. If koşulundan çıkmak için durum değeri false yapılır ve yeni veri gelene kadar program kaldığı yerden devam eder.
Biraz karışık gibi gözükebilir ancak çoğu zaman bu seri port kesmesi hayat kurtarır. Seri haberleşme içeren her program da kesinlikle kullanırım. Detaylı bilgi almak isterseniz mail atabilirsiniz.
TEŞEKKÜRLER
Wow! that guide has been awfully practical thanks alot : ). “Ignorant men don’t know what good they hold in their hands until they’ve flung it away.” by Sophocles..