How to read serial data with multiprocessing in python?

ε祈祈猫儿з 提交于 2019-12-02 11:24:12

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")
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!