Modbus TCP
Des registres et des bits Modbus sur TCP/IP, avec un adressage typé, la maîtrise de l'ordre des octets et un balayage réseau borné.
Le pilote Modbus TCP lit et écrit des registres et des bits Modbus sur TCP/IP : automates, compteurs, passerelles et tout serveur qui parle Modbus/TCP. L'adressage est entièrement typé : vous choisissez une classe de registre et un numéro de registre à partir de 0, et l'application assemble la requête du bus; il n'y a aucune adresse en texte libre à manquer.
Équipement
| Champ | Sens | Par défaut |
|---|---|---|
| Hôte | Le nom DNS, l'adresse IPv4 ou IPv6 du serveur ou de la passerelle Modbus. | vide : l'équipement n'est pas connecté tant qu'aucun n'est saisi |
| Port | Le port TCP, de 1 à 65535. Un champ vide affiche 502 en gris et l'équipement est appelé sur ce port; un équipement enregistré avec 0 se lit de la même façon. | 502 |
| ID d'unité | L'identifiant d'unité (esclave) Modbus porté par chaque requête, ce qu'une passerelle emploie pour router vers l'équipement derrière elle. De 0 à 255. | 1 |
| Format de trame | Comment chaque requête circule sur la connexion : MBAP, l'en-tête Modbus TCP devant chaque requête, ou RTU, la trame RTU avec son CRC envoyée telle quelle, pour un convertisseur série-Ethernet en mode transparent (voir RTU sur TCP). L'hôte, le port, l'ID d'unité et les tags sont les mêmes dans les deux cas. | MBAP |
| Intervalle minimal entre transactions (ms) | Une cadence de compatibilité : le silence minimal après la fin d'une transaction avant que la suivante ne commence, de 0 à 1000. Zéro n'ajoute aucun délai artificiel. | 0 |
| Intervalle de scrutation (ms) | La cadence de scrutation par défaut des tags qui ne la remplacent pas. | 1000 |
L'URI de base montrée dans l'en-tête du volet est
modbus+tcp://host:port/unitID, plus ?minimumTransactionIntervalMs=n quand
l'intervalle est posé.
Les équipements qui partagent un hôte et un port partagent aussi une seule porte de transaction : les requêtes vers le même endpoint ne se chevauchent jamais, et c'est le plus grand intervalle minimal entre transactions configuré parmi les équipements activés de cet endpoint qui les cadence tous. Le volet le dit quand un autre équipement relève l'intervalle effectif au-dessus de celui qui est configuré ici. L'intervalle ne gouverne que le trafic que cette application émet : c'est une aide à la compatibilité avec un serveur ou une passerelle lents, pas une réparation des défauts du réseau.
La connexion attend 5 secondes au plus; une réponse est attendue 10 secondes au plus; il n'y a aucune reprise au niveau du protocole. La boucle de reprise en arrière-plan possède la reconnexion, si bien qu'un équipement éteint ne coûte rien de plus qu'une lecture de mauvaise qualité.
RTU sur TCP
Un convertisseur série-Ethernet en mode transparent ne parle pas Modbus TCP de lui-même : ce qui arrive sur son socket repart tel quel sur son bus série, et ce que le bus répond revient. Un équipement derrière lui est un équipement Modbus TCP dont le Format de trame est RTU : la station envoie la trame RTU (l'ID d'unité, la requête et son CRC) sans en-tête MBAP, et ne croit une réponse que si son CRC est valide. Le Base URI porte alors framing=rtu dans sa requête, par exemple modbus+tcp://192.168.0.20:502/1?framing=rtu; un équipement en MBAP garde l'adresse qu'il a toujours eue. Tout le reste de cette page s'applique sans changement : les classes de registre, les codes de fonction, la file des écritures, les délais et l'intervalle entre transactions.
- L'ID d'unité est l'adresse de l'équipement sur le bus série derrière le convertisseur, de 1 à 247.
- Les équipements derrière un convertisseur partagent son hôte et son port, et avec eux sa barrière de transactions : une requête à la fois, ce qui est aussi tout ce que porte un bus série. Si le convertisseur a besoin d'une pause entre les trames, augmentez l'Intervalle minimal entre transactions (ms).
- Les réglages série du convertisseur lui-même (débit en bauds, format) se font sur le convertisseur; la station ne les voit jamais.
- Une trame RTU ne porte pas de numéro de transaction : avant chaque requête, la station écarte donc tout ce que le convertisseur a déjà envoyé, et une réponse arrivée après l'expiration de sa requête n'est jamais prise pour celle de la suivante.
Adressage d'un tag
| Champ | Sens | Par défaut |
|---|---|---|
| Classe de registre | Quelle entité Modbus le tag adresse : Bobine (0xxxx), Entrée discrète (1xxxx), Registre d'entrée (3xxxx) ou Registre de maintien (4xxxx). Chacune porte le premier chiffre que l'adresse du manuel a pour elle : un manuel qui n'imprime que 30001 désigne donc les registres d'entrée. | Déduite du type et de l'accès : les tags booléens reçoivent une entrée discrète (lecture seule) ou une bobine (inscriptible); tout autre type reçoit un registre d'entrée (lecture seule) ou un registre de maintien (inscriptible). |
| Numéro de registre (base 0) | L'adresse brute du protocole. C'est l'adresse à partir de 0 sur le bus, non la notation du manuel : le registre de maintien 40001 est le numéro de registre 0. Saisir 30001 ici ne choisit pas la classe, car certains équipements ont réellement des registres au-delà de 30000 : la classe se choisit au-dessus. Le registre voyage sur le bus comme un nombre de 16 bits : le champ prend donc de 0 à 65535 et refuse plus large là où il est saisi. | 0 |
| Quantité (registres, vide = automatique) | Combien de registres de 16 bits la valeur occupe. La zone n'est dessinée que sur les tags de texte : tout autre type a une largeur fixe, il n'y a donc rien à remplacer. | Par type : booléen, Int16 et UInt16 1, Int32 et Float 2, texte 4 |
| Octet de poids fort en premier (MSB first, gros-boutiste) | Quel octet de chaque registre de 16 bits passe en premier sur le bus; les mots entre parenthèses sont ceux que les manuels impriment. Tags numériques, et un booléen gardé dans un registre de maintien ou d'entrée; un booléen dans une bobine ou une entrée discrète est un seul bit, sans octet à ordonner : la zone n'y est donc pas dessinée. | activé (ce que la spécification Modbus demande) |
| Mot de poids fort en premier (mot haut en premier) | Quel registre d'une valeur sur deux registres porte la moitié haute. Tags Int32 et Float seulement : une valeur sur un seul registre (booléen, Int16, UInt16) n'a pas de second registre, la zone n'y est donc pas dessinée. Sous les deux zones, Ordre des octets de la valeur nomme la disposition qu'elles forment avec les lettres d'un manuel (Ordre des octets et des mots). | activé |
La carte Source de la valeur se termine par Adresse dans le manuel, l'endroit où se trouve le tag dans la notation que le manuel de l'équipement imprime : le premier chiffre de la classe puis le registre compté à partir de 1. Le registre d'entrée 0 se lit 30001, un Float au registre de maintien 100 se lit de 40101 à 40102, et un registre au-delà de 9998 passe à six chiffres (le registre de maintien 9999 se lit 410000) : le volet se lit donc ligne à ligne contre le manuel.
Types de valeur et quantités
Six types de valeur sont offerts, et la largeur de chacun sur le protocole est fixe :
| Type de donnée | Registres | Forme sur le bus |
|---|---|---|
| Booléen | 1 | Sur une classe de registre : tout registre non nul se lit vrai, et une écriture envoie 1 ou 0. Sur Coil ou DiscreteInput : le bit lui-même. |
| Int16 | 1 | Un entier signé de 16 bits dans un seul registre, de -32768 à 32767. |
| UInt16 | 1 | Un entier non signé de 16 bits dans un seul registre, de 0 à 65535. Le même registre se lit 65535 en UInt16 et -1 en Int16 : le signe vient du type de donnée choisi, non du registre. |
| Int32 | 2 | Un entier signé de 32 bits sur une paire de registres. |
| Float | 2 | Une simple précision IEEE 754 sur une paire de registres. |
| Texte | 1 ou plus (4 par défaut) | Des octets UTF-8 empaquetés deux par registre. Une lecture s'arrête au premier octet nul; une écriture doit tenir dans la quantité déclarée (2 octets par registre) et est complétée par des zéros. |
Un tag de texte est lu et écrit dans l'ordre où l'équipement détient les octets, et une écriture envoie toujours de l'UTF-8. Des octets qui ne sont pas de l'UTF-8 valide, ce à quoi ressemble une plage que l'équipement n'a jamais initialisée ou du texte écrit dans un autre codage, se lisent comme le caractère de remplacement Unicode plutôt que d'échouer : le tag montre quelque chose de visiblement fautif, et chaque autre tag de cet équipement continue de lire.
La Quantité (registres, vide = automatique) n'est demandée que sur les tags de texte. Les largeurs des booléens, des Int16, des UInt16, des Int32 et des Float sont fixes : la zone n'est donc dessinée sur aucun de ces points, ni dans le volet du tag, ni dans la grille des tags; le remplacement existe pour dimensionner les tags de texte.
Ordre des octets et des mots
La zone de l'ordre des octets est dessinée sur les tags numériques et sur un booléen gardé dans un registre, celle de l'ordre des mots sur ceux à deux registres seulement (Int32, Float). Ce sont deux questions
indépendantes : quel octet mène à l'intérieur de chaque registre, et quel registre mène dans une
paire. Modbus n'en définit aucune pour le texte : un tag de texte ne se les voit donc pas
offrir, et ses octets voyagent dans l'ordre où l'équipement les détient. Pour la valeur
0x01020304, A étant l'octet de poids le plus fort, les quatre dispositions sont :
| Octet de poids fort en premier | Mot de poids fort en premier | Octets sur le bus |
|---|---|---|
| activé | activé | AB CD (la valeur par défaut de la spécification) |
| activé | désactivé | CD AB (l'échange de mots classique) |
| désactivé | activé | BA DC |
| désactivé | désactivé | DC BA |
Les lectures et les écritures appliquent les deux mêmes réponses dans le même ordre : une écriture dépose donc exactement les octets qu'une lecture aurait repris. Ordre des octets de la valeur, sous les zones, dit la disposition en un mot (ABCD, CDAB, BADC ou DCBA), comme un manuel la nomme.
Une valeur Int16 ou UInt16 tient dans un seul registre : seul l'ordre des octets s'y
applique. Pour 0x1234, l'octet de poids fort en premier envoie 12 34 et la zone
désactivée envoie 34 12. Il n'y a pas de second registre à placer : la zone de l'ordre des mots
n'y est donc pas dessinée.
Codes de fonction
| Classe de registre | Lecture | Écriture |
|---|---|---|
| Registre de maintien (4xxxx) | fonction 3 (Read Holding Registers) | fonction 6 (registre unique) ou 16 (registres multiples) |
| Registre d'entrée (3xxxx) | fonction 4 (Read Input Registers) | lecture seule; une écriture est refusée |
| Bobine (0xxxx) | fonction 1 (Read Coils) | fonction 5 (Force Single Coil) |
| Entrée discrète (1xxxx) | fonction 2 (Read Discrete Inputs) | lecture seule; une écriture est refusée |
Une écriture ne rapporte un succès que lorsque la réponse de protocole du serveur en confirme l'acceptation; la valeur en cache n'avance qu'à ce moment.
Découverte
Le balayage est explicite et borné : l'application ne déduit ni ne parcourt jamais votre sous-réseau local. Le formulaire de portée prend :
| Champ | Sens | Par défaut |
|---|---|---|
| Hôte IPv4 ou CIDR | Une adresse (192.168.1.10) ou un sous-réseau pas plus large que /24 (192.168.1.0/24). Les adresses de réseau et de diffusion sont sautées. |
obligatoire |
| Port | Le port à sonder. | 502 |
| ID d'unité | Des valeurs, des listes séparées par des virgules ou des plages croissantes : 1, 1,5,9, 1, 3, 8-16 (de 0 à 255). |
1 |
| Format de trame | La trame dans laquelle chaque sondage est envoyé. Un convertisseur en mode transparent ne répond qu'aux trames RTU : balayez-le en RTU. | MBAP |
| Intervalle minimal entre transactions (ms) | La cadence entre deux sondages terminés sur le même hôte, de 0 à 1000. | 0 |
La découverte envoie chaque sondage dans le Format de trame choisi. En RTU, chaque sondage est la trame RTU nue, et une réponse ne compte que si son ID d'unité correspond et que son CRC est valide; les unités derrière un convertisseur en mode transparent sont ainsi trouvées comme les autres. Une unité trouvée garde le format de trame du balayage quand elle est ajoutée.
Un balayage peut envoyer 256 sondages au plus (hôtes × identifiants d'unité); un plan plus grand est refusé avant l'ouverture du moindre socket. La seule requête envoyée est Read Basic Device Identification (fonction 43/14) : la découverte ne lit jamais de registre et ne devine jamais un plan de registres. Une réponse d'exception Modbus entièrement valide prouve qu'une unité est présente sans en revendiquer l'identité; la joignabilité TCP, les délais dépassés et les trames malformées ne le prouvent pas. Quatre hôtes au plus sont balayés en parallèle, séquentiellement à l'intérieur de chaque hôte, avec des délais de 750 ms à la connexion et au sondage.
Les résultats portent l'endpoint complet et un nom suggéré, bâti à partir du fournisseur et du code produit quand l'équipement les rapporte. Les candidats n'ont aucun tag : les registres se configurent après Ajouter. Une unité déjà configurée est marquée comme telle et propose Ouvrir au lieu de créer un doublon.
Des limites bonnes à connaître
- Les autres largeurs d'entier (SByte, Byte, UInt32, Int64, UInt64) et Double ne sont pas offerts : le codec du bus fait l'aller-retour exact des six types ci-dessus.
- Une seule requête est en cours par endpoint à la fois; de nombreux équipements derrière une même passerelle partagent cette sérialisation, et c'est voulu.
- Les écritures adressent un bit ou une suite de registres à la fois; il n'existe pas d'écriture multi-bits.