Relever des données sur un réseau modbus via vba

Résolu
Corentinte - 18 nov. 2014 à 08:37
 Den - 14 nov. 2021 à 19:32
Bonjour,

Dans le cadre d'un projet pour mon stage, je dois relever une valeur contenu sur un DIRIS A40 mis en réseau (Protocol Modbus) via un programme en VBA

Je connais l'adresse IP du DIRIS ainsi que l'adresse décimale (50770) et hexa (C652) de la valeur que je dois relever.

Je ne sais pas trop comment commencer...

Comment me "connecter au Diris" ? et ensuite comment relever la valeur ?

Je connais les bases du VBA, j'ai fait quelques programmes, mais je n'ai jamais fait ce genre de programme...

J'ai fait de nombreuses recherche sur internet mais la je suis perdu...

Pourriez-vous me débloquer ? Ou me donner quelques piste au moins pour la "connexion" avec le diris A40 ?

Je reste à votre disposition si vous avez des questions.

Merci d'avance.



Corentin

6 réponses

Merci NHenry,

Cela semble correspondre à ce dont j'ai besoin en particulier le controle Winsock, mais je suis sous excel 10 et je n'ai pas accès a ce "module" dans outil => Reference, je n'ai rien avec le nom Winsock, cela a changé de nom ? Où est ce normal que je n'ai rien sous excel 10 ?

Merci pour tout.
1
jordane45
Messages postés
35474
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
22 mai 2022
356
18 nov. 2014 à 16:54
0
Merci !
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
18 nov. 2014 à 12:08
Bonjour,

Regardez du côté du controle Winsock pour gérer la connexion TCP/IP.
Pour le protocole, une recherche de la doc de "Modbus TCP" devrait être d'une grande utilité.
0
jordane45
Messages postés
35474
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
22 mai 2022
356
18 nov. 2014 à 16:53
Discussion déplacée dans VBA
0
Bonjour,

Je suis toujours un peu bloqué...

Je ne comprends pas où est ce que je dois mettre l'adresse decimale de la valeur que je souhaite relever...

Je vous mets le code que j'ai fait, la connection marche, mais la réception ne retourne rien ! Je ne vois pas trop comment continuer...

Merci d'avance.

Function tuto1()
    Dim lData As WSADATA
    Dim lsock As Long
    Dim lname As SOCKADDR
    Dim lRet As Long

    ' Initialisation de Winsock
    If WSAStartup(257, lData) = 0 Then
        ' Création d'une socket
        lsock = socket(AF_INET, SOCK_STREAM, 0)
        If lsock <> -1 Then
            lname.sin_family = AF_INET ' famille "classique"
            lname.sin_port(1) = 502 \ 256 ' première partie du port
            lname.sin_port(2) = 502 Mod 256 ' deuxième partie du port
            lname.sin_addr = addrfromhost("10.100.114.123") ' adresse du serveur
     
            ' Connexion
           lRet = Connect(lsock, lname, LenB(lname))
           
           'Vérification connexion OK
           If lRet = 0 Then
    
              ' Réception des données de connexion
              lStrToReceive = Space(1024)
              lRet = recvstr(lsock, lStrToReceive, Len(lStrToReceive), 0)
            
              If lRet > 0 Then
                    lStrToReceive = Left(lStrToReceive, lRet)
                    Debug.Print "Octets reçus : " & lRet & vbCrLf & lStrToReceive
                End If
           Else
                MsgBox "Le code d'erreur est :" & Err.LastDllError
           End If
           
           closesocket lsock
           
       End If
       WSACleanup
    End If
End Function
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
19 nov. 2014 à 13:42
As-tu regardé la documentation du protocole Modbus TCP ?
0
oui, j'ai compris que je devais poser une question, mais je ne comprend pas bien comment poser cette question...

j'ai cru comprendre que la question devais commencer par le numero visé donc je pense 50770 mais ensuite je ne comprend pas du tout comment relever cette valeur !
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
19 nov. 2014 à 19:42
Le protocole Modbus est un protocole multipoint, un maitre et plusieurs esclaves.

Il y a donc le numéro d'esclave pour dire à qui tu t'adresses et un code fonction pour dire ce que tu veux lui demander.
Et le l'adresse que tu as sert à dire à quel offset chercher les données.

https://en.wikipedia.org/wiki/Modbus
0
Oui, j'ai bien compris cela.

Ce que je ne comprends pas c'est que :

je me connecte à l'exclave (via le vba)

' Connexion
lRet = Connect(lsock, lname, LenB(lname))


Et ensuite, je n'ai qu'un seul exclave, et je n'ai pas de numéro d'exclave...
Du coup je suis incapable de creer le code à envoyer car celui ci commence par le numéro d'exclave.

Ensuite j'ai compris que je dois envoyer 1 car je cherche une lecture, puis l'adresse C652. Ensuite je doit mettre un mot de controle et celui ci non plus je ne sais pas à quoi il correspond...

donc pour récapituler je dois envoyer XXX.C652.1.XXX

Voici le code où je suis arrivé.

Function tuto1()
Dim lData As WSADATA
Dim lsock As Long
Dim lname As SOCKADDR
Dim lRet As Long

' Initialisation de Winsock
If WSAStartup(257, lData) = 0 Then
   ' Création d'une socket
   lsock = socket(AF_INET, SOCK_STREAM, 0)
   If lsock <> -1 Then
           lname.sin_family = AF_INET ' famille "classique"
           lname.sin_port(1) = 502 \ 256  ' première partie du port
           lname.sin_port(2) = 502 Mod 256 ' deuxième partie du port
           lname.sin_addr = addrfromhost("10.100.114.123") ' adresse du serveur
     
     ' Connexion
           lRet = Connect(lsock, lname, LenB(lname))
           
    'Vérification connexion OK
        If lRet = 0 Then
        
            If lRet = 0 Then
            
                ' Envoi des données
                lStrToSend = "XXX.01.C652.XXX" & vbCrLf
                lRet = sendstr(lsock, lStrToSend, Len(lStrToSend), 0)
                Debug.Print "Octets envoyés : " & lRet & " / " & Len(lStrToSend) & vbCrLf & lStrToSend
                
                ' Réception des données
                lStrToReceive = Space(1024)
                lRet = recvstr(lsock, lStrToReceive, Len(lStrToReceive), 0)
                
                If lRet > 0 Then
                
                    lStrToReceive = Left(lStrToReceive, lRet)
                    Debug.Print "Octets reçus : " & lRet & vbCrLf & lStrToReceive
                    
                End If

                
            Else
                Debug.Print "Erreur de connexion n° " & Err.LastDllError
            End If

        closesocket lsock
           
        End If
    WSACleanup
    End If
End If
End Function


       
0
J'ai aussi une autre petite question,

En ce qui concerne le port, est ce bien 502 ? Comment être sur car l'absence de réponse pourrais aussi venir de là ?!
0

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

Posez votre question
Voilà ce que j'ai trouvé sur internet.

j'en conclu donc que je doit envoyer : "03 00050770 00000001"

Mais cela ne fonctionne pas... Je ne reçoit pas de réponse...

Quelqu'un sait où je me serais trompé ?

Ethernet TCP/IP - Protocole Modbus TCPLecture d'une suite de plusieurs registres (Code Fonction 3)

? Requête :
Octet 0 : Code Fonction = 03
Octets 1-2 : Numéro de référence cible (offset)
Octets 3-4 : Nombre de mots à lire (1-125)

? Réponse :
Octet 0 : Code Fonction = 03
Octet 1: Byte count de la réponse (B=2 x Nb de mots)
Octets 2 à(B+1):Valeurs des registres

? Réponse d'exception :
Octet 0 : Code Fonction = 83 (hexa)
Octet 1 : Code d'exception = 01 ou 02
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
20 nov. 2014 à 18:40
Il te manquue encore des champs :
Identifiant de requête (Déclinaison TCP de Modbus)
Longueur de requête (Déclinaison TCP de Modbus)
Numéro d'esclave (Générique modbus)

Les données sont à coder en binaire, si c'est du modbus TCP ASCII, le binaire doit être transformé en chaine HEXA (sans préfixe no séparateur de groupe)
0
Merci beaucoup, ton aide m'aide à bien avancer !

Je vais poser deux questions qui vont sans doute parraitre débile, mais je ne comprend pas :
-Comment connaitre le numéro d'esclave ? J'ai beau chercher je ne vois pas où je peux trouver ce numéro...
-Identifiant de requête, ce n'est pas le 03 que j'ai mis au début ?
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
22 nov. 2014 à 20:16
Bonsoir,

N° esclave : de base, c'est souvent le numéro 1, mais ça peut changer, voir la doc de ton équipement.
L'id requête : c'est le premier champ numérique d'une requête Modbus, il sert à identifier quelle réponse va avec quelle requête, car il est possible en modbus TCP d'envoyer plusieurs requête avant d'avoir reçu la première réponse.

Le code 03 est le code pour la fonction de lecture de mots.
0
Bonjour,

Dans un premier temps merci pour ton aide.

Je suis toujours bloqué mais j'ai bien avancé enfin du moins je pense que ce que j'ai fait avant fonctionne.

Actuellement j'ai donc réussi à me connecter et j'envoie une trame.

Mais je ne reçois rien... enfin si 1024 espace

voici la ligne de code et en dessous le rapport debug.print

'Envoi des données
            lStrToSend = Chr(2) + Chr(1) + Chr(3) + Chr(C6) + Chr(52) + Chr(0) + Chr(1) + vbCrLf
            lret = sendstr(lsock, lStrToSend, Len(lStrToSend), 0)
            Debug.Print "Octets envoyés : " & lret & " / " & Len(lStrToSend) & vbCrLf & lStrToSend
' Réception des données
Sleep 200
            lStrToReceive = Space(1024)
            lret = recvstr(lsock, lStrToReceive, Len(lStrToReceive), 0)
            If lret > 0 Then
'lStrToReceive = Left(lStrToReceive, lRet)
                Debug.Print "Octets reçus : " & lret & lStrToReceive
            End If



Octets envoyés : 9 / 9
 4 

Octets reçus : 9

J'ai mis un tempo de 200ms pour attendre la réponse mais rien ne viens.... Est ce un problème de tram d'envoi, un problème de reception ou autre ? Je dois avouer que là je suis bloqué... Je cherche depuis plusieurs jours, mais rien...
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
18 déc. 2014 à 19:11
Bonsoir,

Le "vbCrLf" qui traine en fin de ta chaine à envoyer, me fait penser que tu as mélangé les protocoles Modbus.

Si tu mets un VbCrLf, ça veut dire que tu veux échanger en texte, soit chaque octet à envoyer doit former 2 caractères en hexadécimal.
Si tu mets les données avec un Chr$, cela veut dire que tu veux transmettre en binaire et c'est donc l'absence de données qui signale la fin de la trame.

La présence de l'instruction : Chr(C6) me laisse penser que tu t'es trompé dans le format de ta chaine, penses à mettre "Option Explicit" en haut de tout tes modules de code.

Tu veux communiquer en ModbusTCP (enfin, je suppose), mais tu ne semble pas respecter le formalisme de ce protocole, je t'invite donc à revoir le formatage de ta trame afin d'aller plus loin.
0
Je n'arrive pas trop trop à comprendre le principe.

Désormais je reçois une réponse à ma question mais elle ne veux rien dire enfin pas à ma connaissance...
Voici ma nouvelle ligne de code....

lStrTosend = Chr(&H1) + Chr(&H1) + Chr(&H3) + Chr(&HC6) + Chr(&H52) + Chr(&H0) + Chr(&H2) + Chr(&H59) + Chr(&H7)


Je n'arrive vraiment pas à comprendre ce que je dois envoyer pour recevoir une réponse correcte ...

Selon ce que tu me dit, avec cette methode j'envoi en Binaire or j'ai compris que c'était de l'hexa qu'il me fallais ... La solution en Chr ne fonctionne donc pas ?

je ne comprend pas du tout ce que je doit envoyer aurais tu un exemple à me montrer ou quelque chose qui m'eclaire ? j'ai éplucher de nombreux cours sur internet mais aucun ne m'a aidé...

Merci d'avance !
0
NHenry
Messages postés
14927
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 mai 2022
162
21 déc. 2014 à 21:34
Il faut que tu résonnes en octet, pas en caractères, il serait même mieux que tu envoies un tableau d'octet plutôt qu'une chaine :

Dim ltByte(0 to 8) as Byte
ltByte(0)=&h1
ltByte(1)=&h1
ltByte(2)=&h3
ltByte(3)=&hC6
ltByte(4)=&h52
ltByte(5)=&h0
ltByte(6)=&h2
ltByte(7)=&h59
ltByte(8)=&h7


Et tu envoies le tableau directement.

Qu'est-ce que tu reçois ?
0
Bonjour,

Je viens de tester avec ton tableau d'octet.

'Envoi des données
                    Dim ltByte(0 To 8) As Byte
                            ltByte(0) = &H1
                            ltByte(1) = &H1
                            ltByte(2) = &H3
                            ltByte(3) = &HC6
                            ltByte(4) = &H52
                            ltByte(5) = &H0
                            ltByte(6) = &H2
                            ltByte(7) = &H59
                            ltByte(8) = &H7
                    'lStrTosend = "0103C6520003"
                    'lStrTosend = "01" & "03" & "07" & "70" & "00" & "03" & "05" & "64" & vbCrLf
                    lret = sendstr(lsock, ltByte, 9, 0)


Je reçois une réponse en code ACSII que je "décode"

Octets reçus : 9 / 9
a?R?  € ===> 97 63 82 63 0 3 0 128 1


Je ne vois toujours pas de logique...
0
Petite précision, j'ai remarqué que le 03 dans la réponse est toujours présent ! quelque soit ma requête en entré : Avec le tableau, avec les chr(), en entrant directement les caractères, ....

97 63 82 63 0 3 0 128 1

est ce un code erreur ? ou quelque chose comme cela ?
0