环境:ubuntu18.04 python3.6

1. 绑定串口号与串口设备

背景:一台主机与多个串口模块连接,每次开机会使得设备的串口号发生变化,需要对串口号与串口设备进行绑定。
(1)查看串口设备号
拔插串口设备,终端lsusb找出需要命名的设备号,形式如下:

Bus 003 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

记录设备号 067b:2303,自定义绑定规则:
(2) cd /etc/udev/rules.d
(3) 创建自定义规则文件 sudo gedit usb.rules
(4)输入如下命令绑定串口号,其中idVendor和idProduct为(1)记录的设备号,SYMLINK”为自定义的设备名字。

KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE:="0777", SYMLINK+="imu"

(5)使规则生效:

sudo udevadm control –reload-rules
sudo service udev restart 
sudo udevadm trigger

(6)使用 /dev/imu读取设备即可。

2. modbus_tk 读取设备

2.1 安装modbus_tk

pip install pymodbus_tk

2.2 读取串口demo

参考链接

# -*- coding: utf_8 -*-

# 2021-08-11 添加自动扫描COM口的程序 @1

import serial.tools.list_ports    #@1 获取COM口列表库

import serial
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
import time           #添加定时器
from time import *
import numpy as np

Baudrate = [9600,115200,19200,38400,57600]


# @1 start 获取现有COM口程序
ports = serial.tools.list_ports.comports()
for p in ports:
    print(p.device)
print(len(ports), 'ports found')

#time.sleep(1) #延时1s(可以不延时,方便看输出)
# @1 end


def mod(BAUDRATE,SlaveID):
    red = []
    alarm = ""
    try:
        # 设定串口为从站
        # p.device 为读取的串口设备名,默认为ttyUSB*,可以替换为自定义设备名,如/dev/imu
        # baudarate 为波特率
        master = modbus_rtu.RtuMaster(serial.Serial(port=p.device,
                                                    baudrate=BAUDRATE, bytesize=8, parity='N', stopbits=1))
        master.set_timeout(0.05)  #50ms
        master.set_verbose(True)

        # 读保持寄存器
        # SlaveID为站台号,0为地址,2为读取长度,可查看设备文档获取地址信息与含义
        # cst.READ_HOLDING_REGISTERS 为读取保持寄存器,2.3有其他的功能码说明
        red = master.execute(SlaveID, cst.READ_HOLDING_REGISTERS, 0, 2)  # 这里可以修改需要读取的功能码
        print(red)
        alarm = "正常"
        
       # return list(red), alarm
        return alarm

    except Exception as exc:
        #print(str(exc))
        alarm = (str(exc))
        

    return red, alarm  ##如果异常就返回[],故障信息


if __name__ == "__main__":

    print("开始扫描当前设备站号和波特率,全部扫描结束时间为90S左右")
    print("雷达站号范围:1-100,波特率:9600、19200、38400、57600、115200")
    print("----------------------------------------")
    begin_time = time()
    for x in range(5):
        for y in range(1,100):
            z = mod(Baudrate[x],y)
            if z == '正常':
                print("当前波特率:",Baudrate[x],"当前站号:",y)
    end_time = time()
    run_time = end_time - begin_time
    print("查询运行时间:",run_time)

2.3 功能码

参考链接
READ_COILS H01 读线圈
READ_DISCRETE_INPUTS H02 读离散输入
READ_HOLDING_REGISTERS H03 读寄存器
READ_INPUT_REGISTERS H04 读输入寄存器
WRITE_SINGLE_COIL H05 写单一线圈
WRITE_SINGLE_REGISTER H06 写单一寄存器
WRITE_MULTIPLE_COILS H15 写多个线圈
WRITE_MULTIPLE_REGISTERS H16 写多寄存器

#读保持寄存器 03H 1站号 0地址 长度2 
logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 2))
#01 03 00 00 00 02 C4 0B

# 读输入寄存器 04H    
logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 0, 8))
#反馈:01 04 00 00 00 08 F1 CC

# 读线圈寄存器 01H   
logger.info(master.execute(1, cst.READ_COILS, 0, 6))
#反馈:01 01 00 00 00 06 BC 08

#读离散输入寄存器 02H
logger.info(master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 16))
#反馈:01 02 00 00 00 10 79 C6 

# 单个读写寄存器操作 06H
# 写寄存器地址为0的保持寄存器 06H  
logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 0, output_value=6))
#反馈:01 06 00 00 00 06 09 C8
 
logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 1))
#反馈:01 03 00 00 00 01 84 0A

# 写寄存器地址为0的线圈寄存器,写入内容为0(位操作) 05H
logger.info(master.execute(1, cst.WRITE_SINGLE_COIL, 0, output_value=0))
#反馈:01 05 00 00 00 00 CD CA 

logger.info(master.execute(1, cst.READ_COILS, 0, 1))
#反馈:01 01 00 00 00 01 FD CA

# 多个寄存器读写操作 10H
# 写寄存器起始地址为0的保持寄存器,操作寄存器个数为4
logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 11, output_value=[20,21,22,23]))
#反馈:01 10 00 0B 00 04 08 00 14 00 15 00 16 00 17 AB A9

logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))
#反馈:01 03 00 00 00 04 44 09 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐