industrial-modbus-tcp-client-8.ino
Low-level Modbus TCP client for industrial data acquisition via Intel Ethernet controllers.
The script uses raw sockets for maximum efficiency on the 2.5GbE network. The MS-U320 has two independent Ethernet ports, allowing IT and OT traffic segregation. Configure the Modbus slave IP address in the code. Intel I226-V/LM controllers offer low latency ideal for automation. Test connectivity with 'ping' before running the script to validate the physical link.
industrial-modbus-tcp-client-8.ino
import socket
import struct
import time
# Configuration Modbus TCP simple pour le BIOSTAR MS-U320
# Utilise les ports Ethernet Intel I226-V/LM pour une communication fiable
class ModbusTCPClient:
def __init__(self, host, port=502):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def connect(self):
try:
self.sock.connect((self.host, self.port))
print(f"Connecté au serveur Modbus {self.host}:{self.port}")
return True
except Exception as e:
print(f"Erreur de connexion : {e}")
return False
def read_holding_registers(self, start_addr, quantity=1, unit_id=1):
# Construction de la trame Modbus TCP (Func 03: Read Holding Registers)
# Transaction ID | Protocol ID | Length | Unit ID | Function | Start Address | Quantity
transaction_id = 1
protocol_id = 0
length = 6
func_code = 3
byte_count = quantity * 2
packet = struct.pack('>HHHBBHH', transaction_id, protocol_id, length, unit_id, func_code, start_addr, quantity)
try:
self.sock.send(packet)
response = self.sock.recv(1024)
if len(response) >= 9:
# Extraire les données (simplifié)
data_len = response[8]
values = struct.unpack(f'>{int(data_len/2)}H', response[9:9+data_len])
return values
except Exception as e:
print(f"Erreur de lecture Modbus : {e}")
return None
def close(self):
self.sock.close()
# Exécution d'exemple
if __name__ == "__main__":
# Remplacez par l'IP de votre PLC/Esclave Modbus sur le réseau industriel
client = ModbusTCPClient('192.168.1.10')
if client.connect():
try:
while True:
regs = client.read_holding_registers(start_addr=0, quantity=2)
if regs:
print(f"Registres [0-1] : {regs}")
time.sleep(1)
except KeyboardInterrupt:
print("Arrêt manuel.")
finally:
client.close()