Précédent   Forum des professionnels en informatique > Systèmes > Autres systèmes > Automation
Automation Forum d'entraide sur l'automatisme, la robotique et l'informatique industrielle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 29/09/2008, 17h46   #1
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
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 :
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)
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/09/2008, 22h42   #2
Nouveau Membre du Club
 
Inscription : juin 2007
Messages : 24
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : juin 2007
Messages : 24
Points : 28
Points : 28
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:
Citation:
– 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
sethangel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/09/2008, 22h52   #3
Responsable Visual Basic
 
Avatar de bbil
 
Inscription : juin 2003
Messages : 11 783
Détails du profil
Informations personnelles :
Âge : 45
Localisation : France, Ariège (Midi Pyrénées)

Informations forums :
Inscription : juin 2003
Messages : 11 783
Points : 16 871
Points : 16 871
Envoyer un message via Skype™ à bbil
+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.
bbil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 08h53   #4
Membre régulier
 
Homme
Inscription : novembre 2007
Messages : 81
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : novembre 2007
Messages : 81
Points : 99
Points : 99
+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.)
Poil_dur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 16h28   #5
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
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 :
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
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 17h00   #6
Nouveau Membre du Club
 
Inscription : juin 2007
Messages : 24
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : juin 2007
Messages : 24
Points : 28
Points : 28
En me basant sur les propos de bbil et de Poil_dur une modification de ton code de la sorte devrait être suffisante:

Code :
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 :
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
sethangel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 20h58   #7
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
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 ...
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 21h06   #8
Nouveau Membre du Club
 
Inscription : juin 2007
Messages : 24
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : juin 2007
Messages : 24
Points : 28
Points : 28
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.
sethangel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 21h22   #9
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
Par exemple j'envoie la trame

Citation:
"0503072B0002B4F3" 'Pour avoir la somme des KWh
Le compteur me répond
Citation:
"" qui signifie "050304"
Et pourtant avec leur .exe ca fonctionne, je reçois la trame complete ... (en 8bits)
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/09/2008, 21h30   #10
Nouveau Membre du Club
 
Inscription : juin 2007
Messages : 24
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : juin 2007
Messages : 24
Points : 28
Points : 28
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.
sethangel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/10/2008, 08h52   #11
Membre régulier
 
Homme
Inscription : novembre 2007
Messages : 81
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : novembre 2007
Messages : 81
Points : 99
Points : 99
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
Poil_dur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/10/2008, 11h53   #12
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
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
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/10/2008, 19h33   #13
Responsable outils internes
 
Avatar de Nono40
 
Homme Bruno Guérangé
Ingénieur développement logiciels
Inscription : mai 2002
Messages : 7 899
Détails du profil
Informations personnelles :
Nom : Homme Bruno Guérangé
Âge : 44
Localisation : France, Loir et Cher (Centre)

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

Informations forums :
Inscription : mai 2002
Messages : 7 899
Points : 11 915
Points : 11 915
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 !
Nono40 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/10/2008, 19h55   #14
Membre régulier
 
Avatar de mat-tech
 
Inscription : avril 2006
Messages : 201
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : avril 2006
Messages : 201
Points : 90
Points : 90
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 :
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
__________________
mat-tech est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h50.


 
 
 
 
Partenaires

Hébergement Web