How to read serial data with multiprocessing in python?

前端 未结 1 653
暗喜
暗喜 2021-01-28 06:49

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.

He

相关标签:
1条回答
  • 2021-01-28 07:32

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

    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)
    

    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.

    The multiprocessing module doesn't like pickling pyserial.

    This following code snip works on my Windows10 box

    • Used threading instead.
    • Added some print statements here ad there to understand what is happening.
    • Used multiprocessing.Event() to improve shutdown.
    • Print exception error messages to see what causes serial exceptions.
    • One second timeout on serial port to allow read loop to continue.
      • Maybe not necessary for release code.


    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")
    
    0 讨论(0)
提交回复
热议问题