Конвертировать RS232 Ascii в Modbus TCP с помощью Pymodbus - PullRequest
1 голос
/ 12 марта 2019

Я пытаюсь преобразовать данные строки RS252 Ascii из датчика в регистры ввода / хранения Modbus TCP, используя pymodbus Callback Sever , сервер является основными данными отчетов при запросе кклиентский регистратор, и я не уверен, что мне нужно сделать, чтобы это заработало.В настоящее время я могу прочитать данные и записать их в файл CSV, используя эту

#!/usr/bin/env python
# Log data from serial port


import argparse
import serial
import datetime
import time
import os


parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-d", "--device", help="device to read from", default="/dev/ttyUSB0")
parser.add_argument("-s", "--speed", help="speed in bps", default=9600, type=int)
args = parser.parse_args()

outputFilePath = os.path.join(os.path.dirname(__file__),
                 datetime.datetime.now().strftime("%Y-%m-%d") + ".csv")

with serial.Serial(args.device, args.speed) as ser, open(outputFilePath,'w') as outputFile:
    print("Logging started. Ctrl-C to stop.") 
    try:
        while True:
            time.sleep(0.2) 
            x = (ser.read(ser.inWaiting())) 
            data = x.decode('UTF-8')
            if data !="":
                outputFile.write(time.strftime("%Y/%m/%d %H:%M ") + " " + data  )
                outputFile.flush()

    except KeyboardInterrupt:
        print("Logging stopped")

Строка с датчика выходит из устройства в виде:

 0.00 0.0 0.0 346.70 25.14

Мне нужноу каждой части есть свой собственный регистр Modbus, и я пытаюсь использовать pymodbus на Raspberry Pi Zero.Датчик обновляется 4 раза в секунду, и я могу разбить данные на части, я просто еще не дошел до этого, потому что я не уверен, что мне нужно делать в скрипте обратного вызова, я еще не настолько разбираюсь в PythonЯ все еще учусь.У меня есть понимание Modbus TCP, и я уже использовал его в системах Arduino.Любая помощь будет оценена.

1 Ответ

2 голосов
/ 12 марта 2019

Вам нужен сервер обновлений , который вы можете использовать для заполнения регистров.Вам нужно сосредоточиться на функции def updating_writer и выполнять последовательное чтение, обрабатывать их и записывать в регистры по вашему выбору.Пример трудно прочитать и понять с первого взгляда.Я изменил пример , чтобы удовлетворить ваши потребности.Но вот некоторые ключевые понятия, которые будут полезны для понимания кода.

ModbusSlaveContext

BinaryPayloadBuilder

Также обратите внимание,В этом примере используется асинхронный сервер на основе витой. Если вы новичок в витой или у вас есть ограничения, которые не позволят вам использовать витую на своей цели, вы можете добиться того же с помощью простых потоков.Дизайн будет примерно таким:

  1. Запустите функцию обновления в отдельном потоке
  2. Запустите ваш TCP-сервер в конце (блокировка)
# Complete gist here --> https://gist.github.com/dhoomakethu/540b15781c62de6d1f7c318c3fc8ae22
def updating_writer(context, device, baudrate):
    """ A worker process that runs every so often and
    updates live values of the context. It should be noted
    that there is a race condition for the update.
    :param arguments: The input arguments to the call
    """
    log.debug("updating the context")
    log.debug("device - {}, baudrate-{}".format(device, baudrate))
    data = serial_reader(device, baudrate)  # Implement your serial reads, return list of floats.
    if data:
        # We can not directly write float values to registers, Use BinaryPayloadBuilder to convert float to IEEE-754 hex integer
        for d in data:
            builder.add_32bit_float(d)
        registers = builder.to_registers()
        context = context
        register = 3  # Modbus function code (3) read holding registers. Just to uniquely identify what we are reading from /writing in to.
        slave_id = 0x01 # Device Unit address , refer ModbusSlaveContext below
        address = 0x00 # starting offset of register to write (0 --> 40001)
        log.debug("new values: " + str(registers))
        context[slave_id].setValues(register, address, registers)

Когда сервер запущен и значения обновляются, вы можете использовать клиент для считывания значений и синтаксического разбора его на плавающее значение.

from pymodbus.client.sync import ModbusTcpClient as Client
from pymodbus.payload import BinaryPayloadDecoder, Endian
client = Client(<IP-ADDRESS>, port=5020)

# Each 32 bit float is stored in 2 words, so we will read 10 registers 
raw_values = client.read_holding_registers(0, 10, unit=1)
if not registers.isError():
    registers = raw_values.registers
    decoder = BinaryPayloadDecoder.fromRegisters(registers, 
    wordorder=Endian.Big, byteorder=Endian.Big)

    for _ in range(5):
        print(decoder.decode_32bit_float())

...