IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Découper une trame série RS232


Sujet :

VB.NET

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut Découper une trame série RS232
    Bonjour,

    J'ai une machine reliée sur le port série de mon PC qui m'envoie une trame de données de 5 octets plusieurs dizaines de fois par seconde :

    0D 02 59 01 F2

    (c'est un exemple, la trame est en hexadécimal, j'ai séparé les octets par un espace pour que ce soit plus visible)

    Le premier octet est le délimiteur de début de la trame : il est toujours le même (0D)

    Le 2eme et 3eme octet (02 59) représentent une valeur qui va de 0 a 65535, le 2eme octet est donc l'octet de poids fort et le 3eme l'octet de poids faible (cela donnerait 601 en décimal donc)

    Le 4eme octet (01) est une autre valeur qui va de 0 à 255 (ici 1).

    Et le 5eme octet (F2) est une autre valeur qui va de 0 à 255 (ici 242).


    La question est que je ne sais pas comment scinder cette trame, j'aimerais récupérer les 3 valeurs utiles dans des variables utilisables par VB (genre VarA, VarB, VarC as integer) et qu'elles soient actualisées a chaque variation des variables dans la trame.
    Merci

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    quand tu recois des octets, tu les ajoutes dans une collection (list(of byte))
    juste après (dans la même méthode donc) tu regardes si la collection contient au moins un octet de début de trame et 4 octets derrière (boucle sur chaque item)
    si c'est pas le cas tu ne fais rien (ca peut arriver, la réception des octets peut parfois se faire sur plusieurs events, bien que dans ton cas ca devrait être rare)

    si tu as une trame complète tu peux alors découper et traduire les données
    suppression des éléments avant l'octet de début ; ca peut paraitre étrange mais c'est pour coder propre
    si tu reçois 2 trames donc une a été parasité et l'octet de début a été modifié (un cable série ca peut bugger, et il n'y a pas forcément de correction d'erreur) alors tu va te retrouver avec quelque chose d'erroné, il faut donc bien commencer la lecture à l'endroit du 1er caractère de début trouvé
    traduction des 5 octets, puis suppression de ceux ci de la collection

    pour la traduction, il y a bitconverter.getint16 qui devrait te servir


    après tu mets tout ca dans une classe avec un songleton, des propriétés pour les données, et une propriété avec la date de dernière lecture réussie
    comme ca tu pourras aussi savoir si le dialogue fonctionne toujours

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci mais ça m'a l'air un peu compliqué pour ce que je veux faire

    En fait j'ai une routine qui tourne en fond et me lit chaque ligne de mon port série (délimitée par le caractère ASCII "0D" donc) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     Private Sub rxthread_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles rxthread.DoWork
     
            Do While serialport.IsOpen
     
                serialport.NewLine() = ChrW(13)
                rx = serialport.ReadLine()
     
            Loop
     
        End Sub
    Donc l'idée serait de découper "rx"

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    développer ce n'est pas toujours une ligne de code simple qui fait tout ...

  5. #5
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    développer ce n'est pas toujours une ligne de code simple qui fait tout ...
    Eh oui je sais bien, vu que j'ai développé le firmware de ma machine sur microcontrolleur... le truc c'est que la programmation sur microcontrolleur (interruptions, etc) est bien différente de la programmation sur PC que je trouve trop "abstraite" (surtout avec les outils Microsoft).

    Alors je t'avoue que je ne veux pas trop perdre de temps sur VB, surtout que c'est pas la lune ce que je veux faire, je veux juste afficher mes valeurs dans une fenêtre

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    je sais ce que c'est, moi je galère sur des arduinos car je trouve ce langage trop bas niveau alors que la programmation PC je trouve ça simple, surtout avec les outils microsoft ^^
    (comme quoi tout est subjectif)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
       serialport.NewLine() = ChrW(13)
     
       While serialport.IsOpen
                Dim rx = serialport.ReadLine()
                Dim bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(rx)
                If bytes.Count <> 5 OrElse bytes(0) <> &H0D Then Continue While 'trame érronée on ne la traite pas
     
                Dim v1 = BitConverter.ToInt16(bytes, 1)
                Dim v2 = bytes(3)
                Dim v3 = bytes(4)
     
                ' via le backgroundworker on est sur un thread secondaire, qui n'a pas le droit de modifier l'interface, donc il faut passer par me.invoke
                Me.Invoke(Sub()
                              Me.label1.text = v1.ToString
                              ' ...
                          End Sub)
         End While
    et tu n'avais pas précisé que ta trame se finissait par un chr13

  7. #7
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci de ton aide je vais essayer ça ^^

    La trame ne finit pas par un chr13, mais elle commence par un chr13. Chaque chr13 indique une nouvelle trame.

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    Citation Envoyé par pxidr Voir le message
    Merci de ton aide je vais essayer ça ^^

    La trame ne finit pas par un chr13, mais elle commence par un chr13. Chaque chr13 indique une nouvelle trame.
    dans ce cas mon code est faux (je n'utilise "jamais" l'hexa, et je viens de me rendre compte que OD = 13 ^^)

    mais bon tu peux l'adapter (par exemple c'est byte(4) qui à comparer à &H0D vu qu'il est à la fin par le découpage, et pour lignes v1 à v3 il faut faire -1 sur les nombres (0,2,4))

  9. #9
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2013
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juillet 2013
    Messages : 235
    Points : 359
    Points
    359
    Par défaut
    Bonjour à tous,
    Je suis justement sur un projet qui utilise une sonde (co2/humidité/température), tout comme pxidr en rs-232, sauf que les valeurs arrivent que deux fois par seconde.

    Voici le code que j'aurais utilisé dans ton cas:
    (Fait le test, créé un nouveau projet et colle ce code)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    Option Strict On
    Option Explicit On
    Imports System.IO.Ports
     
    Public Class Form1
        Public WithEvents SerialPort1 As SerialPort = New System.IO.Ports.SerialPort
        Dim TexteRecu As New TextBox
        Delegate Sub SetTextCallback(ByVal Recu As String)
        Dim VarA, VarB, VarC As Integer
     
        Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If SerialPort1.IsOpen Then SerialPort1.Close()
        End Sub
     
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.Controls.Add(TexteRecu)
            TexteRecu.Size = New Size(TexteRecu.Width * 2, TexteRecu.Height)
            AddHandler TexteRecu.TextChanged, AddressOf TextRecu_TextChanged
            With SerialPort1
                .BaudRate = 9600
                .Parity = Parity.None
                .DataBits = 8
                .StopBits = StopBits.One
                .PortName = "COM3" 'à changer au besoin
                .Open()
            End With
        End Sub
     
        Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
            System.Threading.Thread.Sleep(100) 'une pause de 100ms
            Try
                SetText(SerialPort1.ReadExisting())
            Catch ex As Exception
            End Try
        End Sub
     
        Private Sub SetText(ByVal Recu As String)
            If Me.TexteRecu.InvokeRequired Then
                Dim d As New SetTextCallback(AddressOf SetText)
                Me.BeginInvoke(d, New Object() {Recu})
            Else
                Me.TexteRecu.Text = Recu
            End If
        End Sub
     
        Private Sub TextRecu_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
            If TexteRecu.Text.StartsWith("0D") And TexteRecu.TextLength = 10 Then
                VarA = (Convert.ToInt32(TexteRecu.Text.ToCharArray(2, 2), 16) * 256) + Convert.ToInt32(TexteRecu.Text.ToCharArray(4, 2), 16)
                VarB = Convert.ToInt32(TexteRecu.Text.ToCharArray(6, 2), 16)
                VarC = Convert.ToInt32(TexteRecu.Text.ToCharArray(8, 2), 16)
                Me.Text = VarA & " " & VarB & " " & VarC
            End If
        End Sub
     
    End Class
    A+

  10. #10
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci à vous 2.

    Alors je me suis inspiré de vos codes, et je suis arrivé à ça, et cela fonctionne relativement bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     Private Sub rxthread_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles rxthread.DoWork
     
     
            Do While serialport.IsOpen
     
                serialport.NewLine() = ChrW(13)
                rx = serialport.ReadLine()
     
                If rx.Length = 4 Then
     
                    var1 = Asc(rx.Substring(0, 1)) * 256 + Asc(rx.Substring(1, 1))
                    var2= Asc(rx.Substring(2, 1))
                    var3 = Asc(rx.Substring(3, 1))
     
                 End If
     
                       info_refresh()
     
            Loop
     
      End Sub
     
     
    End Class
    J'arrive bien à récupérer mes variables avec ce bout de code.

    En gros je me place ou il faut dans la chaine "rx" avec rx.Substring() et je convertis la valeur ASCII associée en valeur décimale.

    Bon effectivement ça marche, mais je trouve pas ça très propre niveau code... j'aimerais directement lire les octets...

  11. #11
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2013
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juillet 2013
    Messages : 235
    Points : 359
    Points
    359
    Par défaut
    Re:
    Oui... mais Asc() c'est du vb6 pas du .net
    De plus tu fais une boucle do:loop qui risque de te bloquer plus loin dans ton appli même si tu l’exécutes dans un backgroundworker

    Histoire de mieux comprendre,
    Essaye le code que je t'ai envoyé tel quel sur un nouveau projet, je t'ai même fait les conversions, tu n'as qu'à faire un copier/coller du code
    la lecture du serialport se fait dans un autre thread aussi (ce que tu voulais faire avec le backgroundworker)

    A+

  12. #12
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Salut,

    Excuse je me suis absenté quelques jours.

    Alors j'ai tenté ton code, et il ne fonctionne pas (j'ai bien sur modifié les paramètres du port série pour mes besoins).

    La boite de dialogue m'affiche n'importe quoi (mais ça prouve que les données arrivent bien).

    Mais en regardant ton bout de code, j'ai l'impression qu'il essaye de décoder des caractères ASCII, or ma machine m'envoie du HEX directement (pour 0D par exemple, elle m'envoie pas les lettres "0" et "D", mais directement la valeur 0D (13 en décimal).

  13. #13
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2013
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juillet 2013
    Messages : 235
    Points : 359
    Points
    359
    Par défaut
    Re:

    Excuse je me suis absenté quelques jours.
    Pas grave on a tous un boulot supplémentaire...

    Alors soit ce qu tu reçois ne commence pas par "0D" soit sa longueur (nombre de caractères) n'est pas 10.
    souvent il arrive à certains systèmes de finir par 'CRLF' soit par le chr 10 et 13 (ou un des deux), ce qui est invisible

  14. #14
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Es tu sur de ton coup? 0D est égal à 13 ce qui correspond au caractère de fin de ligne (clf). Ne pense tu pas que tu décale ton texte 5 octets plus vbcrlf ce qui fait 7 octets!

    01 02 03 04 05 0A 0D
    En considérant 0D comme le début de ligne tu fais un décalage Enfin je pense!

    Sur la première trame tu prend 5 octets en reculant le vbcrlf, sur la trame de tu ne prend 0D comme premier octets alors que le premier ce trouve après, donc tu décale!

    Comme gérés tu ton port série? Tu le bufférise?

    Si tu as des caractères après 0D c'est que tu reçois une phrase donc plusieurs lignes, il faut spliter mer retour chariot.
    Dernière modification par Invité ; 12/12/2015 à 16h43.

Discussions similaires

  1. [PIC] Capture d'une trame série
    Par lcoulon dans le forum C
    Réponses: 1
    Dernier message: 18/04/2009, 17h52
  2. Réponses: 1
    Dernier message: 08/03/2009, 17h55
  3. Affichage incomplet après réception d'une trame via RS232
    Par sroge dans le forum Composants VCL
    Réponses: 3
    Dernier message: 01/02/2008, 15h50
  4. acquerir une trame nmea rs232(serie)>PIC
    Par strygolw dans le forum C
    Réponses: 7
    Dernier message: 06/05/2007, 14h17
  5. Comment capturer les données sur une liaison série RS232
    Par jef Orome dans le forum Windows Serveur
    Réponses: 3
    Dernier message: 02/04/2007, 18h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo