Protocole modbus

fbillard Messages postés 1 Date d'inscription mercredi 20 août 2003 Statut Membre Dernière intervention 21 août 2003 - 21 août 2003 à 18:36
 krypton67 - 4 févr. 2013 à 10:38
Salut
je vois que nous sommes pas les seuls dans la galere avec ce protocole !!

NOus avons un indicateur utilisant le protocole modbus, nous avons recuperé le prog calcul crc de cyrille qui marche bien, cepedant lorsque l'on envoie la trame nous n'avons pas de réponse !!!
Comment envoyer la trame en VB pour ce faire comprendre ?

urgent, merci
dmretude@wanadoo.fr
A voir également:

16 réponses

cs_liquide Messages postés 1016 Date d'inscription samedi 22 mars 2003 Statut Membre Dernière intervention 24 juin 2008
21 août 2003 à 19:08
liquide
Pas de reponse, mais ne connaissant pas, peux tu m'expliquer a quoi cela sert et quelles sont ses fonctionnalités en qqes mots pour mon info perso et dormir moins con se soir, merci d'avance.
0
sunlightdada Messages postés 1 Date d'inscription samedi 22 avril 2006 Statut Membre Dernière intervention 24 avril 2006
24 avril 2006 à 22:28
Moi aussi je dois communiquer avec un compteur d'énergie électrique à l'aide d'une application en VB; quand j'envois les trames je reçois pas réponses!!! pour être plus claire j'ai relié le compteur (RS485) à un convertisseur RS232-RS485 puis au port série du PC; et j'ai essayé d'envoyer les trames via un petit programme en VB mais pas de réponse. puis-je avoir de l'aide plz!!! merci d'avance
e-mail : adadi_dalale@yahoo.fr
0
Adn56 Messages postés 1172 Date d'inscription jeudi 24 mai 2007 Statut Membre Dernière intervention 28 septembre 2013 1
4 janv. 2008 à 17:51
Je pense (pour faire les test en ce moment avec un twido) que cela vient du fait que VB utilise les decimale, alors que les API utilise l'héxa !
EX : j'envoie une trame modbus via mon api :
020300000004+CRC pour :
02 = n° exclave
03 = type de requéte ,03=lecture de N mots
0000 = N° du premier mot à lire
0004 = Nb de mots à lire
et le CRC
tout ceci en HEXA !
mais voila VB lui traite cela comme de l'ascii -_-'
Pire il écrit à son tour en DEC ! du style je veux 0A et me place un 010 ! du coup la trame est nul et le CRC totalement à l'ouest !
Voici les tests que je fais en ce moment, si d'autre on une soluce c'est le moment de la placer
amicalement @dn

Tiens les balises ne sont pas reconnues ^_____^, zut alors.....
0
MCSilver Messages postés 13 Date d'inscription mercredi 25 octobre 2006 Statut Membre Dernière intervention 6 janvier 2011
9 août 2008 à 05:28
Il faut utiliser la fonction Chr(Integer).

Par exemple, pour envoyer une requête de lecture du registre 400011 à une device dont l'adresse ModBus est 9, l'on doit construire la chaîne d'envoir de cette façon:

SendString=Chr(9) & Chr(3) & Chr(0) & Chr(10) & Chr(0) & Chr(1) & Chr(2) & Chr(CRC_Hi) & Chr(CRC_Lo)

Ensuite, envoyer SendString sur le port.

Cet exemple est valide en VB5 et en .NET

CiaO!
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_vince42 Messages postés 9 Date d'inscription vendredi 10 avril 2009 Statut Membre Dernière intervention 24 mars 2011
20 août 2009 à 08:30
Bonjour,

Je suis dans le même cas, je dois communiquer avec un fuitomètre ATEQ via le protocole Modbus RTU (RS232) avec une application que je développe en VB Express 2008 et le souci est que :

Comme MCSilver, je génère la trame avec la fonction Chr(xxx), cela marche très bien en VB6 mais en VB Express 2008, le résultat du Chr(0) retourne "Nothing" du coup ma trame avec le calcul du CRC est fausse car le Chr(0) considère comme une fin de chaine de caractères.

Je n'ai pas encore trouvé de solution, si quelqu'un peut m'aider.

Merci d'avance
0
cs_vince42 Messages postés 9 Date d'inscription vendredi 10 avril 2009 Statut Membre Dernière intervention 24 mars 2011
3 sept. 2009 à 10:34
Bonjour,

J'ai réussi à contourner le problème en utilisant un tableau d'octets que j'envoie via la RS232 et ça marche.

A+
0
Adn56 Messages postés 1172 Date d'inscription jeudi 24 mai 2007 Statut Membre Dernière intervention 28 septembre 2013 1
3 sept. 2009 à 13:07
Salut, Bien joué
peux tu poster l'exemple stp que je vois comment tu t'y prends
d'avance merci.

Tiens les balises ne sont pas reconnues ^_____^, zut alors.....
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
5 janv. 2011 à 12:56
Bonjour,
je up ce topic car j'ai le même problème et je galère
je dois développer un logiciel qui permet à un pc de communiquer avec un automate en Modbus par une liaison rs485, le tout en VB.NET
je cherche depuis 2 jours et je ne trouve pas beaucoup d'aide à ce sujet.
Je connais le format de ma trame, je connais le calcul du CRC mais je ne sais pas comment envoyer ma trame en héxa sur le port série avec la méthode "serialport.Write".

vince42 parle de mettre les valeurs dans un tableau d'octet, ok mais en décimal ? en hexa ? et comment les envoyer avec la méthode serialport.Write qui n'accepte que les string ?

merci d'avance
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
6 janv. 2011 à 11:09
J'ai eu une réponse en mp, j'en fais profiter tout le monde même si ça n'a pas résolu mon problème :


Citation de MCSilver

Salut C4rr3r4, en réponse à ton appel à l'aide pour transformer une chaîne de byte en string:

Disons que l'on veut lire le registre 400011 de l'équipement à l'adresse ModBus 9, il faut envoyer (en décimal et peut importe la méthode choisie pour l'envoyer sur le port):
9,3,0,10,0,1,CRC_Hi,CRC_Lo

Maintenant, pour arricher à obtenir cette chaîne de caractères dans une String:
Dim MyString as String
MyString=Chr(9) & Chr(3) & Chr(0) & Chr(10) & Chr(0) & Chr(1) & Chr(2) & Chr(CRC_Hi) & Chr(CRC_Lo)
*Sache que tu ne pourras valider le contenu de cette trame car étant une variable string, à l'affichage, VB essaiera d'afficher le caractère ASCII 0, qui n'est pas un caractère affichable, il le remplacera par un autre caractère genre "|"*

Pour obtenir une chaîne de Byte dans un tableau:
Dim MyArrByte(9) as Byte
MyArrByte(0)=9
MyArrByte(1)=3
....
MyArrByte(8)=CRCHi
MyArrByte(9)=CRCLo

Il y a une 3e méthode proposée par SerialPort.Write (Char,Int, Int). Ne l'utilise par c'est incompatible avec le ModBus (les paramètres de trame ne peuvent pas êtres signés (-1 à -127, ils doivent demeurer dans une plage positive 0 à 255).

Voilà, n'hésites pas si tu as d'autre Q. Bonne chance.


Auquel j'ai répondu :

Salut, merci de m'avoir répondu :)
je t'explique la situation plus en détail, c'est tout simple.
J'ai un automate (iSmart SMT-CD-R20), sur cette automate j'ai une lumière branchée sur une sortie, et je dois créer un logiciel pour allumer cette lumière en envoyant une trame Modbus (supporté par l'automate).
Mon programme est très simpliste, j'ai une interface graphique avec un bouton connexion pour ouvrir le port série COM1, un bouton pour envoyer une trame et une textbox pour lire un retour quelconque de trame sur le port COM1.
Et voila le code pour le moment de mon bouton envoyer :


Private Sub send_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles send.Click
        Dim retour As String
        
        'envoie de la trame
        serialport.Write(...)
        
        retour = serialport.ReadExisting

        log.Text += retour
End Sub


je ne sais pas quoi mettre à la place des "..."
la trame que je dois envoyer est la suivant pour allumer la lumière : 01 06 00 07 00 80 39 AB (en hexa) h80=128, h39=57, hAB=171, le CRC est bon c'est 39 AB
j'ai testé avec simply modbus, j'arrive à envoyer cette trame et allumer la lumière donc mon cablage est bon ;)

pour envoyer une trame sur le port série il y a juste la méthode write de l'objet serialport qui s'implémente avec une string, un tableau de byte ou un tableau de char.

je sais qu'en faisant la méthode chr(01) & chr(00) ... ça ne fonctionne pas car le chr(00) est considéré comme NUL et donc n'envoie pas "0", j'ai essayé en décimal mais je ne sais pas trop comment envoyer la trame en décimal

à la fin de ton message tu me dis de ne pas employer la méthode write, ok mais comment je m'y prends pour envoyer une trame sur le port série alors ?

désolé pour toutes ces questions mais il n'y a pas beaucoup d'infos sur le net :/
0
MCSilver Messages postés 13 Date d'inscription mercredi 25 octobre 2006 Statut Membre Dernière intervention 6 janvier 2011
6 janv. 2011 à 19:46
Voilà un code VB.net qui fonctionne.

Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ByteArr As Byte() = New Byte() {1, 6, 0, 7, 0, Convert.ToByte(&H80), Convert.ToByte(&H39), Convert.ToByte(&HAB)}

'Ajuste les paramètres du protocole RS-232 ou RS-485, Typiquement: 9600, 8, N, 1)
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = IO.Ports.Parity.None
SerialPort1.StopBits = IO.Ports.StopBits.One
SerialPort1.PortName = "Com1"
SerialPort1.Open()
SerialPort1.Write(ByteArr, 0, ByteArr.Length)
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim ByteArr(SerialPort1.ReadBufferSize) As Byte
Dim NbBytesRecu As Integer
Dim i As Integer
Dim BytesEnString As String

NbBytesRecu = SerialPort1.Read(ByteArr, 0, SerialPort1.ReadBufferSize)


For i = 0 To NbBytesRecu - 1
BytesEnString = BytesEnString & ByteArr(i) & "/"
Next

End Sub
End Class
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
6 janv. 2011 à 20:44
Merci beaucoup je vais tester ça demain ;)
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
7 janv. 2011 à 08:53
Merci beaucoup ça fonctionne parfaitement, je n'arrivais pas à trouver la façon de convertir les hexa en byte dans le tableau c'est parfait !!
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
11 janv. 2011 à 13:12
Je suis confronté à un autre problème, j'arrive bien à envoyer la trame que je veux sur l'automate mais j'ai un petit problème pour lire la trame retour
Pour lire la trame retour, je fais un évènement datareceived sur le serialport que j'utilise comme précisé plus haut dont voici le code :

 Private Sub SerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles serialport.DataReceived
        'lecture du buffer du port série
        Dim ByteArr(serialport.ReadBufferSize) As Byte
        Dim NbBytesRecu As Integer
        Dim i As Integer
        Dim BytesEnString As String =  ""

        NbBytesRecu = Me.serialport.Read(ByteArr, 0, serialport.ReadBufferSize)

        For i = 0 To NbBytesRecu - 1
            If ByteArr(i) < 16 Then
                BytesEnString += "0" & Hex(ByteArr(i)) & " "
            Else
                BytesEnString += Hex(ByteArr(i)) & " "
            End If
        Next
        SetText(vbCrLf & BytesEnString)
    End Sub

    Delegate Sub SetTextCallback(ByVal [text] As String)

    Private Sub SetText(ByVal [text] As String)
        If Me.log.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf SetText)
            Me.Invoke(d, New Object() {[text]})
        Else
            Me.log.Text += [text]
        End If
    End Sub


mon problème c'est que lorsque j'envoie la trame 01030B300001+CRC pour lire une température je n'ai pas de retour immédiat, l'évènement datareceived ne se déclenche pas de suite, si je renvoie n'importe quelle autre trame alors je reçois la réponse à ma première trame ... et ainsi de suite, c'est un peu embêtant !

ce que je devrais avoir :
1er envoie : 01 03 0B 30 00 01 86 21
1er retour : 01 03 0B 30 00 01 86 21 01 03 02 00 D1 78 18 (la réponse est bonne)


ce que moi j'ai :
1er envoie : 01 03 0B 30 00 01 86 21
1er retour : 01 03 0B 30 00 01 86 21

2ème envoie : 01 06 00 07 00 80 39 AB (autre trame au hasard)
2ème retour : 01 03 02 00 D1 78 18(la réponse de la trame d'avant) 01 06 00 07 00 80 39 AB (début de la réponse du 2ème envoie, la fin sera émise au 3ème envoie et ainsi de suite)





voilà les paramètres de mon objet serialport :

serialport.Baudrate  = 19200
serialport.databits = 8
serialport.dtrenable = true
serialport.handshake = none
serialport.parity = none
serialport.readbuffersize = 4096
serialport.readtimeout = 2000
serialport.receivedbytes = 8
serialport.Rtsenable = true
serialport.stopbit = one
serialport.writebuffersize = 2048
serialport.writetimeout = 400



pour le handshake je ne sais pas quoi mettre, je n'ai pas trouvé d'info sur la doc de mon automate ...
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
11 janv. 2011 à 14:50
J'ai un problème de temporisation de l'algorithme ou alors de lecture du buffer du serialport parce que quand je rajoute une msgbox dans l'algo de l'évènement serialport.datareceived je me retrouve avec ce que je veux ...

    Private Sub SerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles serialport.DataReceived
        'lecture du buffer du port série
        Dim ByteArr(serialport.ReadBufferSize) As Byte
        Dim NbBytesRecu As Integer
        Dim i As Integer
        Dim BytesEnString As String =   ""

          MsgBox(serialport.ReadBufferSize)  

        NbBytesRecu   = Me.serialport.Read(ByteArr, 0, serialport.ReadBufferSize)

        For i = 0 To NbBytesRecu - 1
            If ByteArr(i) < 16 Then
                BytesEnString += "0" & Hex(ByteArr(i)) & " "
            Else
                BytesEnString += Hex(ByteArr(i)) & " "
            End If
        Next
        SetText(vbCrLf & BytesEnString)
    End Sub

    Delegate Sub SetTextCallback(ByVal [text] As String)

    Private Sub SetText(ByVal [text] As String)
        If Me.log.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf SetText)
            Me.Invoke(d, New Object() {[text]})
        Else
            Me.log.Text += [text]
        End If
    End Sub


comment faire une tempo dans un code mise à part en faisant une boucle ?
il n'y a pas une fonction sleep() ?
0
c4rr3r4 Messages postés 16 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 4 juin 2012
11 janv. 2011 à 15:43
j'ai mis un threading.thread.sleep(200) à la place du msgbox et ça fonctionne parfaitement !
0
pascal


salut,

pour envoyer de l'hexa tu peux faire pour "00" en hex --> &h00 ou "3F" --> &h3F

bon courage
0
Rejoignez-nous