Envoyer commande sur port série [Résolu]

mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 30 août 2010 à 12:11 - Dernière réponse : mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention
- 1 sept. 2010 à 17:04
Bonjour ici.
Voilà, ne connaissant pas bien la classe SerialPort, je ne sais pas comment envoyer une commande sur un port COM.
Par exemple, sur hyperterminal, j'écris ma commande, à destination d'un module GPS, dans son langage d'instruction. Je cherche à faire ça, par l'intermédiaire d'un programme personnel en C#, qui va envoyer la commande saisie sous forme d'une string (en réalité un peu plus complexe que ça, mais la commande est, au final bien envoyée en string, puisque chaque composant est récupéré d'un fichier xml).
il y a bien SerialPort.Write() mais manifestement, ça n'a pas l'air d'être ça (ou bien c'est ma récupération de la réponse qui est foireuse).
Afficher la suite 

28 réponses

Répondre au sujet
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 31 août 2010 à 16:22
+3
Utile
C'est bien Write qu'il faut utiliser

Mais Write à la particularité de faire par défaut les envois en ASCIIEncoding, donc tous les caractères dont le code ascii est supérieur à 127 seront remplacer par ?

Pour pouvoir envoyer ces caractères correctement, il faut passer sur un encoding UTF8, UTF32 ou Unicode, mais alors chaque caractère sera représenté par 2 à 4 octets.

Sinon, (de mémoire d'après divers messages vus sur les forums) il faut convertir la chaine de caractère en tableau de byte et envoyer ce tableau.


[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_casy
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 31 août 2010 à 20:24
+3
Utile
Ah ok, avec un tableau de byte

Effectivement il te faut 2 paramètres de plus qui sont des nombres.
Le premier indique à partir de quel élément dans le tableau l'envoi se fera, le second indique combien d'éléments du tableau seront envoyés.

Donc pour toi, à priori, l'envoi se fera à partir du premier élément (indice 0) et tu enverra la totalité du tableau (soit un nombre égal à la longueur du tableau

Donc quelque chose comme ça :
mySerialPort.Write(data,0,data.Lenght);



[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_casy
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 1 sept. 2010 à 15:53
+3
Utile
Tu peux essayer comme ça

Tu prend ta chaine de commande, brute, tu lui rajoute Environment.Newline, qui normalement sous windows rajoute les caractères CR + LF.
Puis tu envoie le tout avec Write et non pas WriteLine.

Sinon tu converti ta chaine brute en tableau de byte dans un tableau plus grand de 1 ou 2 éléments (suivant ce que tu as besoin). Dans le(ou les 2) dernier(s) élément(s) tu y met manuellement la(es) valeur(s) &h13 (et &h10).
Puis tu balance la totalité du tableau.

[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_casy
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 1 sept. 2010 à 16:56
+3
Utile
t'as quoi comme message d'erreur ???

Essaye peut-être avec la syntaxe
=(byte)0x13;


[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_casy
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 16:55
0
Utile
aah. ok.
J'ai tenté une conversion "forcée" en ASCII, passant donc par un tableau de bytes.
Voici mon code de test. Je ne reçoit aucune réponse de l'appareil branché, en retour de mes commandes. Par contre il m'envoie des messages que je reçois bien.
public partial class MainForm : Form
    {
        SerialPort mySerialPort;
        public MainForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            
            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //                
        }
        
        private void MainFormLoad(object sender, EventArgs e)
        {
            mySerialPort=new SerialPort();            
            //paramètres pour le VT10
            mySerialPort.PortName="COM3";
            mySerialPort.BaudRate = 57600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.Encoding=Encoding.UTF8;
            mySerialPort.DtrEnable = true;
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
        }
        
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // Event for receiving data
            // Read the buffer to text box.
            this.Invoke(new EventHandler(DoUpdate));
        }

        private void DoUpdate(object s, EventArgs e)
        {
            txsortie.Text = txsortie.Text + mySerialPort.ReadExisting();
        }
       
        private void btSend_Click(object sender, EventArgs e)
        {
            // Button to send test data
            try
            {
                string output;
                byte[] data = Encoding.Unicode.GetBytes(txentree.Text);
                output = Encoding.ASCII.GetString(data);
                mySerialPort.WriteLine(output);
            }
            catch (Exception wex)
            {
                MessageBox.Show(wex.ToString());
            }
        } 
        
        void BtOpenClick(object sender, EventArgs e)
        {
            if (mySerialPort.IsOpen == false)

                try
                {
                    mySerialPort.Open();

                    //MessageBox.Show("Port Open");
                }

                catch (Exception oex)
                {

                    MessageBox.Show("Error Opening Port: " + oex.ToString());

                }
        }
        
        void BtCloseClick(object sender, EventArgs e)
        {
            mySerialPort.Close();
        }
    }
Commenter la réponse de mcferson
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 31 août 2010 à 17:17
0
Utile
Attention à WriteLine qui, à la différence de Write, rajoute automatiquement les caractères de saut de ligne (théoriquement CR et LF) à la fin de la chaine envoyée.

As-tu moyen de savoir si tes caractères sont correctement envoyés, en branchant par exemple un terminal (ou autre pc) à la place de ton module GPS ?

[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Commenter la réponse de cs_casy
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 17:22
0
Utile
Je devrais, quand le collègue sera dispo. pour ce qui est de rediriger vers un terminal, je sais pas faire.
suis complètement noob sur ce sujet.
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 17:26
0
Utile
Par contre, si je ne fais pas la reconversion en ASCII et string, je passe comment toute ma chaîne, dans le SerialPort.Write ?
Commenter la réponse de mcferson
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 31 août 2010 à 17:33
0
Utile
de la même façon, remplace WriteLine par Write

[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Commenter la réponse de cs_casy
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 19:30
0
Utile
ok donc là, par exemple :
byte[] data = Encoding.ASCII.GetBytes(txentree.Text);
                mySerialPort.WriteLine(data);
Mais ça me demande plus de paramètre, entre les parenthèses.
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 20:07
0
Utile
-Line (bien sûr).
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 22:14
0
Utile
OK. je testerai comme ça demain. Je dirai ce qu'il en est.
Commenter la réponse de mcferson
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 31 août 2010 à 22:30
0
Utile
Pour tes tests, si tu n'as pas la possibilité de brancher un second PC sur ton port série pour voir si tu envois bien, il existe des logiciels qui permettent de créer des ports virtuels comme par exemple Virtual Serial Port Driver de l'éditeur Eltima (version d'éval 14 jours).

LE principe c'est de créer 2 ports virtuels sur ta machine. Ces 2 ports sont reliés (virtuellement) comme si tu branchais 2 PC sur des ports réels.

Ensuite tu configure ton appli pour utiliser un des 2 ports, il ne te reste qu'à connecter l'hyperterminal (ou autre logiciel) sur le second port, le tout sur le même PC.


[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Commenter la réponse de cs_casy
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 31 août 2010 à 22:33
0
Utile
ah ben j'avais essayé ça avec Com0com. mon appli plantait à la connexion sur le port.
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 1 sept. 2010 à 13:07
0
Utile
Bon alors, résultat des courses : Mon appli fonctionne impeccablement bien. Que j'envoie directement le contenu string de ma textbox ou que je le convertisse en ascii (ou autre). Je reçoie autant que j'envoie, tout est bon.
Sauf, étrangeté, chaque envoie s'inscrit à la suite, pas sur une ligne suivante. Et si j'utilise WriteLine, il y a bien une ligne passée, mais le texte ne s'affiche pas en début de ligne : à la suite du précédent MAIS une ligne en dessous.
Dans ce style là :
testtest$wp+ver$WP+VERtagada
dgfchdfhgf
testsuite
Perturbant. Toujours est-il que le module GPS branché sur le COM3 (à l'origine) ne semble pas recevoir ou comprendre le blabla que je lui balance (saut de ligne ou pas). peut-être à cause de ce détail bizarre.
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 1 sept. 2010 à 13:09
0
Utile
ce maudit forum a reformaté mon exemple, je le remet ici :
testtest$wp+ver$WP+VERtagada
                            dgfchdfhgf
                                      testsuite 
Commenter la réponse de mcferson
cs_casy 7745 Messages postés mercredi 1 septembre 2004Date d'inscription 24 septembre 2014 Dernière intervention - 1 sept. 2010 à 13:29
0
Utile
Oui, j'avais remarqué ça aussi. Cela vient de l'information retour à la ligne ajoutée automatiquement à la fin de la chaine avec la méthode WriteLine et de la façon dont l'interprète le terminal.

Cette information doit être constituée du seul caractère "Saut de ligne" (LF de code ascii 0x10) ou alors elle est constituée des 2 caractères "Saut de ligne" (LF) et "Retour chariot" (CR de code ascii 0x13) mais dans le désordre, c'est à dire LF suivi de CR
Il est vrai qu'habituellement, lorsqu'on envoie les 2 caractères on met le CR avant le LF.


Du coté du terminal, soit il reçoit un seul caractère et l'interprète de façon brute, soit il reçoit les 2 mais n'interprète que le premier. Certains terminaux ont des options pour configurer la façon d'interpréter ces caractères là.

Ensuite, si tu préfère voir le code hexa brut reçu, plutôt que les caractères interprétés par un terminal, tu peux aussi utiliser le petit utilitaire RS232 Hex Com Tool de l'éditeur Virtual Integrated Design (coupure de la connexion toutes les 5 min en version démo)


[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
Commenter la réponse de cs_casy
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 1 sept. 2010 à 15:44
0
Utile
Ok, c'est résolu !
Le problème venait bien du retour à la ligne. WriteLine envoie le code <LF>, surement en premier, et mon module GPS attend, en tout premier lieu, un <CR>. Donc, il ne répondait pas à ce qu'il ne comprenait pas.
Reste donc à coder ce <CR> en fin de ligne (perso, j'ai juste testé avec une textbox multiligne, donc en appuyant sur "Entrée" avant d'envoyer la commande), car le soft complet, lui, va concaténer toute une commande à partir de multiples paramètres et choix dans des listes, etc... PLUS le code <CR>.
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 1 sept. 2010 à 15:59
0
Utile
La première solution fonctionne.
Tout est parfait.

Merci énormément !
Commenter la réponse de mcferson
mcferson 33 Messages postés jeudi 7 septembre 2006Date d'inscription 1 juin 2012 Dernière intervention - 1 sept. 2010 à 16:04
0
Utile
Toutefois, par soucis de portabilité, si cette commande fait un CR que sous Windows, il vaut mieux la deuxième solution.
Commenter la réponse de mcferson

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

envoyer commande sur port série - page 2