Creazione di prototipi con Modbus

Codice di programmazione Python, Java Script, codice html sullo schermo di un notebook
Alex Pohjanpelto
Alex Pohjanpelto
Published:
Produzione e processi industriali
Misurazioni industriali
Scienze della vita

Ti occupi di creazione di prototipi o cerchi un modo conveniente per misurare umidità e temperatura nella tua applicazione senza compromettere la qualità delle misurazioni? Hai anche delle conoscenze di base sui linguaggi di programmazione, quali Python? In questo caso, vorrei mostrarti come puoi agevolmente registrare dati per periodi di tempo prolungati utilizzando semplicemente una sonda HMP110, un cavo di servizio USB (219690) e un computer con installato Python 3. Ti illustrerò le diverse sezioni del codice, ma se non ti interessa una spiegazione, puoi andare al fondo della pagina e scaricare l'intero codice. Vorrei sottolineare che si tratta solo di uno script di esempio per illustrare la comunicazione Modbus.

Librerie

Prima di esaminare il codice, vediamo le librerie che utilizzeremo, la più importante delle quali è pymodbus. La utilizziamo per comunicare con la sonda tramite Modbus RTU. Più specificamente, importeremo ModbusSerialClient da pymodbus.client.sync. Utilizziamo la libreria struct per gestire i bit nei diversi tipi di variabili, la libreria time per modificare la frequenza di polling, la libreria datetime per ottenere la data e l'ora delle letture dati e importiamo argparse per passare argomenti dalla riga di comando al codice.

from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import struct
import time
import datetime
import argparse

Parametri

Ho aggiunto alcuni argomenti per migliorare la flessibilità del codice. Li utilizziamo per poter modificare agevolmente i valori delle variabili dalla riga di comando senza dover modificare il codice. Gli argomenti che ritengo potrebbero essere utili sono la porta di comunicazione, il nome del file in cui sono memorizzati i dati, l'indirizzo slave della sonda, la frequenza di polling e la lunghezza di registrazione dei dati.

parser = argparse.ArgumentParser(
    description="Modbus data logger"
)
parser.add_argument('port', help="The COM port where the probe is attached")
parser.add_argument('-f', '--file', help="The file name to store the data (default data.csv)", default="data.csv")
parser.add_argument('-a', '--address', help="The address of the probe (default 240)", default=240, type=int)
parser.add_argument('-r', "--rate", help="The poll rate in seconds (default 1)", default=1, type=float)
parser.add_argument('-l', '--length', help="The length of time in hours to data log (default 9999999)", type=float, default=9999999)
args = parser.parse_args()
 

Connessione Modbus

Per prima cosa dobbiamo inizializzare un nuovo client Modbus seriale con le impostazioni corrette per la nostra sonda. Il set di parametri in questo esempio deve includere il metodo di comunicazione, la porta di comunicazione, il timeout di risposta, la velocità di in baud, i bit di stop e la parità. Il metodo è "rtu" per Modbus RTU, la porta dipende dal tuo computer, quindi spiegherò in una sezione seguente come identificare quella corretta. Gli altri parametri sono determinati dalle impostazioni della sonda, quindi dovrai fare riferimento alla relativa scheda dati per conoscere i valori appropriati. In genere per le sonde Vaisala, la velocità in baud è 19200, i bit di stop sono 2 e la parità è nessuna.

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

 

Lettura dei registri operativi

Creiamo ora una funzione per leggere i registri operativi della sonda. Chiamiamo il metodo read_holding_registers() dell'istanza del client Modbus che abbiamo creato nella sezione precedente per leggere i registri. Dobbiamo specificare l'indirizzo iniziale del registro operativo, il numero di registri e l'indirizzo slave della sonda. Riceveremo i dati dai registri in parole di 16 bit in formato little-endian, che dovremo poi convertire in valori a virgola mobile a 32 bit. 

def holding_registers_data():
    try:        
        registers = probe.read_holding_registers(address=0,count=10, unit=args.address).registers
            except Exception as e:
        print(e)
        return False, None, None, None
    try:
        rh = data_from_register(registers, 1)
        t = data_from_register(registers, 3)  
        dp = data_from_register(registers,9)   
       
    except Exception as e:
        print(e)
        return False, None, None, None
        return True, rh, t, dp
 

Conversione dei registri in valori a 32 bit

I registri sono memorizzati come valori interi a 16 bit e dobbiamo convertirli in valori a virgola mobile a 32 bit. Ho creato una funzione che prende i valori del registro e l'indice del registro e restituisce un valore a virgola mobile a 32 bit dei dati in tale indice. Utilizziamo il modulo struct per eseguire la conversione

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

 

Registrazione dei dati

Ora che possiamo leggere i registri operativi e convertire i valori in valori a virgola mobile a 32 bit, dobbiamo creare una funzione che memorizzi i valori in un file .csv. Ho creato una funzione chiamata data_logger() a tale scopo. Chiama la funzione holding_registers_data() e aggiunge i dati ricevuti a un file nel formato data e ora, umidità relativa, temperatura, punto di rugiada.

def data_logger():
    probe.connect()
    successful, rh, t, dp = holding_registers_data()
    if (successful):
        dt = datetime.datetime.now()
        
        try:
            with open(args.file, "a") as f:
                line = f"{dt},{rh},{t},{dp}\n"
                print(line)
                f.write(line)   
        except Exception as e:
            print(e)
        probe.close()
        time.sleep(args.rate)
        
    else:
        probe.close()
        time.sleep(0.5)
 

 

Determinazione della porta di comunicazione della sonda

Innanzitutto, assicurati che la sonda sia collegata correttamente al computer. 
 

Windows
Nel sistema operativo Windows, puoi trovare la porta COM del dispositivo in Gestione dispositivi. Per aprire la finestra Gestione dispositivi, apri il menu Start in basso a sinistra dello schermo e digita "Gestione dispositivi". Dovrebbe apparire come primo risultato sotto "Corrispondenza migliore", aprilo facendo clic sull'icona o premendo Invio sulla tastiera. Fai clic sulla freccia accanto a Porte (COM e LPT) per espandere le porte. Dovrebbe essere presente un device denominato "Vaisala USB Device" con indicata accanto la porta COM, nel nostro caso COM6.

Image
Determining the communication port of the probe

Linux 
In Linux puoi determinare la porta di comunicazione digitando il comando "dmesg | grep tty" nel terminale. Dovrebbe restituire, insieme ad altri risultati, un messaggio simile a "cp210x converter now attached to ttyUSBn", dove ttyUSBn è la porta.

Esecuzione del codice

Per eseguire lo script, devi avere tutte le librerie installate. Se necessario, puoi usare il comando pip 

pip3 install -U pymodbus 
per installare pymodbus. Le altre librerie dovrebbero essere già incluse con il pacchetto python 3.
In un prompt dei comandi, vai alla directory in cui è memorizzato lo script Python e digita 
    python Modbus_RTU -h 

per ottenere informazioni sugli argomenti. Dovrebbero venire visualizzate nel prompt dei comandi. Di seguito è riportata una schermata dell'output.

Image
Terminal

 

 

 

 

 

L'unico parametro richiesto è la porta di comunicazione, mentre gli altri argomenti hanno un valore predefinito che può essere modificato in base alle preferenze. L'argomento della porta di comunicazione non richiede identificatori e può essere inserito in qualsiasi posizione dopo il nome del file. Gli altri argomenti, che sono facoltativi, richiedono un identificatore.
 Ecco un esempio di un comando tipico in forma lunga e breve:

    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 
 

 

Scarica l'intero codice e guarda il webinar su Modbus 101.

 

Comment

Guillermo Hernández Hernández

ott. 7, 2023
Magnífico ejemplo, muchas gracias por su trabajo, y sus explicaciones, solamente me falta probarlo utilizando una Raspberry Pi 4B y un instrumento marca Select para medir variables eléctricas. Saludos desde la Ciudad de Mérida Yucatán México.

Vaisala

ott. 12, 2023
¡Gracias Guillermo Hernández por tus amables comentarios!

Invia nuovo commento