Seri iletişimde stabil olmayan davranış

Başlatan muhendisbey, 19 Ekim 2014, 12:42:16

muhendisbey

Merhaba
C# üzerinden seri iletişimden hem veri gönderip hem veri almaya çalışıyorum. Ancak sürekli olarak program bir yerde ya patlıyor, yada istenmeyen durumlar ortaya koyuyor. Sistemden string okuma yapmam şart. Okuma kodunu aşağıya ekledim, sizce ne yapmam lazım? picproje'deki tüm seri iletişim hataları kısmını okudum. Asenkron yapmam gerektiği kanısına vardım ancak nasıl asenkron kodlayacağım hakkında en ufak fikrim bile yok. Kaynak olarak nereye bakmamı önerirsiniz yada bu kodun adam olma ihtimali var mı?


        void SeriPortum_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            
            SerialPort sp = (SerialPort)sender;
            dump = sp.ReadTo("pwmdurum=");
            pwmdurum = Convert.ToSingle(sp.ReadTo("$"));

            this.Invoke(new EventHandler(DisplayText));
            SeriPortum.DiscardInBuffer();

        }


Bu kodun üzerinde okuma yaptığım yerde şöyle bir kod daha var
        private void BtnOku_Click(object sender, EventArgs e)
        {
            if (SeriPortum.IsOpen)
            {
                
                SeriPortum.Write("pwmdurum\n\r");

                
                SeriPortum.DataReceived +=new SerialDataReceivedEventHandler(SeriPortum_DataReceived);
                
            }

        }


Yardımlarınız bekliyorum, iyi çalışmalar.
Zulmü alkışlayamam, zalimi asla sevemem; Gelenin keyfi için geçmişe kalkıp sövemem.

berat23

ortalık biraz karışmış gibi. koddan ziyade ne yapmaya çalıştığınızı yazarsanız yardım edebilirim. gelen giden verinin formatı vs. gibi.

muhendisbey

Gelen verinin formatı
pwmdurum=integer sayı (debug yaptım herhangi bir sıkıntı yok)----->pwmdurum=1000$
giden verinin formatı
pwmdurum

c#'ta okunan
pwmd
pwmduru
pwmdurum
wmdurum
.
.
.
bunun gibi eksik karakter okuyor. ya baştan ya sondan kırpıyor.
Seri portu kapatmak istediğimde
Alıntı YapBir iş parçacığı çıkışı veya bir uygulama isteği nedeniyle G/Ç işlemi iptal edildi.
hatası alıyorum.
Yardımcı olabilir misiniz?
Zulmü alkışlayamam, zalimi asla sevemem; Gelenin keyfi için geçmişe kalkıp sövemem.

berat23

öncelikle her butona basıldığında event oluşturmanıza gerek yok, bu işlemi ya başlangıçta ya da objenin özelliklerinden yapabilirsiniz.

serial evet'te ise aslında terslik c#de. tahminim siz de  elektronikçisiniz, bende ilk başta uğraşmıştım. o event olduğu zaman belirsiz uzunlukta veri geliyor, toplayıp sonra parse etmek gerekiyor. mantıken byte byte almak ya da readline deyince \n e kadar almasınız beklersiniz ama öyle değil.

event içinde şu yapılabilir,

string sSerialBuffer;

void SeriPortum_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    sSerialBuffer+= sp.ReadExisting();
}


sonra periyodik bir fonksiyon yaratın, ister timer ile ister thread yapın. bu fonksiyon gelen datayı parse etsin. "pwmdurum=" stringini arayıp parse edebilirsiniz.

ya da şöyle bir metod var, bir thread ile gelen datayı dinleyebilir, byte byte alıp dahakolay parse edebilirsiniz ama bu çözüm biraz kazmaca. ben genelde test programı vs. yazarken thread yapıp byte byte alıyorum ama ilk yola alışmak daha doğru.

muhendisbey

Hocam bu yolu thread yada timer ile okuma yapmadan denedim. Ancak yine de istenilen sonucu elde edemedim. Buton olayı şu, karşıdan sürekli veri basılmıyor, siz talep ediyorsunuz o da veri gönderiyor.
Zulmü alkışlayamam, zalimi asla sevemem; Gelenin keyfi için geçmişe kalkıp sövemem.

MrDarK

Yerinizde olsam receive ettiğiniz datanın uzunluğuna göre karşılaştırma yapın. Eğer bu bir RF datası içinden çekilmiyor ise veri başladıktan sonra bir timer kurup paket sonunu tespit edebilirsiniz.
Picproje Eğitim Gönüllüleri ~ MrDarK

muhendisbey

Veri uzunluğu sabit olsa keşke ama değil. yeri geliyor 10 karakter oluyor yeri geliyor 14 karakter oluyor.
Zulmü alkışlayamam, zalimi asla sevemem; Gelenin keyfi için geçmişe kalkıp sövemem.

justice_for_all

o zaman once bir bayt karakterin uzunluğunu gönderin sonra datayı gönderin.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

MrDarK

Belki cihazın protokolü müdahale edebileceği yapıda değildir, şu son söylediğinizle en mantıklısı ilk gelen karakterde timer başlatıp timer kesme oluşturana kadar datayı analiz etmeyin
Picproje Eğitim Gönüllüleri ~ MrDarK

EMP_Otto

Bu işler zordur,özveri ister...

muhendisbey

Cihaza müdahale etmem mümkün, ancak byte ile veri uzunluğunu stabil alabilirsem bütün stringi byte'a çevirir byte byte alırım. Ancak bu bir şekilde olmuyor. Gördüğüm şu 115200 baud rate'te kullanmam gerekiyor, galiba bu baud rate c# ın yakalama limitini zorluyor. Sonuçta bir işletim sistemi altında bu türden io erişimleri sıkıntı oluyor. Daha önce raspberry pi'de de başıma gelmişti phyton komutu ile iki led arka arkaya belirli aralıkla yanarken senkron bozulup bazen aynı anda yanabiliyordu. Ben buna bağladım.
ilk karakterde timer başlatmak için soruyorum: ilk karakter özel karakter mi olsun diyorsunuz yani #giden_veri$ şeklinde mi?
Bu durumda seri iletişimde parity kullanmak çözüm olur mu? şu an parity bitini kullanmıyorum stop bitim de tek.
Forumda bir arkadaş CRC kullanımından bahsetmiş (ne olduğunu bilmiyorum ancak en kısa sürede araştıracağım) bu çözüm olabilir mi?
Seri iletim aslında asenkron yapıya sahip olmalı, acaba C#'ta beceremediğim kısım bu mu? Bir şekilde kendimi interrupt oluşturamıyormuş gibi hissediyorum. String gelirken program nerede kaldıysa oradan devam edip seri iletime gelince kafasına dank ediyor gibi, böyle olunca da kaçırıyor. Bunu daha önce interrupt nedir bihaberken mcu'larda rastlardım.

EMP_Otto, programınızı kullanamadım, COM portlarım dolu olmasa yer değiştireceğim, ancak programı COM11 115200 baud'a ayarlı derleyebilirseniz makbule geçer. Benim de debug denemem neredeyse aynı arayüze sahipti. Bir terminal programı gibi, onda da stabil çalıştıramadım. Bir şekilde mantık hatam var ve çözemedim.
Zulmü alkışlayamam, zalimi asla sevemem; Gelenin keyfi için geçmişe kalkıp sövemem.