使用pyserial读取多个串行设备时延迟大
Large delay when reading multiple serial devices using pyserial
我正在尝试使用 pyserial 从多个串行设备读取数据,并将所有内容同步在一起。最后我希望代码为:
- read serial from laser
- read serial from gps
- get a single string with [gps_reading, laser_reading]
GPS 刷新率高达 5hz
激光按需发送高达 20 赫兹左右的值
孤立地,它们都工作正常,我的响应时间也很快。但是,当我尝试读取多个数据时,我会出现延迟,而且延迟会随着时间的推移而增加。
代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
import time
import gps
import laser
#serial
def serialGeneric(device, baudRate):
ser = serial.Serial(
port=device,
baudrate=baudRate,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
return ser
#Device 1
gpsSerial = serialGeneric("/dev/ttyUSB0",9600)
gps.gps_init(gpsSerial)
#Device 2
laserSerial = serialGeneric("/dev/ttyUSB1",19200)
i = 1
start_time = time.time()
while i<50:
dis = laser.lrf_getDistance(laserSerial)
print dis
pos = gps.gps_getData(gpsSerial)
print pos
i+=1
print("--- %s seconds ---" % (time.time() - start_time))
gps 和激光功能只需发送适当的命令来请求数据:
即
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
def lrf_getDistance(ser):
i = 0
while i == 0:
ser.write("d\r\n")
ser.flush()
msg = ser.readline()
try:
msg = float(msg)
i == 1
return msg
except ValueError:
pass
当 运行 编译代码时,如果我注释掉 'pos = gps.gps_getData(gpsSerial)' 和 'print pos',"laser" 设备输出几乎是立即的。取消注释后 "laser" 输出非常滞后。
以防相关,我运行在台式机上编写代码。
任何人都可以建议我如何摆脱滞后吗?
- 编辑:我已将代码更改为 运行 两者都在多线程中运行。遵循 python.
中关于多线程的 tutorialspoint 教程
新代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
import time
import threading
import gps
import laser
#serial
def serialGeneric(device, baudRate):
ser = serial.Serial(
port=device,
baudrate=baudRate,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
#timeout=0
)
return ser
#Device 1
gpsSerial = serialGeneric("/dev/ttyUSB0",9600)
#Device 2
laserSerial = serialGeneric("/dev/ttyUSB1",19200)
class myThreadGPS (threading.Thread):
def __init__(self, ser):
threading.Thread.__init__(self)
self.ser = ser
def run(self):
print "Starting GPS"
gps.gps_getDataINF(self.ser)
class myThreadLAS (threading.Thread):
def __init__(self, ser):
threading.Thread.__init__(self)
self.ser = ser
def run(self):
print "Starting Laser"
laser.lrf_getDistanceINF(self.ser)
# Create new threads
thread1 = myThreadGPS(gpsSerial)
thread2 = myThreadLAS(laserSerial)
# Start new Threads
thread1.start()
thread2.start()
如评论中所述,这 "solved" 手头的问题。不幸的是,我仍然不太明白为什么需要这样做。
对于每个线程,将有以下同步资源:
- 指示循环何时结束以及收到数据的事件
- 共享变量,存储要打印的数据
- 另一个指示何时可以开始新循环的事件。每个线程在开始循环之前必须等待这个标志,并且会在两个线程结束各自的任务时引发。
我没有仔细检查以下代码的语法,因此可能存在一些语法错误。基本上,线程在读取串行端口时与主例程同步。当主程序允许开始一个新的循环时,他们再次并行读取端口。
class myThreadGPS (threading.Thread):
def __init__(self, ser, start_event, end_event, pos):
threading.Thread.__init__(self)
self.ser = ser
self.start_event = start_event
self.end_event = end_event
self.pos = pos
def run(self):
self.start_event.wait()
self.start_event.clear()
print "Starting GPS"
self.pos[0] = gps.gps_getDataINF(self.ser)
self.end_event.set()
class myThreadLAS (threading.Thread):
def __init__(self, ser, start_event, end_event, dis):
threading.Thread.__init__(self)
self.ser = ser
self.start_event = start_event
self.end_event = end_event
self.dis = dis
def run(self):
self.start_event.wait()
self.start_event.clear()
print "Starting Laser"
self.dis[0] = laser.lrf_getDistanceINF(self.ser)
self.end_event.set()
#Declare the used events
gps_end_event = threading.Event()
laser_end_event = threading.Event()
gps_start_event = threading.Event()
laser_start_event = threading.Event()
#Initialize shared variables
pos = [None]
dis = [None]
# Create new threads
thread1 = myThreadGPS(gpsSerial, gps_start_event, gps_end_event, pos)
thread2 = myThreadLAS(laserSerial, laser_start_event, laser_end_event, dis)
# Start new Threads
thread1.start()
thread2.start()
#Start events initially set to True
gps_start_event.set()
laser_start_event.set()
while True:
#Wait for both threads to end and reset them.
gps_end_event.wait()
gps_end_event.clear()
laser_end_event.wait()
laser_end_event.clear()
#print the shared variables
print pos[0]
print dis[0]
gps_start_event.set()
laser_start_event.set()
我正在尝试使用 pyserial 从多个串行设备读取数据,并将所有内容同步在一起。最后我希望代码为:
- read serial from laser
- read serial from gps
- get a single string with [gps_reading, laser_reading]
GPS 刷新率高达 5hz 激光按需发送高达 20 赫兹左右的值
孤立地,它们都工作正常,我的响应时间也很快。但是,当我尝试读取多个数据时,我会出现延迟,而且延迟会随着时间的推移而增加。
代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
import time
import gps
import laser
#serial
def serialGeneric(device, baudRate):
ser = serial.Serial(
port=device,
baudrate=baudRate,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
return ser
#Device 1
gpsSerial = serialGeneric("/dev/ttyUSB0",9600)
gps.gps_init(gpsSerial)
#Device 2
laserSerial = serialGeneric("/dev/ttyUSB1",19200)
i = 1
start_time = time.time()
while i<50:
dis = laser.lrf_getDistance(laserSerial)
print dis
pos = gps.gps_getData(gpsSerial)
print pos
i+=1
print("--- %s seconds ---" % (time.time() - start_time))
gps 和激光功能只需发送适当的命令来请求数据: 即
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
def lrf_getDistance(ser):
i = 0
while i == 0:
ser.write("d\r\n")
ser.flush()
msg = ser.readline()
try:
msg = float(msg)
i == 1
return msg
except ValueError:
pass
当 运行 编译代码时,如果我注释掉 'pos = gps.gps_getData(gpsSerial)' 和 'print pos',"laser" 设备输出几乎是立即的。取消注释后 "laser" 输出非常滞后。
以防相关,我运行在台式机上编写代码。
任何人都可以建议我如何摆脱滞后吗?
- 编辑:我已将代码更改为 运行 两者都在多线程中运行。遵循 python. 中关于多线程的 tutorialspoint 教程
新代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import serial
import time
import threading
import gps
import laser
#serial
def serialGeneric(device, baudRate):
ser = serial.Serial(
port=device,
baudrate=baudRate,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
#timeout=0
)
return ser
#Device 1
gpsSerial = serialGeneric("/dev/ttyUSB0",9600)
#Device 2
laserSerial = serialGeneric("/dev/ttyUSB1",19200)
class myThreadGPS (threading.Thread):
def __init__(self, ser):
threading.Thread.__init__(self)
self.ser = ser
def run(self):
print "Starting GPS"
gps.gps_getDataINF(self.ser)
class myThreadLAS (threading.Thread):
def __init__(self, ser):
threading.Thread.__init__(self)
self.ser = ser
def run(self):
print "Starting Laser"
laser.lrf_getDistanceINF(self.ser)
# Create new threads
thread1 = myThreadGPS(gpsSerial)
thread2 = myThreadLAS(laserSerial)
# Start new Threads
thread1.start()
thread2.start()
如评论中所述,这 "solved" 手头的问题。不幸的是,我仍然不太明白为什么需要这样做。
对于每个线程,将有以下同步资源:
- 指示循环何时结束以及收到数据的事件
- 共享变量,存储要打印的数据
- 另一个指示何时可以开始新循环的事件。每个线程在开始循环之前必须等待这个标志,并且会在两个线程结束各自的任务时引发。
我没有仔细检查以下代码的语法,因此可能存在一些语法错误。基本上,线程在读取串行端口时与主例程同步。当主程序允许开始一个新的循环时,他们再次并行读取端口。
class myThreadGPS (threading.Thread):
def __init__(self, ser, start_event, end_event, pos):
threading.Thread.__init__(self)
self.ser = ser
self.start_event = start_event
self.end_event = end_event
self.pos = pos
def run(self):
self.start_event.wait()
self.start_event.clear()
print "Starting GPS"
self.pos[0] = gps.gps_getDataINF(self.ser)
self.end_event.set()
class myThreadLAS (threading.Thread):
def __init__(self, ser, start_event, end_event, dis):
threading.Thread.__init__(self)
self.ser = ser
self.start_event = start_event
self.end_event = end_event
self.dis = dis
def run(self):
self.start_event.wait()
self.start_event.clear()
print "Starting Laser"
self.dis[0] = laser.lrf_getDistanceINF(self.ser)
self.end_event.set()
#Declare the used events
gps_end_event = threading.Event()
laser_end_event = threading.Event()
gps_start_event = threading.Event()
laser_start_event = threading.Event()
#Initialize shared variables
pos = [None]
dis = [None]
# Create new threads
thread1 = myThreadGPS(gpsSerial, gps_start_event, gps_end_event, pos)
thread2 = myThreadLAS(laserSerial, laser_start_event, laser_end_event, dis)
# Start new Threads
thread1.start()
thread2.start()
#Start events initially set to True
gps_start_event.set()
laser_start_event.set()
while True:
#Wait for both threads to end and reset them.
gps_end_event.wait()
gps_end_event.clear()
laser_end_event.wait()
laser_end_event.clear()
#print the shared variables
print pos[0]
print dis[0]
gps_start_event.set()
laser_start_event.set()