一、应用场景
我们在串口设备连入主机的时候,特别是串口设备多时候,通过【我的电脑】中的【设备管理】查看COM口的编号不是固定的,有时候跟插拔的先后关系也有关系,插拔顺序变了,其串口序号也就变了:
Windows USB虚拟串口驱动的COM口分配一般均遵循以下原则:
针对USB描述符中内置USB Serial Number(USB串行序列号)的USB串口设备如CH343,默认系统会根据设备内置的SN编号,为其分配固定的COM口号,此时可以实现设备连接不同USB口时COM口均固定不变的效果,连接多个不同设备时因各芯片的USB Serial Number编号均不同,会分别对应生成不同的固定COM口。
针对USB描述符不包含USB Serial Number的USB串口设备如CH340和CH341,系统会根据设备的USB Location(USB位置)来分配COM口号,当连接不同的USB口时,因为USB端口的位置不同所以生成的COM口号也不同。
------详细见原文链接
点开串口的详细信息,很多USBCOM设备也无法读取区分其它设备的ID号,或者方法太复杂,于是,干脆我们采用直接使用打开串口号,去逐个询问的方式(即发送一个自定义字符串,然后检测回来的设备响应)来判断是否是我们想要的设备。
二、设备端增加串口询问机制
本次接入的是仿UARM的机械臂设备设备USB专串口设备,
在控制终端植入了接受询问自定义设备号的串口通讯响应代码,主要思路是:
1、设置本设备的ID号:如,ID000118
2、设置询问ID号的询问代码,如G999 ARMID
3、根据询问,返回自定义的ID号
如设备为arduino,则可以这样代码:
String responstr="G999 ID000118";//回复字符串
String recestr="";
void setup() {
Serial.begin(9600); //串口波特率
}
void loop() {
recestr= "";
while (Serial.available() > 0)
{
recestr += char(Serial.read()); // read是剪切,而不是复制
delay(10); // 延时
}
if(recestr=="G999 ARMID"){
Serial.println(responstr);//答复设备ID号
}
`
三、python上位机端轮询USB端口
定义号自己串口设备查询服务接口后,我们就可以在python上位机侧,运行主程序时,先进行USB串口的查询,并根据串口号进行逐一打开发送设备查询字符串,如果接受到的响应是我们约定的响应,那么说明这个端口就是我们想要的端口,这样就实现了自动识别COM口的目的,这样就不用单向多个设备插入顺序的问题了。
python代码如下:
import serial.tools.list_ports
import time
# 查询所有可用的串口
ports = list(serial.tools.list_ports.comports())
# 输出所有串口的信息
for port in ports:
comnum= list(port)[0]
print("conenct ",comnum)# 设置要使用的串口号
ser = serial.Serial(comnum, baudrate=9600, timeout=1)
# 发送字符串
ser.write("G999 ID000118".encode())
time.sleep(0.5)
# 等待接收特定的字符串
expected_str = 'G999 ID000118'
while Ture:
if ser.in_waiting:
# 读数据
received_str = ser.readall()
break
else:
print("no resposne")
break
if received_str[:7] != expected_st[:7]r:
# 返回串口号
print('Received on port: ' + comnum)
# 关闭串口
ser.close()
四、总结
以上方法虽然可以解决串口自动选择问题,但如果插入一个不是自定义串口设备,可能需要先进行相应询问字符串的测试,找到一个适合唯一定位该设备的询问字符串,然后加入询问列表,这样就可以丰富所自动接入的串口设备了。当然,此方法未从本质上即设备的唯一标识识别入手,如果网友知道这个更本质的方法,请分享出来,将收益不少玩物联网的人们。