如何在python中使用多处理读取串行数据? [英] How to read serial data with multiprocessing in python?

查看:68
本文介绍了如何在python中使用多处理读取串行数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个以不规则间隔输出数据的设备.我想以 2 秒的间隔将数据写入 csv.所以我认为使用队列进行多处理可能会奏效.

I have a device that outputs data at irregular intervals. I want to write data onto a csv in 2 second intervals. So I figured multiprocessing with a queue might work.

在这里,我试图将数据从一个进程传递到另一个进程,但出现串行异常.另外,我无法在 IDLE 上运行它.所以我坚持使用终端.结果,错误消息一打开就关闭.

Here I'm trying to just pass data from one process to another but I get Serial Exception. Also, I'm unable to run it on IDLE. So I'm stuck with using the terminal. As a result, the error message closes as soon as it opens.

代码如下:

import multiprocessing
import time
import datetime
import serial

try:
    fio2_ser = serial.Serial("COM3",
                baudrate=2400,
                bytesize=serial.EIGHTBITS,
                parity =serial.PARITY_ODD)

except serial.SerialException:
        print("FiO2 Analyser Device not detected")   


def Read_Data(q):
    global fio2_ser

    while True:

        try:                    
            fio2_data = fio2_ser.readline().decode('utf-8')
            fio2_data = str(fio2_data).replace("\r\n","")
            fio2_data = fio2_data.replace("\x000","")

        except:
                fio2_data = "FiO2 Data Unavailable"

        q.put(fio2_data)

def Disp_Data(q):

    while q.empty() is False:

        fio2_data = q.get()
        print(fio2_data)

        time.sleep(2)


if __name__ == "__main__":

    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=Read_Data, args=(q,))
    p2 = multiprocessing.Process(target=Disp_Data, args=(q,))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

当我运行一个单独的模块来收集数据时,它运行良好并收集数据.

When I run a separate module to collect data, it runs fine and collects data.

import serial

try:
    fio2_ser = serial.Serial("COM3",
                baudrate=2400,
                bytesize=serial.EIGHTBITS,
                parity =serial.PARITY_ODD)

except serial.SerialException:
        print("FiO2 Analyser Device not detected")   

def Reader():
    global fio2_ser
    try:                    
        fio2_data = fio2_ser.readline().decode('utf-8')
        fio2_data = str(fio2_data).replace("\r\n","")
        fio2_data = fio2_data.replace("\x000","")
        return fio2_data
    except:
            return "FiO2 Data Unavailable"

if __name__ =='__main__':
    value = Reader()
    print(value) 

推荐答案

当 q.empty() 为 True 时,Disp_Data() 函数将停止运行.在我的情况下,循环立即退出.

The Disp_Data() function will stop running when q.empty() is True. In my case the loop exits immediately.

可能有助于显示 SerialException 抛出的错误消息以查看原因:

Might be useful to display the error message thrown by SerialException to see the cause:

except serial.SerialException as msg:
        print( "Error opening serial port %s" % msg)

此外,最好优雅地关闭子进程.就我而言,它们在杀死主进程后继续运行,因此 Read_Data() 进程保持端口打开.

Also, it would be better to gracefully shut down the child-processes. In my case, they kept running after killing the main process, so the Read_Data() process keeps the port open.

多处理模块不喜欢酸洗 pyserial.

以下代码片段适用于我的 Windows10 机器

This following code snip works on my Windows10 box

  • 改用线程.
  • 在此处添加了一些打印语句,以了解什么是正在发生.
  • 使用 multiprocessing.Event() 来改进关闭.
  • 打印异常错误消息以查看导致串行异常的原因.
  • 串行端口上的一秒超时以允许读取循环继续.
    • 发布代码可能不需要.


    import threading, multiprocessing
    import time
    import serial
    import sys
    
    
    def OpenSerialPort(port=""):
        print ("Open port %s" % port)
    
        fio2_ser = None
    
        try:
            fio2_ser = serial.Serial(port,
                        baudrate=2400,
                        bytesize=serial.EIGHTBITS,
                        parity =serial.PARITY_ODD)
    
        except serial.SerialException as msg:
            print( "Error opening serial port %s" % msg)
    
        except:
            exctype, errorMsg = sys.exc_info()[:2]
            print ("%s  %s" % (errorMsg, exctype))
    
        return fio2_ser
    
    
    def Read_Data(queue, serialPort, stopped):
        print ("Start reading data.")
    
        serialPort.timeout = 1.0
        while not stopped.is_set(): 
            fio2_data = ''       
            try:                    
                #print "Reading port..."
                fio2_data = serialPort.readline()
    
            except:
                exctype, errorMsg = sys.exc_info()[:2]
                print ("Error reading port - %s" % errorMsg)
                stopped.set()
                break
    
            if len(fio2_data) > 0:
                fio2_data = fio2_data.decode('utf-8')
                fio2_data = str(fio2_data).replace("\r\n","")
                fio2_data = fio2_data.replace("\x000","")
                queue.put(fio2_data)
            else:
                queue.put("Read_Data() no Data")
    
        serialPort.close()
        print ("Read_Data finished.")
    
    def Disp_Data(queue, stopped):
        print ("Disp_Data started")
        while not stopped.is_set():
            #print "Check message queue."
            if queue.empty() == False:        
                fio2_data = queue.get()
                print(fio2_data)
    
        print ("Disp_Data finished")
    
    if __name__ == "__main__":
    
    
        #serialPort = OpenSerialPort('/dev/ttyUSB0')
        serialPort = OpenSerialPort('COM3')
        if serialPort == None: sys.exit(1)
    
        queue = multiprocessing.Queue()
        stopped = threading.Event()
        p1 = threading.Thread(target=Read_Data, args=(queue, serialPort, stopped,))
        p2 = threading.Thread(target=Disp_Data, args=(queue, stopped,))
    
        p1.start()
        p2.start()
    
        loopcnt = 20
        while (loopcnt > 0) and (not stopped.is_set()):
            loopcnt -= 1
            print ("main() %d" % loopcnt)
            try:
                time.sleep(1)
    
            except KeyboardInterrupt: #Capture Ctrl-C
                print ("Captured Ctrl-C")
                loopcnt=0
                stopped.set()
    
        stopped.set()
        loopcnt=0        
    
        print ("Stopped")
        p1.join()
        p2.join()
    
        serialPort.close()
        print ("Done")
    

    这篇关于如何在python中使用多处理读取串行数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆