Picproje Elektronik Sitesi

PROGRAMLAMA DİLLERİ => Visual C# => Konuyu başlatan: hadesi - 19 Haziran 2022, 10:12:24

Başlık: C# datareceive Problemi
Gönderen: hadesi - 19 Haziran 2022, 10:12:24
arduinodan gelen verimi sıkıntısız bir şekilde c# a çekiyorum ancak bir süre sonra herhangibir butona tıkladığımda timer 2 yi hiç bir şekilde çalıştıramıyorum porta bağlanmadan basınca sıkıntı yok çalışıyor ama porta bağlandıktan sonra timerı hiç bir türlü çalıştıramıyorum. Yardım ederseniz sevinirim. C# ta biraz amatörüm umarım sorunumu anlatabilmişimdir.
public partial class Form1 : Form
    {
        string[] portlar = SerialPort.GetPortNames();
        public Form1()
        {
            InitializeComponent();
            serialPort1.BaudRate = 9600;
            Control.CheckForIllegalCrossThreadCalls = false;
        }
        int x, y = 0,bekleme=30,calisma=5,bekleme1=30,a=0;
        double ec1 = 5;
       

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (string port in portlar)
            {
                comboBox1.Items.Add(port);
                comboBox1.SelectedIndex = 0;

            }
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
           
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string data;
            string[] splitted_data;
            data=serialPort1.ReadLine();
            splitted_data = data.Split('-','.');

            label1.Text = data;

            double a, b, c, d,isi,ec;
            a = Convert.ToInt32(splitted_data[0]);
            b = Convert.ToDouble(splitted_data[1]);
            c = Convert.ToInt32(splitted_data[2]);
            d = Convert.ToDouble(splitted_data[3]);

            /////ısı-hesaplama/////
            d = d / 100;
            isi = c + d;
            label2.Text = "derece: " + isi.ToString();
            ////Ec Hesaplama/////
            b = b / 100;
            ec = a + b;
            label3.Text = "EC: " + ec.ToString();
            if (ec<ec1)
            {
                if (bekleme == bekleme1)
                {
                   
                    bekleme = 0;
                   
                    label12.Text = "Motor Çalışıyor";
                    timer2.Start();
                    button5.BackColor = Color.Green;

                   
                }
            }
            else
            {
                label12.Text = "Motor Çalışmıyor";
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                serialPort1.PortName = comboBox1.Text;
                try
                {
                    serialPort1.Open();
                }
                catch (Exception)
                {
                   
                    throw;
                }
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
        }

        private void button3_Click(object sender, EventArgs e)
        {
           
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            y = Convert.ToInt32(trackBar1.Value);
            label9.Text = trackBar1.Value.ToString();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
           
        }

        private void button3_Click_1(object sender, EventArgs e)
        {
            ec1 = Convert.ToDouble(textBox1.Text);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            label15.Text = "b";
        }

        private void timer3_Tick(object sender, EventArgs e)
        {

        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            a++;
            label17.Text = a.ToString();
            /*if (bekleme==calisma)
            {
                bekleme = 0;
                label12.Text = "motor durdu";
                timer2.Enabled = false;
            }*/
        }

        private void button7_Click(object sender, EventArgs e)
        {
            timer2.Start();
        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            label4.Text = DateTime.Now.ToString();
            byte i;
            string[] yazi;
            yazi = label4.Text.Split(':', '.', ' ');

            for (i = 0; i <= yazi.Length - 1; i++)
            {
                x = Convert.ToInt32(yazi[5]);
                if (y>x)
                {
                    label7.Text = "Motor Çalıştı";
                    button4.BackColor = Color.Green;
                    if (serialPort1.IsOpen)
                    {
                        serialPort1.Write("0");
                    }
                }
                else
                {
                    label7.Text = "Motor Durdu";
                    button4.BackColor = Color.Red;
                    if (serialPort1.IsOpen)
                    {
                        serialPort1.Write("0");
                    }
                }
            }
        }
    }
Başlık: Ynt: C# datareceive Problemi
Gönderen: foseydon - 19 Haziran 2022, 20:36:18
hocam debug edebilir musun? timer2'yi datarecived icerisinde calistiriyorsun ustelik kosul var. bu durumda 2 alternatif var.
1. datareceived giriyor, kosul calismiyor.
2. datareceived hic girmiyor, yani veri gelmiyor.

bu arada serialport eventleri sikintili. ben burada daha once bi makale paylasmistim konu ile alakali. bunun yerine timer kullanin daha guvenli olur demisti. usenmezsen benim iletilere bak, C# diye aratirsan cikar sanirim. yazilari bi kontrol et gorursun. bu konularda daha onceden baya yazmistim cunku. tekrar yazmaya useniyorum
Başlık: Ynt: C# datareceive Problemi
Gönderen: hadesi - 19 Haziran 2022, 20:54:48
datareceived a giriyor sıkıntısız veri çekiyor ama koşul ile timerı çalıştıramıyorum. Koşuldamı sıkıntı var diye butonun içine timer attım serial porta bağlanmadan sıkıntısız çalışıyor ama serial porta bağlandığımda çalışmıyor bir süre sonra. Bundan önce verileri timer ile çekiyordum ondada sıkıntı çıkıyor program donuyor.
şu dersteki kodları uyguladım açıkça söylemek gerekirse
Başlık: Ynt: C# datareceive Problemi
Gönderen: muhittin_kaplan - 20 Haziran 2022, 20:24:51
thread nedir, c# da thread kullanımı nasıldır?
Başlık: Ynt: C# datareceive Problemi
Gönderen: hadesi - 22 Haziran 2022, 21:58:20
thread i bilmiyordum araştırdım genelde örnekler for döngüsüyle açıklanmış c# form da thread ile timer çalıştıranı bulamadım. Bulabilsem sorunum hallolacak gibi.
Başlık: Ynt: C# datareceive Problemi
Gönderen: hadesi - 23 Haziran 2022, 23:48:16
public void thread()
        {
            for (int i = 0; i < 1000000; i++)
            {
                try
                {
                    string sonuc = serialPort1.ReadLine();
                    string[] pot = sonuc.Split('-', '.');
                    label1.Text = sonuc + "";
                   
                    a = Convert.ToInt32(pot[1]);
                    label3.Text = a.ToString();
                    if (a>1)
                    {
                        if (bekleme==30)
                        {
                            bekleme = 0;
                            timer1.Start();
                        }
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    throw;
                }
            }
şöyle bişey yaptım verileri timer yerine for ile çekmeye çalıştım sıkıntısız çekiyor ama thread ile çalıştırdığım for döngüsünün içine timer1.start yazdığımda timer buga giriyor. normal butona atadığımda timerı sıkıntısız çalışıyor.
Başlık: Ynt: C# datareceive Problemi
Gönderen: yas - 24 Haziran 2022, 11:24:40
C# kullanmıyorum, ama öneride bulunmak istedim acaba timer nesnesini public olarak mı atamak gerek.
Başlık: Ynt: C# datareceive Problemi
Gönderen: muhittin_kaplan - 25 Haziran 2022, 12:21:39
uzun zamandır c# yazmıyorum.
Masaüstünde bir işi yaparken, mesala bir form u ekranda göstermek gibi, başka bir işle mesgul olmak isterseniz mesela prt dinlemek gibi (veri geldiğini nerden anlayacak)işte burada thread, multiprocess gibi ayrık işler kullanmanız gerekir.
Neden ?
ekranda bir form u göstermk bile bir iş parcasıdır ve devamlı yapılmalıdır ki kullanıcı formu biryere taşırken boyutlandırırken, işlemcinin diğer iş parçacını yapması dolayısıyla donmalar yaşamasın.

Bunun için yeni bir thread yaratılıp bu theradın ana thread ı (form işlemleri örneğin) kesintiye ugratmadan port u dinlemesi ve gelen bir veri olursa ana thread la iletişim kurup "bak bu geldi alabilirsin formuna demesi gerekir.

https://www.picproje.org/index.php/topic,76385.msg583218.html#msg583218

https://www.picproje.org/index.php/topic,70627.msg541714.html#msg541714

https://www.picproje.org/index.php/topic,64626.msg500784.html#msg500784

https://www.picproje.org/index.php/topic,59768.msg461826.html#msg461826

https://www.picproje.org/index.php/topic,50376.msg379540.html#msg379540
Başlık: Ynt: C# datareceive Problemi
Gönderen: foseydon - 25 Haziran 2022, 19:43:24
hemen bisey ekliyim. timer GUI'nin calistigi thread'de calisir. bu yuzden veri isleme isini timer'da yaparsaniz sorununuz cok hizli cozulur.
Başlık: Ynt: C# datareceive Problemi
Gönderen: muhittin_kaplan - 25 Haziran 2022, 20:13:00
Alıntı yapılan: foseydon - 25 Haziran 2022, 19:43:24hemen bisey ekliyim. timer GUI'nin calistigi thread'de calisir. bu yuzden veri isleme isini timer'da yaparsaniz sorununuz cok hizli cozulur.
Bence hatalı bir öneri.
Timer ile bir portu dinliyorsanız veri kaçırma ihtimaliniz yüksektir.
Timer ı kurdunuz. Timer veri geldi dedi. Almaya başladınız. Bu esnada gui nin threadı ne durumda olacak ?
Başlık: Ynt: C# datareceive Problemi
Gönderen: foseydon - 25 Haziran 2022, 20:32:37
Alıntı yapılan: muhittin_kaplan - 25 Haziran 2022, 20:13:00Bence hatalı bir öneri.
Timer ile bir portu dinliyorsanız veri kaçırma ihtimaliniz yüksektir.
Timer ı kurdunuz. Timer veri geldi dedi. Almaya başladınız. Bu esnada gui nin threadı ne durumda olacak ?

veriyide timer'in icerisinde toplayacaksiniz zaten? ben bu sekilde yapiyorum. veri hic kacmaz.
Başlık: Ynt: C# datareceive Problemi
Gönderen: muhittin_kaplan - 25 Haziran 2022, 22:30:58
Timer i ntervali nedir, eğer timer intervali çok hızlıysa form da donmalar, yavaş ise veride kaçaklar oluşur. Keskin kılıç. Doğrusu Thread dır.
Başlık: Ynt: C# datareceive Problemi
Gönderen: foseydon - 26 Haziran 2022, 09:39:24
Alıntı yapılan: muhittin_kaplan - 25 Haziran 2022, 22:30:58Timer i ntervali nedir, eğer timer intervali çok hızlıysa form da donmalar, yavaş ise veride kaçaklar oluşur. Keskin kılıç. Doğrusu Thread dır.

hocam threadpool kullandim, backgroundworker kullandim vs. en randuman aldigim sistem timer. illa 1 tane timer olacak diye birsey de yok. 2-3 tane timer kurupta yapabilirsin islerini. timer sureleri degisken. 100mste olur 1000mste olur. data hizina gore ayarlarsin. 9600 baud standart 1200 byte yapar saniyede. islemesi citir cerez bilgisayar icin zaten. seriaport buffer'ini da tasiman pek olasi degil ki zaten buffer boyutunu da buyutebilirsin, seriport'un buffersize property sini kullanarak. formda donmasi icin cok uzun sure islem yapman lazim. oyle agir islem gerektiren birsey varsa, o zaman iste arka planda isletip sonra guncellemek daha dogru oluyor. ama o kadar agir islem gerektirecek bisey de lazim olmuyor. sonucta bilgisayarda genelde yaptigin is gelen veriyi goruntuleme, parametre gonderip degistirme.
Başlık: Ynt: C# datareceive Problemi
Gönderen: tunayk - 27 Haziran 2022, 10:54:18
Thread ile çalışmanın korukulacak bir yanı yoktur.  Form uygulamalarında, hertürlü IO işlemlerinin (Dosya, Ağ, Ser port, veritabanı işlemleri  vb.) timer ile yapılması genel olarak doğru bir yol değildir.  Yapılmaz değil ancak önerilen yol değildir. Bunu MSDN deki örneklerde de farklı referanslarda da açıkça görebilirsiniz. 
Buradaki temel prensip, dış kaynak kullanacak işlemlerde dış kaynağın dönüş hızı keskin olarak garanti edilemeyeceğinden formla aynı thread içinde yapılacak hareketler az veya çok donmaya neden olur. Miktarı uygulamanın karmaşıklığına bağlı olarak değişir. Yorum farkları biraz buradan kaynaklanıyor.  250ms de bir 10byte gönderen bir uygulamada bu hissedilmez. Aynı uygulama hem seri portta haberleşme yapıp, hem veritabanına birşeyler yazıp okuyacak, hem ekranda hızlı grafikler çizecekse işler değişir. Hepsini form timer ile çözelim derseniz uygulama ancak çok güçlü makinalarda çalışabilecektir.

Seri portta veri kaçırma ihtimali görece düşük bir itimal.  Windows tarafında 2k kadar bir input buffer olduğundan pek sorun yaşanmaz. Ancak alınan dataya hızlı reaksiyon gerekli ise daha farklı düşünmek lazım.

Sözün özü windows uygulamasında kurgulanan mimari ile uygulama örtüşüyor ise sorun yok. Ancak bu çözüm her zaman en iyi çözüm olmayabilir.
Başlık: Ynt: C# datareceive Problemi
Gönderen: bocek - 27 Haziran 2022, 16:55:20

Sorunun çözümü burada anlatılıyor.

Salih Cantekin'in anlatımı çok güzel.
Ele aldığı konuları sıfırdan başlayarak anlatıyor.