python - 使用 Pymodbus 将 RS232 Ascii 转换为 Modbus TCP

标签 python raspberry-pi modbus pymodbus

我正在尝试使用 pymodbus 将 RS252 Ascii 字符串数据从传感器转换为 Modbus TCP 输入/保持寄存器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 寄存器,并且我正在尝试在 Raspberry Pi Zero 上使用 pymodbus。传感器每秒更新 4 次,我能够将数据分成几部分,我只是还没有做到这一点,因为我不确定我需要在回调脚本中做什么,我还不熟悉 Python我是我还在学习。我确实了解 Modbus TCP,并且之前在 Arduino 系统上使用过它。任何帮助将不胜感激。

最佳答案

您需要的是updating server ,您可以使用它来填充寄存器。您必须专注于函数 def moving_writer 并执行串行读取、处理它们并写入您选择的寄存器。这个例子在第一次使用时很难阅读和理解。我修改了example满足您的需求。但这里有一些关键概念,可以方便地理解代码。

ModbusSlaveContext

BinaryPayloadBuilder

另请注意,该示例使用基于twisted的异步服务器,如果您不熟悉twisted或有一些限制不允许您在目标上使用twisted,您也可以使用简单的线程实现相同的目的。设计大概是这样的。

  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)

服务器运行并且值更新后,您可以使用客户端读取值并将其解析回 float 。

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

关于python - 使用 Pymodbus 将 RS232 Ascii 转换为 Modbus TCP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55111572/

相关文章:

python - 尝试将 keras 中具有相同形状的两个层连接起来,导致形状匹配出现错误

python - 导入错误: cannot import name redirect_stderr

opencv - 生成文件:160: recipe for target 'all' failed

python - 如何用 Python 发送十六进制

c - 在 Raspberry Pi 上构建源代码

php - CRC-CCITT 到 CRC16 Modbus 实现

python - 基于kmeans聚类中心绘制边界线

python - 为什么我的脚本没有写入文件?

telnet - 通过 Internet 向 Modbus 设备发送查询

c - 带有 C 共享库的 ffi Node.js 中的 undefined symbol - libmodbus