使用pyserial读取多个串行设备时出现大延迟

时间:2017-01-04 10:04:25

标签: python gps pyserial uart

我尝试使用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 

运行代码时,如果我发表评论&#39; pos = gps.gps_getData(gpsSerial)&#39;和&#39; print pos&#39; &#34;激光&#34;设备输出几乎是即时的。取消注释&#34;激光&#34;输出非常滞后。

如果相关,我会在桌面计算机上运行代码。

任何人都可以建议我如何摆脱滞后?

  • 编辑:我已经更改了代码以在多个线程中运行这两个函数。关于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()

正如评论中所提到的,这个&#34;解决了&#34;手头的问题。不幸的是,我仍然不明白为什么需要这样做。

1 个答案:

答案 0 :(得分:1)

对于每个线程,将有以下同步资源:

  • 指示周期何时结束的事件和收到的数据
  • 共享变量,其中存储要打印的数据
  • 指示何时可以开始新周期的另一个事件。每个线程都必须在开始循环之前等待这个标志,并且当两个线程结束它们各自的任务时将被引发。

我没有彻底检查以下代码的语法,因此可能存在一些语法错误。基本上,线程在读取串行端口时与主程序同步。当主程序允许开始新的循环时,它们再次并行读取端口。

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