Linux - Seri Port İletişimi

Başlatan canavaroski90, 28 Şubat 2012 - 19:56:34

« önceki - sonraki »

0 Üyeler ve 2 Ziyaretçi konuyu incelemekte.

canavaroski90

Herkese merhabalar. Basitçe Linux altında c++ diliyle ve seri port ile çalışabileceğim bir kütüphane arıyorum. Bana gereken fonksiyonlar;

- Seri port aç/kapat
- Seri portta veri var mı, varsa kaç byte bilgisi (SERİ PORT BUFFERINI BOŞALTMADAN SADECE GELEN BİLGİ BOYUTUNU ÖĞRENMEK İSTİYORUM!)
- Seri porttan veri oku (istenilen boyut kadar)
- Seri porta veri yaz

Böyle bir kütüphanenin varlığı hakkında bilgisi olan?

sem

".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?


canavaroski90

Alıntı yapılan: sem0900 - 28 Şubat 2012 - 21:26:22
Yani genel girdi çıktı işlmleri...

http://tldp.org/HOWTO/IO-Port-Programming.html

Hocam dediğiniz siteyi inceledim ancak orada standart Read, Write, Open, Close komutları bulunmakta. Aslında elimde zaten böyle bir seri port kullanımı mevcut ancak bana asıl gerekli olan

- BytesToRead fonksiyonu.

Bu fonksiyon çağırıldığı zaman, eğer seri porta veri gelmişse kaç byte veri olduğunu bana döndürecek, ancak seri porttan okuma yapmayacak Çünkü seri porttan okuma yapılınca seri port bufferındaki veriler silinmekte. Sadece bana kaç byte veri beklediğini söyleyecek. Bunu bulamadım..

Alıntı yapılan: Ozmo - 28 Şubat 2012 - 23:40:37
http://www.vanemery.com/Linux/Serial/serial-console.html
http://mutasyon.net/makaleoku.asp?id=118


Hocam dediğiniz siteleri de inceledim buralarda da ihtiyacım olan fonksiyonu bulamadım..

sem

Biraz bakındım, bahsettiğiniz fonksiyon C# için gözüküyor. Port programlama ile uğraşmadım ama C ile uğraştığım kadarı ile doğrudan böyle hazır fonksiyonlar olmayabilir. Yani gelmiş olan veriyi siz hesaplamak zorunda kalabilirsiniz.

Araştırmak gerekirse şurası kolay bir yer olabilir, araştırma ctrl f ile yapılabilir en azından.

http://www.easysw.com/~mike/serial/serial.html


pdf olarak bulmak için Google'da şu aramayı yazmanız yeterli;

Serial Programming Guide for POSIX filetype:pdf
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

canavaroski90

Yine kaldım cahilliğimle başbaşa desenize :))

Teşekkür ederim cevap için.

travego0403

Baştan söyleyeyim tecrübeli bir sistem programcısı değilim. Sadece mantık yürütüyorum. Bu aralar boş kaldığımda biraz biraz ilgileniyorum.
-Seri portu open() sistem çağrısıyla açtınız.(Sadece okumak için)Tıpkı bir dosya gibi, Linuxta hemen hemen her şey dosya muamelesi görür.
-Veriyi read() sistem çağrısıyla okudunuz. Ayrıca read çağrısı kaç byte veri okunduğunu da geri döndürür.

Şimdi siz diyorsunuz ki veriyi okuduğum zaman tampondan siliniyor. Acaba silinme değilde dosya offset dediğimiz(Türkçesi nedir bilmiyorum.) dosya içerisinde gezdiğimiz bir yer gösterici, okuduğumuz tamponun sonunda konumlanmış halde kalmaz mı? Eğer böyle ise lseek() sistem çağrısıyla bu offseti tamponun başına çekebiliriz.
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

canavaroski90

Madem konuyu derinleştirdiniz, bende biraz açıklamada bulunayım.

Biz bir proje üzerinde çalışan öğrenci 2 arkadaşız. Projede ARM mimarisi kullanan bir işlemciyi üzerinde bulunduran, üzerinde Linux işletim sistemi kerneli yüklenmiş bir donanım kullanmaktayız. Ama feci tecrübesiziz. Peki ne yapıyoruz?

Bir PIC vericiden, bir kablosuz modül yardımıyla veri gönderiyorum, arkadaşımda verileri alıcı bir kablosuz modül yardımıyla alıp ARM kartımızda işlemekte. Ben işin Linux tarafına yeni yeni ısınıyorum.  Şu an bu kablosuz ağ modülü ile bağlantı kütüphaneleri hazırlamakla meşgulüm bilgisayar tarafında. Ben C# bildiğim için, C#'ta istediğimiz iletişim protokolünü sağlamak için kütüphaneler hazırlıyorum, arkadaşa veriyorum, o da karta C++'da gömmeye çalışıyor :)

İş elektronik boyutuna girince biraz olaylar değişiyor. En büyük sıkıntıyı bahsettiğim noktada yaşamaktayız. Portu read ediyoruz, hooop bufferdaki veriler uçtu.. Yani dediğiniz gibi bir seek() fonksiyonu bulabilir miyiz?... Açıkçası pek emin değilim :) (ya da bulsak da bize ne kadar zamana mal olur, kullanabilir miyiz vs..)

Hikayenin özeti bu. Aslında işimiz sadece Linux ile değil. Bir de elektronik boyutu var. Ancak aklıma yeni gelen bir konu var ki, acaba bir UART interrupt mevcut değil midir? (Donanımsal ya da Linux tarafında?)

- Eğer donanım tarafında varsa, bunu bulmak zaten bizim işimiz. Sizin bilginizin olmasını bekleyemem.
- Eğer yazılım tarafında böyle bir kesme varsa, biliyorsanız, bilgi verebilir misiniz?

sem

travego'nun dediği gibi read edebiliyorsanız lseek de işe yarayabilir. Ya da bir tampon oluştursanız o şekilde olmuyor mu işler? Kaynak sıkıntısından dolayı mı buffer kullanmıyorsunuz. read edip okuyabiliyorsanız veriler elinizde olmuş oluyor, yanlış mı anlıyorum?
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

travego0403

Ben sizin bir kart üzerinde degilde bilgisayarda çalıştığınızı düşünmüştüm. Ayrıca Linux API lerini kullandığınızı sanmıştım.(Belki bu API lerin kullandığı glibc kütüphanesi ordada mevcuttur ya da derlenebilir.) Malum başlık C/C++ bölümünde :)
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

canavaroski90

Alıntı yapılan: travego0403 - 29 Şubat 2012 - 22:34:58
Ben sizin bir kart üzerinde degilde bilgisayarda çalıştığınızı düşünmüştüm. Ayrıca Linux API lerini kullandığınızı sanmıştım.(Belki bu API lerin kullandığı glibc kütüphanesi ordada mevcuttur ya da derlenebilir.) Malum başlık C/C++ bölümünde :)

travego0403 hocam (özür dilerim, isminizi bilmiyorum) kusuruma bakmayın, başka konuyu açacak uygun başlık bulamadım :)

Alıntı yapılan: sem0900 - 29 Şubat 2012 - 21:55:48
travego'nun dediği gibi read edebiliyorsanız lseek de işe yarayabilir. Ya da bir tampon oluştursanız o şekilde olmuyor mu işler? Kaynak sıkıntısından dolayı mı buffer kullanmıyorsunuz. read edip okuyabiliyorsanız veriler elinizde olmuş oluyor, yanlış mı anlıyorum?

sem0900 (sizden de özür dilerim, sizin de isminizi bilmiyorum) hocam, dediğim gibi Linux'a daha yeni ısınıyorum. Kartın detaylı donanım bilgisine de henüz hakim değilim. Iseek() gibi bir fonksiyon varsa, ben readbytes(3) dedikten sonra, imlecimi 3 byte geriye kaydırıp tekrar okutma yapabiliyorsam, bu zaten bana istediğimi verir. Ancak arkadaşımın bu kadar bilgisi var mı bilemiyorum, ben de elimde donanım vs. olmadığı için en ufak bir deneme yapamıyorum (ki zaten bilgisizlikten ötürü yapmam da zor :) ) Sorduğunuz soruya gelirsem, "read edip okuyabiliyorsanız veriler elinizde olmuş oluyor, yanlış mı anlıyorum?", ben neden BytesToRead gibi bir fonksiyon arayışı içerisindeyim, onu açıklayayım.

Bizden proje kapsamında istenen bir iletişim protokolü oluşturup, bu protokolde abartılı miktarlarda veri akışını sağlıklı bir şekilde sağlayabilmek. Biz de sağdan soldan biraz iletişim protokollerini araştırıp bir sistem ürettik kendimize. İşte bu:

Başlangıç Byte'ı  + Verinin Uzunluğu + Adres Bilgisi + User Data + CheckSum

Şimdi, ben bu yapının kendisine "1 FRAME" diyorum. Her frame başlangıç byte'ı ile başlamak zorunda, veri uzunluğu o frame de kaç byte veri olduğunu söyleyen bilgi, User data benim karşıya göndermek istediğim data. Gerisi klasik adres ve checksum.

Diyelimki 10 frame yolluyorum karşıya. Ancak user data uzunlukları FARKLI. Yani frameler hiç bir zaman eşit uzunlukta olmuyor. Ben seri port için bir buffer ayarlayabiliyorum. Gelen veriler bu bufferda birikiyor. Oku dediğim zaman, arkadaşımın gösterdiği fonksiyon, bizim belirlediğimiz bir diziye, belirlediğimiz uzunlukta, belirlediğimiz porttan veri okuyor. Ve okuyup diziye attığı her byte'ı bufferdan siliyor.

Şimdi işin bu kısmı benim için çile. Çünkü örneğin 100 byte okuttuğum zaman ne gibi sıkıntılarım oluyor onu söyleyeyim;
- Kaç adet frame geldi hesaplamam vakit alıyor.
- Her frame'i ayırıp, boyutlarını öğrenip, içerisinden user dataları çekmek ayrı sıkıntı.
- Son gelen frame eksik mi geldi tam mı geldi belirlemek sıkıntı. Ayrıca eğer eksik geldiyse onun için son frame'i alıp, yeni bir diziye atayıp, tekrar seri portu kontrol edip, diğer başlangıç byte'ına kadar okutup, okuttuğum verileri birleştirip, user datayı ayırmam gerek. Ölüm..

Eğer ben portta kaç byte veri geldiğini portu OKUMADAN bilebilirsem (yani tamponu/bufferı silmeden), başlangıç byteını ve veri uzunluğu bilgisini okuttuktan sonra işime yarayacak kadar bilgi okutacağım. Sonra tekrar seri portu check et. Çok daha basit ve hızlı bir yöntem.

Ancak C#'taki SerialPort nesnesinin sahip olduğu BytesToRead fonksiyonunun eksik oluşu (ya da benim ARM ile uğraşan arkadaşımın şimdilik bilemeyişi) sebebiyle işkenceye mağruz kalmaktayım :)

Umarım anlatabildim derdimi. 

sem

Merhabalar, öncelikle isimler nedeni ile özür dilemenize gerek yok  =)

Bu kadar ayrıntı iyi olmuş. Ne hakkında konuştuğumuzu bilirsek, öneriler faraziden o orandakayıyor olacak. Öncelikle C kodluyorsanız lseek komutu zaten bulunacaktır, travego0403 ün dediği gibi C kütüphanesi bulunuyor bildiğim kadarı ile gömülü linuxlarda da... Ki bulunmasa garip olurdu diye düşünüyorum. Yine çok emin, bilir kişi gibi konuşmayayım. Hiç bulaşmadığım bir alan çünkü.

Bahsettiğiniz sorunların tümü ise C'ye ya da gömülü linuxa özgü sorunlar değil. Doğrudan bir protokol oluşturma sorunu. Önerim öncelikle şu olacak; gömülü (embded) linux,  port programlama gibi şeyleri şimdilik bir kenara bırakmanız.

Bahsettiğiniz protokolü  TCP üzerinde denemeniz. Çünkü C ile TCP uygulaması yazarken de bahsettiğiniz sorunların tümü mevcut, tüm veriler gönderildi mi? ne kadar veri okundu? Ne kadar veri gelecek? vs.. Bunlar TCP üzerinde gidermiş olursanız bu TCP üzerinde uğraştığınız prototopi port programlamaya entegre edebilirsiniz.

Okunacak boyut; boyut - sizeof(int) kadar da belirlenebilir. sizeof(int) kadar alanda ise paket uzunluğunu tutarsanız zaten okuyacağınız miktarı biliyor olursunuz. Sonuç olarak C#'ta bu şekilde bir yol ile içsel olarak hallediyordur olayı. Tümü okuyup lseek çekmek de iyi bir deneme olabilir, performansa bakmak lazım, birinci yol daha hızlı olacaktır.

Sonuç olarak TCP önerisini tekrarlayacağım. TCP protokolü belli evet fakat C ile yazdığnızda tüm paketin gidip gitmediğinin kontrolü de yine programcıya kalıyor. Büyük ihtimalle C#'ta sendall ya da writeall gibi bir fonksyion ile hallediliyordur yine bu işlem, yani sınıf içsel olarak hallediyordur Python'da olduğu gibi. Fakat C'de bu gibi işlemlerde programcıya iş düşüyor. Şu an Linux, port programlama vs uğraştığınız tüm birimler aşina olmadığınız birimler. O nedenle sıkıntı olduğunda nerede olduğunu bulmak zor olacaktır. Ama önce prototipin çalıştığını daha hızlı test edebileceğiniz ve kaynağın daha fazla olduğu bir ortamda test ederseniz proje de hızlanacaktır diye düşünüyorum. Ayrıca yardım almanız da bu aşamada çok daha kolay olur. Protopi gerçeklerken de herşeyin çalıştığından ve nasıl olduğundan emin oldğunuz için sorunun aranacak olduğu alan azalmış oluyor. Örneğin lseek var mı yok mu ikilemine düşmezsiniz, bunu gidermek bile güzel bir ilerleme olabilir.

Kolay gelsin...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

canavaroski90

Alıntı yapılan: sem0900 - 01 Mart 2012 - 00:18:36
Merhabalar, öncelikle isimler nedeni ile özür dilemenize gerek yok  =)

Bu kadar ayrıntı iyi olmuş. Ne hakkında konuştuğumuzu bilirsek, öneriler faraziden o orandakayıyor olacak. Öncelikle C kodluyorsanız lseek komutu zaten bulunacaktır, travego0403 ün dediği gibi C kütüphanesi bulunuyor bildiğim kadarı ile gömülü linuxlarda da... Ki bulunmasa garip olurdu diye düşünüyorum. Yine çok emin, bilir kişi gibi konuşmayayım. Hiç bulaşmadığım bir alan çünkü.

Bahsettiğiniz sorunların tümü ise C'ye ya da gömülü linuxa özgü sorunlar değil. Doğrudan bir protokol oluşturma sorunu. Önerim öncelikle şu olacak; gömülü (embded) linux,  port programlama gibi şeyleri şimdilik bir kenara bırakmanız.

Bahsettiğiniz protokolü  TCP üzerinde denemeniz. Çünkü C ile TCP uygulaması yazarken de bahsettiğiniz sorunların tümü mevcut, tüm veriler gönderildi mi? ne kadar veri okundu? Ne kadar veri gelecek? vs.. Bunlar TCP üzerinde gidermiş olursanız bu TCP üzerinde uğraştığınız prototopi port programlamaya entegre edebilirsiniz.

Okunacak boyut; boyut - sizeof(int) kadar da belirlenebilir. sizeof(int) kadar alanda ise paket uzunluğunu tutarsanız zaten okuyacağınız miktarı biliyor olursunuz. Sonuç olarak C#'ta bu şekilde bir yol ile içsel olarak hallediyordur olayı. Tümü okuyup lseek çekmek de iyi bir deneme olabilir, performansa bakmak lazım, birinci yol daha hızlı olacaktır.

Sonuç olarak TCP önerisini tekrarlayacağım. TCP protokolü belli evet fakat C ile yazdığnızda tüm paketin gidip gitmediğinin kontrolü de yine programcıya kalıyor. Büyük ihtimalle C#'ta sendall ya da writeall gibi bir fonksyion ile hallediliyordur yine bu işlem, yani sınıf içsel olarak hallediyordur Python'da olduğu gibi. Fakat C'de bu gibi işlemlerde programcıya iş düşüyor. Şu an Linux, port programlama vs uğraştığınız tüm birimler aşina olmadığınız birimler. O nedenle sıkıntı olduğunda nerede olduğunu bulmak zor olacaktır. Ama önce prototipin çalıştığını daha hızlı test edebileceğiniz ve kaynağın daha fazla olduğu bir ortamda test ederseniz proje de hızlanacaktır diye düşünüyorum. Ayrıca yardım almanız da bu aşamada çok daha kolay olur. Protopi gerçeklerken de herşeyin çalıştığından ve nasıl olduğundan emin oldğunuz için sorunun aranacak olduğu alan azalmış oluyor. Örneğin lseek var mı yok mu ikilemine düşmezsiniz, bunu gidermek bile güzel bir ilerleme olabilir.

Kolay gelsin...

sem0900 hocam çok teşekkür ediyorum bu bilgiler için. Ben TCP ile çalışmadım. Hele Linux'ta hiç. Bakalım arkadaşım bu konularda neler yapabilecek :) Eğer olmazsa dediğiniz gibi Iseek() fonksiyonundan yardım alırız. Artık gerisi araştırmaya ve geliştirmeye kaldı tamamen. Verdiğiniz tüm bilgiler için teşekkür ediyorum tekrardan. Muhtemelen hafta sonuna kadar proje arkadaşımla görüşmüş, denemeler yapmış olacağız. Eğer çözersek, başkalarına lazım olur diye döner buraya çözümü belirtirim. Eğer olurda (çoğu zaman başımıza geldiği gibi :) ) çözemezsek, sizlerin başını boş vakitlerinizde biraz daha ağrıtmak için izin isterim :) .

Tekrar tekrar teşekkürler. İyi çalışmalar. İyi geceler.

cagriemer

Soyle bir sey buldum, is gorur mu bilmiyorum zira c programlama bilmiyorum.

Alıntı YapThe FIONREAD ioctl gets the number of bytes in the serial port input buffer. As with TIOCMGET you pass in a pointer to an integer to hold the number of bytes, as shown in Listing 7.

Listing 7 - Getting the number of bytes in the input buffer.

    #include <unistd.h>
    #include <termios.h>

    int fd;
    int bytes;

    ioctl(fd, FIONREAD, &bytes);
This can be useful when polling a serial port for data, as your program can determine the number of bytes in the input buffer before attempting a read.

Kaynak icin; http://www.easysw.com/~mike/serial/serial.html#advanced

travego0403

Evet ioctl() sistem çağrısı okunabilecek byte sayısını veriyor. Düzenli dosyalar üzerinde denedim çalışıyor.Dosyada toplam kaç byte veri olduğunu buluyor. Muhtemelen seri port üzerinde de çalışması gerekir.
Sistem çağrısının kullanılabilmesi için gereken başlık dosyası
#include <sys/ioctl.h>
da dahil edilmesi gerekiyor. fd diye gösterilen açılan dosyayı ya da akımı temsil eden tanımlayıcı. 2.argüman bir bayrak(flag) değişkeni değiştirmenize gerek yok. bytes değişkeninde adresi geçiliyor sistem çağrısına, oda okunabilecek byte sayısını bu adresteki değişkene atıyor.
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

ulusoyab

eğer gambas kullanmak istersen içindeki örnek proje istediklerinin tümünü karşılıyor.

http://gambasdoc.org/help/comp/gb.net/serialport
burada da kısa açıklaması var.

canavaroski90

Alıntı yapılan: cagriemer - 01 Mart 2012 - 05:51:32
Soyle bir sey buldum, is gorur mu bilmiyorum zira c programlama bilmiyorum.

Kaynak icin; http://www.easysw.com/~mike/serial/serial.html#advanced

cagriemer hocam çok sağol. Anladım ki arama yapmak hakkında hiç bir fikrim yok.. Bide az buçuk ingilizce anlayan adamım diye geçiniyorum. Deyim yerindeyse yaptığım eşşeklik. Çok teşekkürler tekrar. Kullanmaya çalışacağım.

Alıntı yapılan: travego0403 - 01 Mart 2012 - 11:15:06
Evet ioctl() sistem çağrısı okunabilecek byte sayısını veriyor. Düzenli dosyalar üzerinde denedim çalışıyor.Dosyada toplam kaç byte veri olduğunu buluyor. Muhtemelen seri port üzerinde de çalışması gerekir.
Sistem çağrısının kullanılabilmesi için gereken başlık dosyası
#include <sys/ioctl.h>
da dahil edilmesi gerekiyor. fd diye gösterilen açılan dosyayı ya da akımı temsil eden tanımlayıcı. 2.argüman bir bayrak(flag) değişkeni değiştirmenize gerek yok. bytes değişkeninde adresi geçiliyor sistem çağrısına, oda okunabilecek byte sayısını bu adresteki değişkene atıyor.

travego0403 hocam, teşekkür ederim kullanımını anlatıığın için. Bundan da faydalanmaya çalışacağım. Tüm önerileri not ediyorum. Vaktiniz olursa başınızı tekrar ağrıtmak için izin isterim.

Alıntı yapılan: ulusoyab - 01 Mart 2012 - 12:13:36
eğer gambas kullanmak istersen içindeki örnek proje istediklerinin tümünü karşılıyor.

http://gambasdoc.org/help/comp/gb.net/serialport
burada da kısa açıklaması var.

ulusoyab hocam, önerin iin teşekkürler. Ama anladığım kadarıyla Gambas bir dil. (Yanlış da anlamış olabilirim) Eğer doğru anlamışsam, sanırım bunun için uğraşmamız gereğinden fazla vakit alabilir. Tekrar teşekkürler.