使用 Pymodbus 将 RS232 Ascii 转换为 Modbus TCP
Convert RS232 Ascii to Modbus TCP using Pymodbus
我正在尝试使用 pymodbus Callback Sever 将来自传感器的 RS252 Ascii 字符串数据转换为 Modbus TCP Input/Holding 寄存器,当向客户端记录器请求时,服务器是主报告数据,我是不确定我需要做什么才能让它工作。我目前能够读取数据并使用此
将其记录到 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 零上使用 pymodbus。传感器每秒更新 4 次,我能够将数据分成几部分,我只是还没有做到这一点,因为我不确定我需要在回调脚本中做什么,我不是那么精通 Python yet I am 我还在学习。我确实了解 Modbus TCP,并且之前在 Arduino 系统上使用过它。任何帮助将不胜感激。
您所需要的是updating server, which you could use to populate the registers . You will have to focus on function def updating_writer
and do the serial reads, process them and write to registers of your choice. The example is hard to read and understand in first go. I have modified the example满足您的需求。但这里有一些关键概念,有助于理解代码。
另请注意,该示例使用基于 twisted 的异步服务器,如果您是 twisted 的新手或有一些限制不允许您在目标上使用 twisted,您也可以使用简单的线程实现相同的目的。设计大概是这样的
- 在单独的线程中启动更新功能
- 最后启动你的 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())
我正在尝试使用 pymodbus Callback Sever 将来自传感器的 RS252 Ascii 字符串数据转换为 Modbus TCP Input/Holding 寄存器,当向客户端记录器请求时,服务器是主报告数据,我是不确定我需要做什么才能让它工作。我目前能够读取数据并使用此
将其记录到 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 零上使用 pymodbus。传感器每秒更新 4 次,我能够将数据分成几部分,我只是还没有做到这一点,因为我不确定我需要在回调脚本中做什么,我不是那么精通 Python yet I am 我还在学习。我确实了解 Modbus TCP,并且之前在 Arduino 系统上使用过它。任何帮助将不胜感激。
您所需要的是updating server, which you could use to populate the registers . You will have to focus on function def updating_writer
and do the serial reads, process them and write to registers of your choice. The example is hard to read and understand in first go. I have modified the example满足您的需求。但这里有一些关键概念,有助于理解代码。
另请注意,该示例使用基于 twisted 的异步服务器,如果您是 twisted 的新手或有一些限制不允许您在目标上使用 twisted,您也可以使用简单的线程实现相同的目的。设计大概是这样的
- 在单独的线程中启动更新功能
- 最后启动你的 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())