Prototipagem com Modbus

Programmer coding python, java script, html code on notebook screen
Alex Pohjanpelto
Alex Pohjanpelto
Published:
Fabricação Industrial e Processos
Medições industriais
Ciências biológicas

Você está prototipando ou procurando uma maneira acessível de medir umidade e temperatura em sua aplicação sem comprometer a qualidade das medições? Você também tem algum conhecimento básico sobre linguagens de programação, como Python? Nesse caso, espero mostrar como você mesmo pode registrar dados facilmente por longos períodos de tempo com apenas uma sonda HMP110, um cabo de serviço USB (219690) e um computador com o Python 3 instalado. Vou orientá-lo pelas diferentes seções do código, mas se você não se importar com uma explicação, pode pular para o final do código inteiro. Também gostaria de salientar que este é apenas um script de exemplo demonstrando a comunicação Modbus.

Bibliotecas

Antes de chegarmos ao código, vamos primeiro apresentar as bibliotecas que vamos aproveitar, sendo a mais importante a pymodbus. Nós o usamos para nos comunicar com o probe via Modbus RTU, vamos importar mais especificamente ModbusSerialClient de pymodbus.client.sync. Usamos a biblioteca struct para manipular bits em diferentes tipos de variáveis, a biblioteca time para alterar a taxa de pesquisa, a biblioteca datetime para obter a hora e a data das leituras de dados e importamos argparse para passar argumentos da linha de comando para o código.

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

Parâmetros

Eu adicionei alguns argumentos para ajudar com a flexibilidade do código. Nós os usamos para que possamos alterar facilmente os valores das variáveis a partir da linha de comando sem ter que alterar o código. Os argumentos que achei que poderiam ser úteis são a porta de comunicação, o nome do arquivo onde os dados estão armazenados, o endereço do escravo da sonda, a taxa de sondagem e o comprimento do registro de dados.

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()
 

Conexão Modbus

Primeiro precisamos inicializar um novo cliente Modbus serial com as configurações corretas para nossa sonda. O conjunto de parâmetros neste exemplo deve incluir o método de comunicação, a porta de comunicação, o tempo limite de resposta, a taxa de transmissão, os bits de parada e a paridade. O método é ‘rtu’ para Modbus RTU, a porta depende do seu computador, então explicarei em uma seção abaixo, como identificar a correta. Os outros parâmetros são determinados pelas configurações da sonda, portanto, você precisará consultar sua folha de dados para obter os valores apropriados. Normalmente para as sondas Vaisala, a taxa de transmissão é 19200, os bits de parada são 2 e a paridade é nenhuma.

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

 

Lendo os registros de retenção

Vamos agora criar uma função para ler os registradores de retenção da sonda. Chamamos o método read_holding_registers() da instância do cliente Modbus que criamos na seção anterior para ler os registradores. Precisamos especificar o endereço inicial do registro de retenção, o número de registros e o endereço do escravo da sonda. Receberemos os dados dos registradores em palavras de 16 bits no formato little-endian, que devemos então converter em valores de ponto flutuante de 32 bits.

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
 

Convertendo os registradores em valores de 32 bits

Os registradores são armazenados como inteiros de 16 bits e precisamos convertê-los em floats de 32 bits. Eu criei uma função que pega os valores do registrador e o índice do registrador e retorna um valor de ponto flutuante de 32 bits dos dados nesse índice. Fazemos uso da estrutura do módulo para realizar essa conversão

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

 

Registrando os dados

Agora que podemos ler os registradores de retenção e converter os valores em valores de ponto flutuante de 32 bits, precisamos criar uma função que armazene os valores em um arquivo .csv. Eu criei uma função chamada data_logger() para esse propósito. Ele chama a função holding_registers_data() e anexa os dados recebidos a um arquivo no formato data hora, umidade relativa, temperatura, ponto de orvalho.

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)
 

 

Determinando a porta de comunicação do probe

Primeiro, certifique-se de que sua sonda esteja conectada corretamente ao seu computador.

 

WindowsNo sistema operacional Windows, você pode encontrar a porta COM do dispositivo no Gerenciador de dispositivos. Para abrir a janela do Gerenciador de Dispositivos, abra o Menu Iniciar no canto inferior esquerdo da tela e digite “Gerenciador de Dispositivos”. Ele deve aparecer como o resultado principal em “Melhor correspondência”, abra-o clicando no ícone ou pressionando Enter no teclado. Clique na seta ao lado de Portas (COM e LPT) para expandir as portas. Deve haver um dispositivo listado como “Vaisala USB Device” com a porta COM listada ao lado dele, no nosso caso COM6.

Image
Determining the communication port of the probe

Linux 

No Linux você pode determinar a porta de comunicação digitando o comando “dmesg | grep tty” no terminal. Ele deve retornar, entre outras coisas, uma declaração semelhante a 'cp210x converter now attach to ttyUSBn', onde ttyUSBn é a porta.

Executando o código

Para executar o script, você deve ter todas as bibliotecas instaladas. Se necessário, você pode usar o comando pip

pip3 install -U pymodbus 
to install pymodbus. The other libraries should already come with the python 3 package.
In a command prompt, navigate to the directory where they python script is stored and type 
    python Modbus_RTU -h 

para ajudar com os argumentos. Isso deve aparecer no prompt de comando. Abaixo está uma captura de tela da saída.

Image
Terminal

 

 

 

 

O único parâmetro necessário é a porta de comunicação, enquanto os outros argumentos têm um valor padrão que pode ser alterado de acordo com suas preferências. O argumento da porta de comunicação não requer identificador e pode ser colocado em qualquer lugar após o nome do arquivo. Os outros argumentos que são opcionais requerem um identificador.

Aqui está um exemplo de um comando típico em formato longo e curto:

    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 
 

 

Faça o download de todo o código e Assista ao webinar Modbus 101.

 

Comment

Guillermo Hernández Hernández

out. 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

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

Enviar novo comentário