2017-01-04 21 views
0

Я пытаюсь прочитать данные из более чем одного последовательного устройства с использованием pyserial с идеей синхронизации всего вместе. В конце я хотел бы код на:Большая задержка при чтении нескольких последовательных устройств с использованием pyserial

- read serial from laser 
- read serial from gps 
- get a single string with [gps_reading, laser_reading] 

GPS-имеет частоту обновления до 5Гц Лазер посылает значения по требованию до около 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 

При выполнении кода, если я закомментируйте «поз = gps.gps_getData (gpsSerial) 'и' print pos 'вывод устройства «лазер» почти сразу. После расторжения «лазерный» выход очень отсталый.

В случае, если это актуально, я запускаю код на настольной машине.

Может кто-нибудь предложить, как я могу избавиться от задержки?

  • EDIT: Я изменил код для запуска обеих функций в нескольких потоках. Следуя руководству по tutorialspoint по многопоточности в python.

Новый код выглядит следующим образом:

#!/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() 

Как уже упоминалось в комментариях, это «решить» вопрос под рукой. К сожалению, я до сих пор не понимаю, почему это было необходимо.

+0

Как вы знаете, что это лазерная инструкция, которая медленная, а не прокомментированная и раскованная?Для того, что вы говорите, кажется, что инструкция gps является медленной. – Jalo

+0

Помните, что вы не устанавливаете какой-либо тайм-аут, поэтому он будет ждать неопределенно долго, пока значение не будет получено при чтении – Jalo

+0

Hi Jalo, спасибо за ваш комментарий, я просто проверил тест, чтобы проверить «GPS», и чтение не отстает, GPS дает мне время, и я вижу, что нет отставания. GPS определенно медленнее (5 Гц) против «лазера» (способный к выборке при 20 Гц). – Khris

ответ

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

Спасибо, я дам вам попробовать сейчас и дам вам знать. Просто чтобы я понял. В основном цикле. Мы сначала установили их в false, а затем установили их в true? Является ли поведение по умолчанию для события True? – Khris

+0

По умолчанию установлено значение False. Таким образом, начальные события должны быть установлены в True в начале, я изменю это – Jalo

+0

Теперь я могу видеть оба события, выполняемые как потоки, однако dis и pos всегда кажется «ничем», и потоки всегда читают значения (не останавливаясь на значениях обновления dis и pos, а не ждать). Может ли это быть из-за моей функции? Защиту lrf_getDistanceINF (серы): \t в то время как True: \t \t тзд = lrf_getDistance (серы) – Khris