none
Interface graphique pour port série en C # RRS feed

  • Question

  • Bonjour,

    Je suis en train de développer une interface graphique pour communiquer avec une carte de dév via le port série.

    A partir de cette carte, j'envoie des données de type float vers mon PC, ensuite je stocke le résultat dans un fichier.

    J'envoie un tableau de 5 float. à la récupération je n'ai pas de problème.

    Ensuite, dans une boucle while, j'envoie en continu un float.Le problème c'est que en faisant cela, j'ai plus la main sur mon interface graphique et le fichier semble enregistrer des donnés sans arrêt.

    Ci dessous le code que j'ai utilisé: 


              

      private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {

                // Si le port est ouvert, le fermer
                if (!serialPort1.IsOpen) return;

                // Obtenir le nombre d'octets en attente dans le tampon du port
                int bytes = serialPort1.BytesToRead;

                // Créez une zone tampon (tableau d'octets) pour stocker les données entrantes
                byte[] buffer = new byte[bytes];

                // Lire les données du port et de le stocker dans la mémoire tampon
                serialPort1.Read(buffer, 0, bytes);

                this.BeginInvoke(new EventHandler(delegate
                {
                    SetTheText(buffer);
                   // SetTheFloat(bBuffer);

                }));
                Application.DoEvents();
            }

    /*-----------*/

     private void SetTheText(byte[] data)
            {
                try
                {
                    MemoryStream ms = new MemoryStream();
                    ms.Write(data, 0, data.Length);
                    ms.Position = 0;
                    BinaryReader br = new BinaryReader(ms);
                   //int write = ms.Read(data, 0, data.Length); // add by me to test 

                    int length = (int)br.BaseStream.Length;
                    int pos = 0, i = 0;
                    float receivedata;
                    StreamWriter sw = new StreamWriter(@"C:\Users\Hilouane\Desktop\ProjetMultis\Text.txt");//création du fichier 
                    string[] text = new string[5];

                    if (length == 20)
                    {
                        text[0] = "X0:= ";
                        text[1] = "A0:= ";
                        text[2] = "Y0:= ";
                        text[3] = "B0:= ";
                        text[4] = "Theta:= ";
                        while (pos < length)
                        {

                            f[i] = br.ReadSingle();
                            textBox2.Text += text[i] + f[i] + "\r\n";
                            pos += sizeof(float);
                            System.IO.File.WriteAllText(@"C:\Users\Hilouane\Desktop\ProjetMultis\WriteText.txt", textBox2.Text);
                            //   sw.WriteLine(f[i]);
                            i++;
                        }
                        sw.Close(); //dispose streamer
                        br.Close();//dispose reader
                        ms.Close(); //dispose streamer
                    }// end of if length
                    else
                    {
                        while (pos < length)
                        {
                            receivedata = br.ReadSingle();
                            textBox2.AppendText("Position(nm):= " + receivedata + "\r\n");
                            //textBox2.Text += "Position(nm):= " + receivedata + "\r\n";
                            //System.IO.File.WriteAllText(@"C:\Users\Hilouane\Desktop\ProjetMultis\WriteText.txt", textBox2.Text);
                            sw.WriteLine(textBox2.Text);
                        }

                        sw.Flush();
                        sw.Dispose();
                        //sw.Close(); //dispose streamer
                        br.Close();//dispose reader
                    }

                } // end of try
                catch (Exception e)
                {
                    Console.WriteLine("The process failed: {0}", e.ToString());
                }
                
      }

    Pourriez vous me dire ce qui ne va pas avec mon code s'il vous plait?

    Merci d'avance 

    vendredi 28 février 2014 10:23

Toutes les réponses

  • Bonjour

    N'est pas très claire quel est votre soucie.
    Essayez de ne pas sur écrire le fichier pour chaque SetTheText et vérifies le résultat dans le fichier.

    Cordialement, 


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    vendredi 28 février 2014 14:49
  • Le soucie c'est que l’interface se plante( le cas où lenght est différent de 0) et  je ne peux peux pas cliquer sur les  boutons que j'ai crée. Dans le cas ou lenght=20, y a pas de problème.

    Essayez de ne pas sur écrire le fichier pour chaque SetTheText et vérifies le résultat dans le fichier : J'ai essayé d'écrire à la suite du fichier, mais j'ai remarqué que à chaque fois la taille augmente.

    Comment dois je faire pour avoir le contrôle sur mon interface pour pouvoir arrêter la réception ?

    Idéalement, je voudrais enregistrer un certain nombre de valeurs dans mon fichier et le fermer par la suite. Mais cela, je ne peux le faire tant que je n'ai pas la main sur mon interface.

    Merci d'avance  

    vendredi 28 février 2014 15:46
  • Bonjour,

    Pourquoi ne pas mettre votre code qui fait tout le traitement dans "serialPort1_DataReceived", et vous appelez la méthode BeginInvoke() pour invoquer du code qui doit mettre uniquement à jour votre interface graphique :

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
    
                // Si le port est ouvert, le fermer
                if (!serialPort1.IsOpen) return;
    
                // Obtenir le nombre d'octets en attente dans le tampon du port
                int bytes = serialPort1.BytesToRead;
    
                // Créez une zone tampon (tableau d'octets) pour stocker les données entrantes
                byte[] buffer = new byte[bytes];
    
                // Lire les données du port et de le stocker dans la mémoire tampon
                serialPort1.Read(buffer, 0, bytes);
    
                try
                {
                    MemoryStream ms = new MemoryStream();
                    ms.Write(buffer, 0, buffer.Length);
                    ms.Position = 0;
                    BinaryReader br = new BinaryReader(ms);
                    //int write = ms.Read(data, 0, data.Length); // add by me to test 
    
                    int length = (int)br.BaseStream.Length;
                    int pos = 0, i = 0;
                    float receivedata;
                    StreamWriter sw = new StreamWriter(@"C:\Users\Hilouane\Desktop\ProjetMultis\Text.txt");//création du fichier 
                    string[] text = new string[5];
    
                    if (length == 20)
                    {
                        text[0] = "X0:= ";
                        text[1] = "A0:= ";
                        text[2] = "Y0:= ";
                        text[3] = "B0:= ";
                        text[4] = "Theta:= ";
                        while (pos < length)
                        {
    
                            f[i] = br.ReadSingle();
    
                            this.BeginInvoke(new EventHandler(delegate
                            {
                                textBox2.Text += text[i] + f[i] + "\r\n";
                            }));
    
                            pos += sizeof(float);
                            System.IO.File.WriteAllText(@"C:\Users\Hilouane\Desktop\ProjetMultis\WriteText.txt", textBox2.Text);
                            //   sw.WriteLine(f[i]);
                            i++;
                        }
                        sw.Close(); //dispose streamer
                        br.Close();//dispose reader
                        ms.Close(); //dispose streamer
                    }// end of if length
                    else
                    {
                        while (pos < length)
                        {
                            receivedata = br.ReadSingle();
    
                            this.BeginInvoke(new EventHandler(delegate
                            {
                                textBox2.AppendText("Position(nm):= " + receivedata + "\r\n");
                            }));
                            //textBox2.Text += "Position(nm):= " + receivedata + "\r\n";
                            //System.IO.File.WriteAllText(@"C:\Users\Hilouane\Desktop\ProjetMultis\WriteText.txt", textBox2.Text);
                            sw.WriteLine(textBox2.Text);
                        }
    
                        sw.Flush();
                        sw.Dispose();
                        //sw.Close(); //dispose streamer
                        br.Close();//dispose reader
                    }
    
                } // end of try
                catch (Exception ex)
                {
                    Console.WriteLine("The process failed: {0}", ex.ToString());
                }

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    vendredi 28 février 2014 19:22
    Modérateur
  • Merci Gilles pour votre réponse, j'ai essayé votre code mais je n'ai toujours pas le contrôle sur mon interface graphique. De plus, j'ai remarqué que les valeurs enregistrées dans mon fichier ne commence jamais avec la première valeur envoyé par ma carte de dév. et que certaines valeurs sont ignorés.

    Pensez vous que c'est un problème de synchronisation ? Dois-je utiliser les Thread pour résoudre ce problème? 

      Cordialement; 
    samedi 1 mars 2014 17:37
  • Bonjour,

    Oui il faudrait créer un Thread pour récupérer les données depuis le port série. En tout cas, vous devez mettre à jour l'interface graphique en utilisant la méthode Invoke() ou BeginInvoke() de la classe Control.

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    dimanche 2 mars 2014 18:35
    Modérateur
  • Bonjour

    Avez-vous essaye de utiliser l'exemple trouve  ici :
    http://msdn.microsoft.com/en-us/library/System.IO.Ports.SerialPort(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
    Il utilise des threads mais sans DataReceived (à mon avis c'est mieux!).

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.


    lundi 3 mars 2014 09:07
  • Bonjour Aurel,

    Merci pour votre réponse. Non je ne l'ai pas encore essayé. Au fait, mon problème c'est que j'ai une dizaine de bouton dans mon interface, de textBox et de combox , du coup je ne sais pas comment je vais ajouter un thread à ce que j'ai fait avant. De plus, l'exemple dont vous faites référence est sur console alors que moi je travaille sur Windows Form 

    lundi 3 mars 2014 16:19
  • Bonjour,

    A quel moment doit être déclenché la réception des données ? Lors d'un clic sur vos dix bouton ? En continue ?

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    mardi 4 mars 2014 22:47
    Modérateur
  • Bonjour,

    Je veux déclencher la réception lors d'un Click sur 3 de mes dix boutons mais d'une façon indépendante.

    Ci dessous le programme que j'avais fait avec un thread, j'ai pu avoir la main sur mon interface graphique mais je ne reçois toujours pas toute les valeurs que j'envoie.

                                                                   

    /* Thread pour la lecture 

    namespace SerialTest
        {
        class SerialReaderThread
        {
            private Thread t;
            public System.IO.Ports.SerialPort myserial;

            public SerialReaderThread(System.IO.Ports.SerialPort serialport, bool flag)
            {

               this.myserial = serialport;
                if(flag)
                    t = new Thread(RunMethod);
            }

            public void start()
            {
                t.Start();
            }
            public void stop()
            {
                t.Abort();
                closed = true;
            }

            private bool closed = false;
            public void Close() { closed = true; }
            public event EventHandler<DataEventArgs> DataReceived;

            private void RunMethod()
            {
                // Si le port est ouvert, le fermer
                if (!myserial.IsOpen) return;


                while (!closed)
                {
                    // Obtenir le nombre d'octets en attente dans le tampon du port
                    int bytes = myserial.BytesToRead;

                    // Créez une zone tampon (tableau d'octets) pour stocker les données entrantes
                    byte[] buffer = new byte[bytes];
                   // myserial.DiscardOutBuffer();

                    // Lire les données du port et de le stocker dans la mémoire tampon
                    myserial.Read(buffer, 0, bytes);
                   // System.Threading.Thread.Sleep(10);
                    if (DataReceived != null) DataReceived(this, new DataEventArgs(buffer));

                }
            }
        }

         

    /* Un des boutons qui  lance le thread 

     private void Displac_Btn_Click(object sender, EventArgs e)
            {
                // If the port is closed, don't try to send data.
                if (!serialPort1.IsOpen) return;

                // If the port is Open, declare a char[] array with 256 elements.
                char[] Displ_Init = new char[1];
                Displ_Init[0] = '7';
                try
                {
                    // Send the character buffer.
                    serialPort1.Write(Displ_Init, 0, 1);
                }
                catch (System.Exception)
                {
                    MessageBox.Show("Failed to write to port.");
                }
                BoxDeplacement.Clear();
                BoxDeplacement.Text = "Déplacement en cours";
                status = true;
                 if (thread == null)
                   {
                       thread = new SerialReaderThread(serialPort1, status);
                       thread.DataReceived += ThreadDataReceived;
                       thread.start();
                   }
                    reading=true;      
            }

     void ThreadDataReceived(object s, EventArgs e)
            {
                if (reading) Invoke(new EventHandler<DataEventArgs>(ThreadDataReceivedSync), new object[] { s, e });
            }

            void ThreadDataReceivedSync(object s, DataEventArgs e)
            {
                try
                {
                    MemoryStream ms = new MemoryStream();
                    ms.Write(e.Data, 0, e.Data.Length);
                    ms.Position = 0;
                    BinaryReader br = new BinaryReader(ms);
                   
                    int length = (int)br.BaseStream.Length;
                    int pos = 0, i = 0;
                    StreamWriter sw = new StreamWriter(@"C:\Users\Hilouane\Desktop\ProjetMultis\Text.txt", true);//création du fichier 
                   
                    float datarecieve;
                   
                        while (pos < length)
                        {
                            datarecieve = br.ReadSingle();
                            textBox2.AppendText("Position(nm):= " + datarecieve + "\r\n");
                            sw.Write(datarecieve + "\r\n");
                            pos += sizeof(float);
                        }

                        sw.Flush();
                        sw.Dispose();
                        br.Close();//dispose reader
                    }

                } // end of try
                catch (Exception ex)
                {
                    Console.WriteLine("The process failed: {0}", ex.ToString());
                }

            }

    Merci d'avance,

    Cordialement 

    mercredi 5 mars 2014 13:55
  • Bonjour

    Essayez de ajouter

     

       serialPort1.RtsEnable = true;
       serialPort1.DtrEnable = true;

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mercredi 5 mars 2014 14:12
  • Je l'avais déjà ajouté dans le bouton "Open" qui permet de configurer et d'ouvrir le port série.

    Est ce que ma façon d'utiliser le thread est correct ?

    Merci d'avance 

    Cordialement; 

    mercredi 5 mars 2014 17:26
  • Sera difficile pour n'importe qui de regarder un code avec des threads et dire que c'est OK ou non.
    Avec l'autre code vous avez pu vérifier 100% que les données ont été envoyées complètement et correctement?
    Veuillez télécharger cet exemple et essayez de vérifier qu'est qu'il arrive sur le port sériel 
    http://code.msdn.microsoft.com/windowsdesktop/SerialPort-brief-Example-ac0d5004

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    jeudi 6 mars 2014 14:37
  • Je pense que j'ai trouvé d'où vient mon problème. 

    La sortie de ma boucle a une fréquence de ~40Khz, du coup quand j'envoie mes donnés sur le port série qui a une vitesse de 115200 baud, certaines donnés sont ignorées. Donc pour résoudre cela, j'ai du mettre un délai pour réduire la fréquence de ma boucle et par conséquence j'arrive à recevoir toute le données envoyées avec le premier code que j'avais publié tout au début. Avec ce code, mon interface graphique se bloque et je dois forcer sa fermeture.

    La version du code avec le thread ne marche toujours pas, néanmoins j'ai les donnés qui arrivent en ordre d'envoie mais certains blocs sont ignorés. 

    Il va falloir que j'implémente un autre protocole plus rapide qui me permet de rester dans la fréquence de ma boucle. 

    Actuellement, c'est le protocole USB qui es implémenté coté carte. Coté PC, cette carte est vue comme un port com virtuel. Normalement, je devrais atteindre des vitesses importantes avec ça. Malheureusement, même en augmentent la vitesse coté carte, cela n'améliore pas les choses.



    Il va falloir que j'implémente un autre protocole plus rapide qui me permet de rester dans la fréquence de ma boucle. 

    Actuellement, c'est le protocole USB qui es implémenté coté carte. Coté PC, cette carte est vue comme un port com virtuel. Normalement, je devrais atteindre des vitesses importantes avec ça. Malheureusement, même en augmentent la vitesse coté carte, cela n'améliore pas les choses.

    Est ce que coté PC, la vitesse du port série ne peut pas dépasser un certain seuil ?

    Merci d'avance,

    Cordialement, 

    vendredi 7 mars 2014 10:01
  • Evidemment, la vitesse du port sérié est  limitée à 115200  bauds.

    De l'autre côté,   comme vous communiquez sur USB si j'ai bien compris, la vitesse sera limitée a 460,800 bps.

     

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.


    vendredi 7 mars 2014 10:38