Recevoir une trame en ModBus

Une fois qu’on sait ouvrir un port série et y envoyer des infos, il faut s’attendre à recevoir des infos de la part de la machine. Pour comprendre ça, on va voir un petit court de ModBus.

Le principe est assez simple finalement, quand on envoie un message à la machine, et transmet sa réponse qui contient ce qu’on lui a demandé. Une chaîne standard de modbus contient diverses infos, la trame « question » a généralement une longueur fixe, alors que la réponse dépend de la question.

Question : {adresse machine} {fonction lecture/ecriture} {adresse départ lecture} {nombre de registre} {CRC}

L’adresse machine, c’est son identifiant dans le cas où il y a plusieurs appareils ModBus sur le même réseau, la fonction permet de lire ou d’écrire des registres. L’adresse départ est la case par laquelle on commence et on prend autant de case que demandé après. Le CRC est particulier, c’est une valeur calculer en fonction des valeurs précités pour confirmer à la machine qu’on envoie des données viables.

Dans beaucoup de cas, le CRC est calculé par un logiciel en dur, donc pas besoin de la calculer.

Voici un exemple de trame : 01 04 00 00 00 14 F0 H5

Là je lis sur la machine « 01 », avec la fonction « 04 », 20 cases (le « 00 14 » est en hexadécimal) à partir de 00. « F0 H5 » correspond au CRC.

La principale difficulté est de comprendre le codage de la trame à envoyer et de savoir comment recevoir les données. Vous avez sans doute remarquer que certaines valeurs sont codées sur 2 bits « 00 00 » et « 00 14 », alors que la fonction et l’esclave sont codés sur 1 bit.

Mais je ne vais pas faire durer le suspens plus longtemps, voici le code de réception des données.

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 = ""

'Tempo pour laisser le temps à la trame d'arriver
 Threading.Thread.Sleep(200)

'Nombre de bytes reçus
 NbBytesRecu = SerialPort1.Read(ByteArr, 0, SerialPort1.ReadBufferSize)

'Chainage des bytes reçus
 For i = 0 To NbBytesRecu - 1
 BytesEnString = BytesEnString & ByteArr(i) & "/"
 Next

'A ce niveau la chaine BytesEnString contient toutes les valeurs retour de trame séparées d'un "/"

End Sub

C’est un système événement qui se déclenche automatiquement à chaque arrivé d’information. J’ai épuré la véritable fonction que j’utilise car elle contient des données sensibles, mais également un système d’espion et un système de cycle.

Le cycle me permet en cas de case « cycle » coché, de renvoyer une trame quand le traitement de la trame reçue est terminé. Du coup a chaque fois que j’ai fini de traiter la réponse, je repose la question pour revérifier les données.

L’espion quant à lui me permet juste d’afficher dans une fenêtre les trames que je reçois pour les décoder manuellement au besoin.

La trame de retour se compose ainsi :

Réponse : {adresse machine} {fonction lecture/ecriture} {nombre de registre} {registre 0} {registre 1} … {registre X} {CRC}

Si j’ai demandé trois registres dans ma question à la machine 1, le retour sera : 01 04 03 00 45 06 F4 00 0A CRC

Le CRC renvoyé sera différent que celui que vous avez transmis puisqu’il est recalculé à chaque question et à chaque réponse. Les trois registres demandés, à partir de l’adresse X sont donc « 00 45 », « 06 F4 » et « 00 0A ». A vous de retravailler les valeurs pour obtenir des données concrètes.

Dans le prochain chapitre, je vous donnerais quelques fonctions et astuce pour traiter vos données.

Series Navigation<< Envoyer une trame en ModBusLe CRC16 en ModBus >>

Une réflexion sur “ Recevoir une trame en ModBus ”

Laisser un commentaire