blog

Prototypage avec Modbus

Programmeur de codage Python, JavaScript et html sur l'écran d'un ordinateur portable
Alex Pohjanpelto
Alex Pohjanpelto
Published: Sep 7, 2021
Fabrication industrielle et processus
Mesures industrielles
Sciences de la vie

Êtes-vous charger du prototypage ou cherchez-vous un moyen abordable de mesurer l'humidité et la température dans votre application sans compromettre la qualité des mesures ? Avez-vous également des connaissances de base sur les langages de programmation, tels que Python ? Si c'est le cas, j'espère pouvoir vous montrer comment vous enregistrer facilement des données sur de longues périodes avec une seule sonde HMP110, un câble de service USB (219690) et un ordinateur équipé de Python 3. Je vais vous expliquer les différentes sections du code mais si vous n'avez pas besoin d'explication, vous pouvez aller directement en bas pour visualiser la totalité du code. Je tiens également à souligner qu'il ne s'agit que d'un exemple de script utilisé pour présenter la communication Modbus.

Bibliothèques

Avant de passer au code, commençons par présenter les bibliothèques dont nous allons tirer parti, la plus importante étant pymodbus. Nous l'utilisons pour communiquer avec la sonde via Modbus RTU. Plus précisément, nous allons importer ModbusSerialClient depuis pymodbus.client.sync. Nous utilisons la bibliothèque struct pour manipuler les bits dans différents types de variables, la bibliothèque time pour modifier le taux d'interrogation, la bibliothèque datetime pour obtenir l'heure et la date des mesures, et importons argparse pour passer des arguments de la ligne de commande au code.

Depuis pymodbus.client.sync, importez ModbusSerialClient comme ModbusClient
import struct
import time
import datetime
import argparse

Parameters (Paramètres)

J'ai ajouté quelques arguments pour améliorer la flexibilité du code. Nous les utilisons pour pouvoir facilement modifier les valeurs des variables à partir de la ligne de commande sans devoir changer le code. Les arguments pratiques sont le port de communication, le nom du fichier dans lequel les données sont enregistrées, l'adresse esclave de la sonde, le taux d'interrogation et la longueur d'enregistrement des données.

parser = argparse.ArgumentParser(
    description = « enregistreur de données Modbus »
)
parser.add_argument('port', help=« Le port COM auquel la sonde est connectée »)
parser.add_argument('-f', '--file', help=« Le nom du fichier pour enregistrer les données (default data.csv) », default=« data.csv »)
parser.add_argument('-a', '--address', help=« L'adresse de la sonde (par défaut 240) », default=240, type=int)
parser.add_argument('-r', « --rate », help=« La vitesse d'interrogation en secondes (par défaut 1) », default=1, type=float)
parser.add_argument('-l', '--length', help=« La durée en heures pour l'enregistrement des données (par défaut 9999999) », type=float, default=9999999)
args = parser.parse_args()
 

Connexion Modbus

Pour commencer, nous devons initialiser un nouveau client Modbus série avec les paramètres corrects pour notre sonde. Dans cet exemple, les paramètres doivent englober la méthode de communication, le port de communication, le temps de réponse, la vitesse de transmission, les bits d'arrêt et la parité. La méthode est 'rtu' pour Modbus RTU. Le port dépend de votre ordinateur donc je vais vous expliquer ci-dessous comment identifier le bon port. Les autres paramètres sont déterminés par les réglages de la sonde. Vous devez donc vous référer à la fiche technique de données pour avoir les valeurs appropriées. En général, la vitesse de transmission des sondes Vaisala est de 19 200 Bd, les bits d'arrêt ont la valeur 2 et la parité est zéro.

probe = ModbusClient(method='rtu', port=args.port, timeout=1, baudrate=19200, stopbits=2, parity='N')

 

Lecture des registres d'exploitation

Créons maintenant une fonction pour lire les registres d'exploitation de la sonde. Nous appelons la méthode read_holding_registers() de l'instance client Modbus que nous avons créée dans la section précédente pour lire les registres. Nous devons spécifier l'adresse de départ du registre d'exploitation, le nombre de registres et l'adresse esclave de la sonde. Nous recevrons les données des registres en mots de 16 bits au format little-endian que nous devons ensuite convertir en valeurs à virgule flottante 32 bits. 

def holding_registers_data():
    essayez :        
        registers = probe.read_holding_registers(address=0,count=10, unit=args.address).registers
            sauf exception comme e :
        print(e)
        return False, None, None, None
    essayez :
        rh = data_from_register(registers, 1)
        t = data_from_register(registers, 3)  
        dp = data_from_register(registers,9)   
       
    sauf exception comme e :
        print(e)
        return False, None, None, None
        return True, rh, t, dp
 

Conversion des registres en valeurs 32 bits

Les registres sont enregistrés sous forme d'integers 16 bits et nous devons les convertir en valeurs à virgule flottante 32 bits. J'ai créé une fonction qui prend les valeurs et l'index du registre et renvoie une valeur à virgule flottante 32 bits des données à cet index. Nous utilisons la structure du module (struct) pour effectuer cette conversion

Def data_from_register (registres, i):
    return struct.unpack('!f', bytes.fromhex('{0:04x}'.format(registers[i]) + '{0:04x}'.format(registers[i-1])))[0]

 

Enregistrement des données

Maintenant que nous pouvons lire les registres d'exploitation et convertir les valeurs en valeurs à virgule flottante 32 bits, nous devons créer une fonction pour enregistrer les valeurs dans un fichier .csv. Ici, j'ai créé une fonction appelée data_logger(). Elle appelle les function holding_registers_data() et affecte les données reçues à un fichier au format date heure, humidité relative, température et point de rosée.

def data_logger():
    probe.connect()
    successful, rh, t, dp = holding_registers_data()
    si (réussi) :
        dt = datetime.datetime.now()
        
        essayez :
            avec open(args.file, « a »), avec f :
                line = f"{dt},{rh},{t},{dp}\n"
                print(line)
                f.write(line)   
        sauf exception comme e :
            print(e)
        probe.close()
        time.sleep(args.rate)
        
    sinon :
        probe.close()
        time.sleep(0.5)
 

 

Détermination du port de communication de la sonde

Tout d'abord, vérifiez que votre sonde est bien connectée à votre ordinateur. 
 

Windows
Dans le système d'exploitation Windows, vous pouvez trouver le port COM du périphérique sous Gestionnaire de périphériques. Pour ouvrir la fenêtre Gestionnaire de périphériques, ouvrez le menu Démarrer en bas à gauche de l'écran et saisissez « Device Manager » (Gestionnaire de périphériques). Il devrait apparaître comme le premier résultat sous « Best match » (Meilleure correspondance). Ouvrez-le en cliquant sur l'icône ou en validant par Enter sur votre clavier. Cliquez sur la flèche figurant à côté de Ports (COM et LPT) pour faire apparaître tous les ports. Il devrait y avoir un périphérique appelé « Vaisala USB Device » (Périphérique USB Vaisala) avec le port COM affiché à côté, dans notre cas COM6.

Image
Determining the communication port of the probe

Linux 
Dans Linux, vous pouvez déterminer le port de communication en entrant la commande « dmesg | grep tty » sur le clavier. Vous devriez obtenir entre autres une information de type « cp210x converter now connected to ttyUSBn », ttyUSBn étant le port.

Exécution du code

Pour exécuter le script, vous devez auparavant installer toutes les bibliothèques. Si nécessaire, vous pouvez utiliser la commande pip 

pip3 install -U pymodbus 
pour installer pymodbus. Les autres bibliothèques devraient déjà être fournies avec Python 3.
Dans une invite de commande, naviguez vers le répertoire contenant le script Python et entrez 
    python Modbus_RTU -h 

pour obtenir de l'aide sur les arguments. Ceci devrait s'afficher dans l'invite de commande. Voyez ci-dessous une capture d'écran de la sortie.

Image
Terminal

 

 

 

 

 

Le seul paramètre requis est le port de communication, tandis que les autres arguments ont une valeur par défaut qui peut être modifiée selon vos préférences. L'argument port de communication ne nécessite aucun identifiant et peut être placé n'importe où après le nom du fichier. Les autres arguments qui sont facultatifs, nécessitent un identifiant.
 Voici un exemple de commande typique sous forme longue et courte :

    Python .\Modbus_RTU  --file datalog.csv --address 240 --rate 10 --length 48 COM6
    Python .\Modbus_RTU -f datalog.csv -a 240 -r 10 -l 48 COM6 
 

 

Téléchargez l'intégralité du code et visualisez le webinaire Modbus 101.

 

Ajouter un nouveau commentaire