basamir
Messages postés335Date d'inscriptionvendredi 21 octobre 2005StatutMembreDernière intervention 8 mars 2008
-
4 avril 2007 à 13:32
42wawa42
Messages postés143Date d'inscriptiondimanche 28 septembre 2003StatutMembreDernière intervention 6 septembre 2011
-
8 avril 2007 à 12:05
bonjour,
j'ai un projet d'étude qui porte sur la communication d'un terminal de pesage (Balance) avec une application que je dois créer.
le port série de mon PC reçoit en continue une trame ayant la forme suivante :
[STX] [8 bits] [Cr]
le but de mon projet est, entre autres, afficher le poids de la balance d'un champ text.
mais je ne sais pas comment récupérer cette trame et la modeler pour l'afficher sous forme de numéro dans le champ Text (p.e: 20600)
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 4 avril 2007 à 13:52
Ne serait-ce pas plutot [STX][8 octets][CR]
Plusieurs possibilités s'offre à toi. Par exemple :
- Tu configure le port pour lire octet par octet et tu analise chaque octet. Dès que tu tombe sur STX, tu reconfigure temporairement le port pour lire 8 octets que tu stocke dans une variable à traiter puis tu te remet à lire octet par octet.
- Tu lit chaque octet que tu empile dans une première variable, dès que tu tombe sur CR, tu prend les 8 derniers octets de la première variable que tu stocke dans une variable à traiter, puis tu réinitialise la première variable et tu recommence.
Autre possibilité un peu plus évoluée : Compte tenu que tu reçoi en permanence, que c'est une balance, par conséquent la vitesse ne doit pas etre bien élevée (9600 ou 19200 bds), tu peut mettre en place un buffer circulaire.
Un buffer circulaire est une variable tampon (buffer) de grande capacité (un tableau de 1024 caractères suffit largement ici) par rapport à la trame à recevoir, associée à 2 taches de traitement. Une première tache se charge de recevoir les caractères sans distinction depuis le port et les stocke dans le tampon. Une seconde tache indépendante se charge de venir lire le tampon et d'en traiter les données. Il te faut 2 pointeurs (index sur le tableau en VB), un à l'entrée pour savoir ou venir écrire les nouveaux octets, un à la sortie pour savoir ou venir lire les octets par encore traiter.
Le principe :
A chaque octet écrit ou lu tu incrémente l'index correspondant, si tu arrive à la fin du tableau pour un index, il repartiera au début (d'où le terme de circulaire). Si les 2 index sont égaux, il n'y a pas de nouveaux caractères à traiter, s'ils sont différents des caractères ne traiter sont présents dans le buffer.
EJ te laisse réfléchir au principe
---- Sevyc64 (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 4 avril 2007 à 13:56
Pardon, j'ai oublié
Pour le buffer circulaire, la tache de traitement aura pour role d'isoler dans les caractères à traiter, la valeur qui t'interesse que tu mettra dans une variable à traiter.
Dans tout les cas, le traitement de la variable àtraiter consistera à récupérer dans les 8 octets, la valeur de l'information qui t'interesse. Probablement avec des fonctions Left, Mid pour découper la chaine de caractères, Val pour convertir en nombre. Mais comme tu veux l'afficher dans une textbx, tu n'aura peut-etre même pas besoin de la convertir en nombre.
---- Sevyc64 (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
basamir
Messages postés335Date d'inscriptionvendredi 21 octobre 2005StatutMembreDernière intervention 8 mars 2008 4 avril 2007 à 17:52
ce que tu dis là est parfaitement ce que j'attends, mais le problème provient de moi car je ne maitrise pas le VB.
par contre pour la conversion en numérique je sais le faire car je dois soustraire deux valeurs prises avec un décalage mais ça c'est une pure gestion de chaine de caractère.
voici comment j'ai procéder pour avoir ce qui est emis par ma balance:
Private Sub Form_Load()
Form1.Caption =
"App2"
With MSComm1
.CommPort = 2 'on utilise le port COM2: car on
utilise 1 PC avec 2 ports COM:
'si vous avez 2
PC, changez en .CommPort=1
!!!
.Handshaking = 2
.RThreshold =
1
.RTSEnable = True
.Settings =
"9600,n,8,1"
.SThreshold = 1
.PortOpen =
True
End With
Text1.Text = ""
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 InBuff As
String
Select Case
MSComm1.CommEvent
' On
effectue la gestion des erreurs (cf. le modèle
ci-dessus)
' Ici, on gère en fait pas
grand-chose, mais c'est pour illustrer la démarche
;)
'liste des
erreurs possibles
Case comEventBreak
'On a reçu un signal
d’interruption (Break)
Case comEventCDTO
' Timeout de la
porteuse
Case comEventCTSTO ' Timeout du signal CTS (Clear To
Send)
Case comEventDSRTO ' Timeout du signal de
réception
Case comEventFrame ' Erreur de trame
Case
comEventOverrun ' Des données
ont été perdues
Case comEventRxOver
' Tampon de réception
saturé
Case comEventRxParity ' Erreur de parité
Case
comEventTxFull ' Tampon
d’envoi saturé
Case comEventDCB ' Erreur de réception DCB (jamais
vu)
'liste des
événements possibles qui sont, eux,
normaux
Case comEvCD 'Changement dans la broche CD
(porteuse)
Case comEvCTS 'Changement dans broche
CTS
Case comEvDSR 'Changement dans broche DSR
(réception)
Case comEvRing 'Changement dans broche RING
(sonnerie)
'Chouette!
on a reçu des données :)
Case
comEvReceive
tampon=MSComm1.Input
Call Traitement(tampon) 'traitement
données
Case comEvSend ' il y a des caractères à
envoyer
Case comEvEOF 'on a reçu le caractère
EOF
End Select
End Sub
mais sur la zone text1.text j'obtiens une série de valeurs envoyées par la balance, p.e:
1200G 1200G 1200G 1200G 1200G 1200G "si cette valeur change" on continue par cette même valeur changé p.e 1220G 1220G 1220G
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 4 avril 2007 à 19:07
Je te propose la fonction Traitement suivant :
Private Sub traitement(rcvstr As String)
Static buffer As String
' Remplissage du buffer avec les caractères reçus
buffer = buffer & rcvstr
' Recherche d'une donnée complete dans le buffer
' c-à-d recherche du caractère de fin de trame CR
Do While (InStr(1, buffer, vbCr) > 0)
i = InStr(1, buffer, vbCr)
' i doit etre >= 9 pour avoir une donnée complete dans le buffer (8 octets + CR)
If i >= 9 Then
' On affiche la partie donnée de la trame
Text1.Text = Trim(Mid(buffer, i - 8, 8))
' On enleve de buffer, les octets déjà traités pour ne pas les traiter dans l'itération suivante
buffer = Mid(buffer, i + 1)
End If
Loop
End Sub<hr />, ----
[code.aspx?ID=41455 By Renfield]
Pense à décalrer tampon correctement dans MsComm1_OnComm, actuellement elle n'est pas déclarée
---- Sevyc64 (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Vous n’avez pas trouvé la réponse que vous recherchez ?
basamir
Messages postés335Date d'inscriptionvendredi 21 octobre 2005StatutMembreDernière intervention 8 mars 2008 5 avril 2007 à 01:44
En fait voici ma fonction de traitement:
Sub traitement(tampon As String)
Dim aData() As String
Dim sDerniereData As String
Text1.SelStart = Len(Text1.Text)
Text1.SelText = CStr(tampon)
aData = Split(tampon, " ") ' Transforme le Tampon en tableau, séparateur "espace"
sDerniereData = aData(UBound(aData)) ' Récupère le dernier élément
If Right$(sDerniereData, 1) = "vbCrlf" Then ' Vérifie la pertinence de la dernière donnée
Text2.Text = Trim(sDerniereData) ' Ok, on l'affiche
Else
' Les 2 derniers caractères ne sont pas corrects (donnée tronquée)
If UBound(aData) > 0 Then ' S'il y a assez de données
sDerniereData = aData(UBound(aData) - 1) ' On prend la précédente
Text2.Text = sDerniereData
Else
' Sinon, on ne touche pas à Text1
End If
End If
End Sub
Mais ça donne des informations en continue dans la zone text1, genre:
22000G 22000G 22000G 22000G 22000G 22000G 22000G 22000G
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 5 avril 2007 à 10:11
Je l'ai testée chez moi avant de te la donner et elle marchait
Est-elle bien appelée au moins?
Met un point d'arret dedant et regarde avec une execution pas à pas ce que se passe exactement
Et vérifie qu'elle correspond au format de la trame que tu reçoit. Je me suis basé sur le format suivant : [STX][8 octets][CR]
<hr size="2" width="100%" />
Concernant ta propre fonction, il est normal que tu obtienne ça dans Text1 puisque tu rajoute systématiquement ce que tu reçoit à la fin du texte présent sans jamais vider la textbox. Les receptions s'accumulent.
En suite dans cette instruction, , tu compare le dernier caractere de la chaine au texte "vbCrlf", ta comparaison ne sera positive que si le dernier caractère reçu est un "v". Il ne faut pas faire la comparaison par rapport au texte "vbCrlf" mais par rapport aux caractères vbCrLf (ATTENTION vbCrLf, c'est 2 caractères, le caractère <CR> suivie du caractère <LF>). Mais ce n'est toujours pas bon. Selon ton protocole, tu ne reçois que le caractère <CR> à la fin de la trame, tu ne reçois pas le caractère <LF>
---- Sevyc64 (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
basamir
Messages postés335Date d'inscriptionvendredi 21 octobre 2005StatutMembreDernière intervention 8 mars 2008 6 avril 2007 à 16:35
tout a fait Cr, beh tu sais je connecte mon terminal à Aspycom et j'espionne ma trame en Hexa et en Ascci.
Crois moi j'ai pris ton code et je l'ai mis dans une fonction et je l'ai appelé au niveau de MsComm1_OnComm avec une déclaration de la variable tampon as string
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 6 avril 2007 à 18:04
Oui il y a un petit bug possible dans ma source. Essaye de déplacer buffer = Mid(buffer, i + 1) après le End If
Sinon plusieurs possibilités, soit le CR n'est pas trouvé dans la trame, soit l'évènement comEvReceive n'est pas déclenché lors de la reception et donc la fonction traitement n'est pas appelée.
Pour ça, il n'y a que toi qui peut le voir. Il faut que tu te mette en deboguage et que tu mette un point d'arret sur l'appel de traitement, tu veras bien si tu passe par cette instruction.
---- Sevyc64 (alias Casy) ----<hr size ="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Dim xPos As Integer
Buffer = Buffer & MSComm1.Input
xPos = InStr(1, Buffer, Chr(2), vbBinaryCompare)
If xPos = 1 Then
Text2.Text = Mid(Buffer, 4, 5)
If Len(Buffer) > 9 Then
Buffer = Right(Buffer, Len(Buffer) - 9)
End If
End If
Text1.Text = Len(Buffer)
End Sub
basamir
Messages postés335Date d'inscriptionvendredi 21 octobre 2005StatutMembreDernière intervention 8 mars 2008 6 avril 2007 à 22:57
ok les gars toutes les solutions que vous me proposier ne sont pas celles qui me convient car peut etre j'ai mal exprimer mon problème.
Voici le code de mon programme:
Private Sub Form_Load()
With MSComm1
.CommPort = 5
.Handshaking = 2
.RThreshold = 1
.RTSEnable = True
.Settings = "9600,n,8,1"
.SThreshold = 1
.PortOpen = True
End With
Text1.Text = ""
End Sub
je travaille avec le port Com 5
voici comment je stocke dans tampon ce que je reçoit du port série:
Private Sub MSComm1_OnComm()
Dim tampon As String
Dim bit_de_trame() As Byte
Select Case MSComm1.CommEvent
' On effectue la gestion des erreurs (cf. le modèle ci-dessus)
' Ici, on gère en fait pas grand-chose, mais c'est pour illustrer la démarche ;)
'liste des erreurs possibles
Case comEventBreak 'On a reçu un signal d’interruption (Break)
Case comEventCDTO ' Timeout de la porteuse
Case comEventCTSTO ' Timeout du signal CTS (Clear To Send)
Case comEventDSRTO ' Timeout du signal de réception
Case comEventFrame ' Erreur de trame
Case comEventOverrun ' Des données ont été perdues
Case comEventRxOver ' Tampon de réception saturé
Case comEventRxParity ' Erreur de parité
Case comEventTxFull ' Tampon d’envoi saturé
Case comEventDCB ' Erreur de réception DCB (jamais vu)
'liste des événements possibles qui sont, eux, normaux
Case comEvCD 'Changement dans la broche CD (porteuse)
Case comEvCTS 'Changement dans broche CTS
Case comEvDSR 'Changement dans broche DSR (réception)
Case comEvRing 'Changement dans broche RING (sonnerie)
tampon = MSComm1.Input
Call traitement4(tampon) 'traitement données
Case comEvSend ' il y a des caractères à envoyer
Case comEvEOF 'on a reçu le caractère EOF
End Select
End Sub
voici la fonction qui renvoie une donnée numérique à mon champ text1 :
Sub traitement4(ByVal InString As String)
Dim temp As String
Dim x As Long
Dim OutString As String
For x = 1 To Len(InString)
temp = Mid$(InString, x, 1)
If temp = Chr$(Xoff) Then
Label6.ForeColor = vbRed
Label6.Caption = "Xoff received"
temp = ""
ElseIf temp = Chr$(Xon) Then
Label6.ForeColor = vbGreen
Label6.Caption = "Xon received"
temp = ""
End If
OutString = OutString & temp
temp = ""
Next x
Call HandleInput(OutString)
End Sub
et la fonction HandleInput:
Sub HandleInput(InBuff As String)
Dim poids As String
poids = Left(Text1.Text & InBuff, 8)
Text1.Text = Right(poids, 5)
End Sub
Voici le problème:
Vue que je communique avec un terminal externe et que je ne suis pas synchronisé avec ce terminal, si j'ai une valeur de 20260 par exemple je peux ne pas avoir que 0260 ou 260 ou 60 ou 0 ou n'importe quelle série de numéro en fonction du moment ou je lis cette valeur et celui de l'envoie de cette meme valeur par le terminal.
ce que je devrait avoir dans mon champ text1 est exactement ce qui est affiché sur mon terminal.
je vous remercie tous
42wawa42
Messages postés143Date d'inscriptiondimanche 28 septembre 2003StatutMembreDernière intervention 6 septembre 2011 7 avril 2007 à 12:10
Hello Basmir,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /??>
J’ai fait marché ton programme sur mon ordinateur la partie RS232 et bonne par contre les routine qui suive ne marche pas. J’ai ajouté un routine qui vas te donné les chiffres. Test et donne moi une réponse merci.
Private Sub Form_Load()
With MSComm1
.CommPort = 5 '5=================================================
.Handshaking = 2
.RThreshold = 1
.RTSEnable = True
.Settings = "9600,n,8,1"
.SThreshold = 0
.PortOpen = True
End With
Text1.Text = ""
End Sub
'je travaille avec le port Com 5
'voici comment je stocke dans tampon ce que je reçoit du port série:
Private Sub MSComm1_OnComm1()
Dim tampon As String
Dim bit_de_trame() As Byte
Select Case MSComm1.CommEvent
' On effectue la gestion des erreurs (cf. le modèle ci-dessus)
' Ici, on gère en fait pas grand-chose, mais c'est pour illustrer la démarche ;)
'liste des erreurs possibles
Case comEventBreak 'On a reçu un signal d'interruption (Break)
Case comEventCDTO ' Timeout de la porteuse
Case comEventCTSTO ' Timeout du signal CTS (Clear To Send)
Case comEventDSRTO ' Timeout du signal de réception
Case comEventFrame ' Erreur de trame
Case comEventOverrun ' Des données ont été perdues
Case comEventRxOver ' Tampon de réception saturé
Case comEventRxParity ' Erreur de parité
Case comEventTxFull ' Tampon d'envoi saturé
Case comEventDCB ' Erreur de réception DCB (jamais vu)
'liste des événements possibles qui sont, eux, normaux
Case comEvCD 'Changement dans la broche CD (porteuse)
Case comEvCTS 'Changement dans broche CTS
Case comEvDSR 'Changement dans broche DSR (réception)
Case comEvRing 'Changement dans broche RING (sonnerie)
tampon = MSComm1.Input
Call traitement4(tampon) 'traitement données
Case comEvSend ' il y a des caractères à envoyer
Case comEvEOF 'on a reçu le caractère EOF
End Select
End Sub
'voici la fonction qui renvoie une donnée numérique à mon champ text1 :
Sub traitement4(ByVal InString As String)
Dim temp As String
Dim x As Long
Dim OutString As String
For x = 1 To Len(InString)
temp = Mid$(InString, x, 1)
If temp = Chr$(Xoff) Then
Label6.ForeColor = vbRed
Label6.Caption = "Xoff received"
temp = ""
ElseIf temp = Chr$(Xon) Then
Label6.ForeColor = vbGreen
Label6.Caption = "Xon received"
temp = ""
End If
OutString = OutString & temp
temp = ""
Next x
Call HandleInput(OutString)
End Sub
'et la fonction HandleInput:
Sub HandleInput(InBuff As String)
Dim poids As String
poids = Left(Text1.Text & InBuff, 8)
Text1.Text = Right(poids, 5)
End Sub
Private Sub MSComm1_OnComm()
Dim xPos As Integer
Buffer = Buffer & MSComm1.Input
xPos = InStr(1, Buffer, Chr(2), vbBinaryCompare)
If xPos = 1 Then
Text1.Text = Mid(Buffer, 4, 5)
If Len(Buffer) > 9 Then
Buffer = Right(Buffer, Len(Buffer) - 9)
End If
End If
'Text2.Text = Len(Buffer)
End Sub