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

Automation Discussion :

VB6 et Mscomm Problème dans la Trame Reçue Modbus


Sujet :

Automation

  1. #1
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut VB6 et Mscomm Problème dans la Trame Reçue Modbus
    Bonjour,
    Je dois communiquer avec un compteur, en Modbus depuis hier et grâce à vous (le forum), j'arrive à envoyer des trames vers ce compteur, le problème est que les Trames que je reçois en réponse sont incomplètes, et elles varient (je ne reçois pas toujours le même nombre d'octet .
    Je vous avoue que la j'ai vraiment besoin de vos lumières, car le fabricant m'a envoyé un petit .exe qui permet de tester la communication, et avec son programme la je reçois toujours la bonne Trame(complete !)
    Voici les 2 codes, pour envoyer et pour recevoir.

    Code :
    Code vb : 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
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    Option Explicit
     
    Private Sub Form_Load()
    Form1.Caption = "App2"
    With MSComm1
    .CommPort = 1 'on utilise le port COM1
    .Handshaking = 2
    .RThreshold = 1
    .RTSEnable = True
    .Settings = "9600,n,8,1"
    .SThreshold = 1
    .PortOpen = True
    End With
    Text1.Text = ""
    Check1.Value = False
    Command1.Caption = "&Send"
    End Sub
     
    Private Sub Command1_Click()
    Dim i As Integer
    Dim st As String
    Dim buffer As String
     
    Text1.Text = ""
    st = "0503072B0002B4F3" 'Pour avoir la somme des KWh
    For i = 1 To Len(st) Step 2
        buffer = buffer & Chr(Val("&h" & Mid(st, i, 2)))
    Next
    MSComm1.Output = buffer
     
    End Sub
     
    Private Sub Command2_Click()
    Dim stRecue, st, st2, st3 As String
    Dim i As Integer
     
    stRecue = Text1.Text 'la chaine récupéré
    For i = 1 To Len(stRecue)
        st = st & Right("0" & Hex(Asc(Mid(stRecue, i, 1))), 2)
    Next
    MsgBox st
    End Sub
     
    Private Sub Form_Unload(Cancel As Integer)
    MSComm1.PortOpen = False 'on ferme le port quand l'appli quitte
    End Sub
     
    Private Sub MSComm1_OnComm()
    Dim Tampon As String
     
    Select Case MSComm1.CommEvent
    Case comEvReceive
    Tampon = MSComm1.Input
    Call Traitement(Tampon) 'traitement données
     
    End Select
    End Sub
     
    Sub Traitement(Chaine As String)
    'cette procédure sert à traiter l’information reçue dans le tampon
         Text1.SelStart = Len(Text1.Text)
         Text1.SelText = Chaine 'ici, on affiche le résultat dans un champ de texte
    End Sub

    Pour la documentation du compteur (ICI)
    Pour la documentation du convertisseur (ICI)

  2. #2
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2007
    Messages : 25
    Points : 31
    Points
    31
    Par défaut A tout hasard
    Bonjour,
    Le problème ne pourrait -il pas venir du fait que tu n'attends pas la fin de l'envoi de la trame ?

    j'ai trouvé ceci sur le net:
    – Input : cette méthode permet de recevoir des données sur le port COM. Ici, une explication s’impose : le port série stocke les données arrivant au système dans une mémoire tampon interne qui vaut par défaut 1024 octets. Si la mémoire tampon est saturée et que de nouvelles données arrivent, celles-ci sont perdues. Il est donc impératif de recopier les données dans une chaîne de caractères, par exemple :

    Dim tampon$
    Tampon$ = Tampon$ & MSComm1.Input

    Bien sûr, cela doit être fait de façon répétitive tant que des données arrivent sur le port. En général, les données se terminent par un caractère de terminaison (si-si!), qui nous fera savoir que la transmission est terminée.

    Par exemple, on attend ici des données terminées par "OK" suivi de retour à la ligne :
    Do
    DoEvents 'indispensable sinon ça marche pas!!!
    Tampon$ = Tampon$ & MSComm1.Input
    Loop Until InStr(Tampon$, "OK" & vbCrLf)

    Source: http://grafikm.developpez.com/portcomm/
    Dans ton cas, au lieu d'attendre le ok et le vbcrlf, il te suffirait d'attendre d'avoir le bon nombre d'octets étant donné que celui-ci est fixe.
    En espérant que cela puisse t'aider
    Bonne continuation

  3. #3
    Expert éminent sénior


    Profil pro
    Inscrit en
    Juin 2003
    Messages
    14 008
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 14 008
    Points : 20 038
    Points
    20 038
    Par défaut
    +1, je pense aussi que sethangel , as mis le doigt sur ton probléme, sauf qu'en modbus les longueurs des trames ne sont pas fixe ,elles dépendent de la requête (type , nombre d'octets à lire ou écrire , réponse ok ou pas...

    habituellement la fin des trames modbus série.. et "réglable" par un temps inter-caractéres maximum, lorsque le temps après la réception d'un caractère dépasse celui-ci la trame est terminée.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    +1, ça doit venir de la gestion un peu "rapide" de l'événement OnComm().
    Les données reçues sont bufferisées, tu peux donc récupérer le contenu du tampon de réception au bout d'un délai raisonnable (lecture de 2 mots => réponse de 2*2+5=9 octets, à 9600 bps => 90ms), disons 100 ms pour ta requète. L'avantage de lire les données reçues au bout de ce délai, c'est que tu récupères la réponse entière, quelle qu'elle soit, que ce soit la réponse attendue (les 9 octets ici) ou une réponse d'exception (qui fera 5 octets, au cas où la requète ne soit pas traitable, par ex.)

  5. #5
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut
    Bonjour le forum et merci pour vos réponses,

    Je ne sais pas tester directement dans mon programme, car je suis pas au travail, mais si j'ai bien compris, je dois juste ajouter un delais d'atente lors de la reception de données.
    Mais j'ai besoin de vous car je ne sais pas du tout à qul moment je dois effectué ce delais d'attente.
    J'imagine que ca va être quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Sleep (100)
    TailleOctetTampon = MSComm1.InBufferCount
    
    Do Until MSComm1.InBufferCount >= TailleOctetTampon
        DoEvents
    Loop
    Mais si vous pouvez me, donner la procedure exacte car la, je ne sais pas du tout ...

    Merci

  6. #6
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2007
    Messages : 25
    Points : 31
    Points
    31
    Par défaut
    En me basant sur les propos de bbil et de Poil_dur une modification de ton code de la sorte devrait être suffisante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Private Sub MSComm1_OnComm()
    Dim Tampon As String
     
    Select Case MSComm1.CommEvent
    Case comEvReceive
    sleep(100)
    Tampon = MSComm1.Input
    Call Traitement(Tampon) 'traitement données
     
    End Select
    End Sub
    A condition que le sleep ne bloque pas la réception de ton MSComm.
    Dans ce cas il faudrait plutôt remplacer le sleep(100) par une boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i = 0 to 10
     sleep(10)
    Tampon = Tampon & MSComm1.Input
    next
    Pas forcément très propre mais devrait être efficace.

    Bon courage

  7. #7
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut
    Bonsoir et merçi pour votre aide,
    mais malheureusement j'ai testé pas de mal de chose(S) mais toujours les mêmes trames "incompletes"
    J'implore votre aide ...

  8. #8
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2007
    Messages : 25
    Points : 31
    Points
    31
    Par défaut
    J'avoue que je suis un peu sec, pourrais-tu nous indiquer, ce que tu reçois dans tes trames ?
    Si tu peux nous en mettre quelques unes en exemple des fois que cela nous inspire quelque chose.

  9. #9
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut
    Par exemple j'envoie la trame

    "0503072B0002B4F3" 'Pour avoir la somme des KWh
    Le compteur me répond
    "" qui signifie "050304"
    Et pourtant avec leur .exe ca fonctionne, je reçois la trame complete ... (en 8bits)

  10. #10
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2007
    Messages : 25
    Points : 31
    Points
    31
    Par défaut
    Je pense que tu as déjà essayé, mais as tu tenté de ne pas lire directement le buffer à réception, juste de te mettre un message, puis écrire un autre bouton, qui ira lire dans le buffer de réception de ton mscomm ?
    tu pourrais aussi essayer (pour vérifier que le problème vient bien de la réception de ton mscomm de faire une boucle do loop comme j'ai expliqué précédemment et d'attendre ton crc (il faut bien sûr l'avoir calculé en fonction de ce qu'indique le compteur).
    Désolé, je demande beaucoup de choses mais j'essaye en même temps de comprendre ce qui peut bloquer.

  11. #11
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Hello,

    perso, je ferais comme ça:

    garder le traitement de l'événement OnComm(), en virant l'appel à Traitement(tampon) (l'événement OnComm() se contente de "manger" les octets au fur et à mesure de leur réception, en les concaténant dans tampon);

    gérer le délai d'attente de réponse par un timer, activé lors de l'envoi de la requète, et cadencé à 100ms, c'est l'événement OnTimer() (de mémoire) qui fera appel à Traitement(tampon).

    L'avantage, c'est que tu pourras facilement régler le délai d'attente pour être sûr d'avoir tous les octets de la trame de réponse, en mettant 2000ms pour la durée du timer, par exemple.

    Manifestement, tu ne reçois que les premiers octets de la réponse du compteur, et ça ressemble à quelque chose de bon (adresse esclave OK, code fonction aussi, 4 octets de données ce qui est attendu), reste à choper les données et le CRC. T'en es plus très loin, là, faut pas débander !
    Courage

  12. #12
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut
    Bonjour le forum,
    j'ai trouvé quelque chose, bon déjà chose importante la transmission fonctionne et la réception aussi (depuis le début), le problème était simplement du au fait que j'envoyé le tampon dans un textbox qui apparemment n'affichait pas tout, pourquoi je ne sais pas; pour faire un test je me suis dit je vais afficher dans un MsgBox, et la surprise il m'affiche la trame complète

    J'ai même pu retirer le "Sleep (1000)", le Do Loop ...
    Ca fonctionne , grâce à Vous !

    Bon maintenant je vais continuer mon programme, a savoir
    1) vérifier la taille du message reçu
    2) tester le CRC
    3) Traduire la valeur reçu
    4) Envoyer les données vers une base de données

    5) Pouvoir récupérer les données de la base de données en fonction d'une requête

    Si vous avez, des conseils à me donner, je vous écoute avec grande attention

  13. #13
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut
    Le textbox n'affiche pas tout car il s'arrète qur le premier #0 rencontré.

    Windows est écrit en C et utilise partout le #0 quand fin de chaine. QUand tu travailles sur des octets de la sorte, tranforme-les en hexa avec de les afficher ce sera beaucoup plus facile à lire.

    Pour le CRC tu devrais trouver sur le nET pal mal de sources pour le calculer. (j'en ai un mais c'est en Delphi)
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  14. #14
    Membre régulier Avatar de mat-tech
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    202
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 202
    Points : 124
    Points
    124
    Par défaut
    Quand c'est simplement expliqué "Tout est plus claire !"

    pour le CRC, j'ai trouvé quelques sources intéressantes, mais je vais utiliser c'elle de Mr Bbil

    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
    'Source bbil (www.developpez.com)
    ' Contrôle de CRC16 pour trame ModBus
    '
    Function VerifCRC16(stTrame As String)
     Dim i As Integer
     Dim cRc As Long
     Dim b As Byte
     Dim stCRC As String
      cRc = 65535
     stTrame = Replace(stTrame, " ", "")
     For i = 1 To (Len(stTrame) - 4) Step 2
       b = Val("&h" & Mid(stTrame, i, 2))
       cRc = cRc Xor b
       For j = 0 To 7
         
         If ((cRc And 1) = 1) Then
              cRc = (cRc \ 2) Xor CLng("&HA001") 'Si Retenue.. XOR avec 40961
          Else
             cRc = (cRc \ 2)  ' Décalage d'un bit vers la droite
          End If
        Next j
       Next i
       stCRC = Right("0000" & Hex(cRc), 4)
       'Swap..
       stCRC = Right(stCRC, 2) & Left(stCRC, 2)
       Debug.Print "CRC Trouvé : " & stCRC
       VerifCRC16 = Right(stTrame, 4) = stCRC
     
     End Function
    Sub Test()
       If VerifCRC16("0503072B0002B4F3") Then MsgBox "Trame OK"
    End Sub

Discussions similaires

  1. [XL-2010] Problème Mscomm.input dans boucle Do
    Par mentat dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 27/02/2012, 11h41
  2. VB6 et Mscomm Problème dans la Trame Reçue Modbus
    Par mat-tech dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 29/09/2008, 17h46
  3. [VB6] Copie graphique excel dans picturebox (problème)
    Par Xerath dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 10/01/2008, 15h47
  4. problème dans l'affichage sur word (VB6)
    Par rupeni dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 23/11/2005, 12h40
  5. [VB6] [MDI] Menus contextuels dans les filles
    Par Rosec dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 16/09/2002, 14h00

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