2012-11-20 31 views
0

我想構建一個gui並從串口接收數據並顯示在一個plot(使用matplotlib)中。但是當我打開端口時,read()失敗。我無法弄清楚爲什麼。有誰能給我一些建議嗎?這將不勝感激! 這裏是我的代碼部分: `pyserial和wxpython matplotlib線程中的讀取方法失敗

class PlotFigure(wx.Frame): 
    """Matplotlib wxFrame with animation effect""" 
    def __init__(self): 
     wx.Frame.__init__(self, None, wx.ID_ANY, title="Figure for figures", size=(1200, 1200)) 
     # Matplotlib Figure 
     self.fig = Figure((6, 4), 100) 
     # bind the Figure to the backend specific canvas 
     self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig) 
     # add a subplot 
     self.ax = self.fig.add_subplot(111) 
     # limit the X and Y axes dimensions 
     self.ax.set_ylim([-180, 180]) 
     self.ax.set_xlim([0, POINTS]) 

     self.ax.set_autoscale_on(False) 
     self.ax.set_xticks([]) 
     # we want a tick every 10 point on Y (101 is to have 10 
     self.ax.set_yticks(range(-180, 180, 50)) 
     # disable autoscale, since we don't want the Axes to ad 
     # draw a grid (it will be only for Y) 
     self.ax.grid(True) 
     # generates first "empty" plots 
     self.user1=self.user2=self.user3 = [None] * POINTS 
     self.l_user1,=self.ax.plot(range(POINTS),self.user1,label='data1') 
    self.l_user2,=self.ax.plot(range(POINTS),self.user2,label='data2') 
    self.l_user3,=self.ax.plot(range(POINTS),self.user3,label='data3') 


     # add the legend 
     self.ax.legend(loc='upper center', 
          ncol=4, 
          prop=font_manager.FontProperties(size=10)) 
     # force a draw on the canvas() 
     # trick to show the grid and the legend 
     self.canvas.draw() 
     # save the clean background - everything but the line 
     # is drawn and saved in the pixel buffer background 
     self.bg = self.canvas.copy_from_bbox(self.ax.bbox) 
     # bind events coming from timer with id = TIMER_ID 
     # to the onTimer callback function 
     wx.EVT_TIMER(self, TIMER_ID, self.onTimer) 

    #for serial 
    self.ser=serial.Serial('COM1', 115200) 
    #print self.ser 

    def onTimer(self, evt): 
    print 'onTimer....' 
     """callback function for timer events""" 
     # restore the clean background, saved at the beginning 
     self.canvas.restore_region(self.bg) 
     # update the data 
    time.sleep(1) 
     self.ser.flushInput() 
     print 'before the read method....' 
    data=self.ser.read(12) 
     print 'after the read method... just cant reach here...' 
    t = struct.unpack('3f', data) 
     temp1 = t[0] 
    temp2 = t[1] 
    temp3 = t[2] 
     self.user1 = self.user1[1:] + [temp1] 
    print temp2 
    self.user2 = self.user2[1:] + [temp2] 
    self.user3 = self.user3[1:] + [temp3] 
     # update the plots 
     self.l_user1.set_ydata(self.user1) 
    self.l_user2.set_ydata(self.user2) 
    self.l_user3.set_ydata(self.user3) 
     # just draw the "animated" objects 
     self.ax.draw_artist(self.l_user1) 
    self.ax.draw_artist(self.l_user2) 
    self.ax.draw_artist(self.l_user3)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated) 
     self.canvas.blit(self.ax.bbox) 
    print 'onTimer ends' 
    def __del__(self): 
    self.ser.close() 
    t.Stop() 

if __name__ == '__main__': 
    app = wx.PySimpleApp() 
    frame = PlotFigure() 
    t = wx.Timer(frame, TIMER_ID) 
    t.Start(1) 
    print 'new test' 
    frame.Show() 
    print 'after frame show ' 
    app.MainLoop() 

I wonder if it is the thread problem.so I do an another test: Here is part of my code:

ser =serial.Serial(port='COM1',baudrate=115200,xonxoff=0) 
def reading(ser): 
    flag = 1 
    print 'threading' 
    while True: 
      print ser.readable() #true 
      print 'before the read method.' 
     data = ser.read(12) 
     print 'after the read method... cant reach here.' 
     time.sleep(1) 

if __name__ == '__main__': 
    threading.Thread(target=reading,args=(ser,)).start() 
    print 'main process1' 

` read方法失敗!

然後是另一個簡單的測試,我擺脫了線程,它工作正常! 這裏是我的部分代碼: `

ser = serial.Serial('COM1', 115200) 
num=0 
try: 
    while True: 

     data = ser.read(12) 
     print num 
     time.sleep(1)  
     ser.flushInput() 


finally: 
    ser.close() 

`

+0

爲什麼是連接線,爲兩個不同的? 'serial.Serial(port ='\\。\ COM1',baudrate = 115200,xonxoff = 0)'vs'serial.Serial('COM1',115200)' – Tim

+0

@Tim,那就沒有區別。至少在我的測試中。 – Don

回答

0
# 
# The following is an example of an application I have running using the 
# serial port. Although the baud is lower, it should not matter. This application 
# will capture each byte and append them into a buffer before processing. All bytes 
# are captured including non-printable characters. The terminator in my application 
# is the RETURN character (0x0A) or the (0x0D) denoting end of line. 
# I think your port is hung waiting on the full twelve (12) bytes that you are 
# expecting on the read. The hang condition is because only a portion of 
# the 12 bytes have occurred. I suggest you add a timeout value of 1 second 
# to the serial read, then test for the length of what was read to validate 
# what you think you just read. If zero, you have a serial cable or problem 
# at the other end of the cable. If greater than zero, then the device is 
# not sending what you think it should. 

import serial 
import string 
import binascii 
import threading 
import thread 
import fileinput 
import datetime 
import time 
import sys 

from configobj import ConfigObj 


# Insert following code at top in the import area of your application 
# 
hdrFile = 'AppName.ini' 
config = ConfigObj(hdrFile) 
hdrVal = 'COM' 
comport = int(config[hdrVal]) 
hdrBaud = 'Baudrate' 
baudrate = config[hdrBaud] 

print "Com Config = ",config 
print "Com Port = ",comport 

boolSerOnline = False 
bool_IsALIVE = False  # thread has active serial port 

class myThread(threading.Thread): 
    def __init__(self, intThreadID, strName, intCountVal): 
     # --------------------------------------- Constructor 
     threading.Thread.__init__(self) # <<-- MUST be first in Init 
     self.threadID = intThreadID 
     self.threadName = strName 
     self.intStartCounter = intCountVal 
    def run(self): 
     # --------------------------------------- Tooltalk 
     # Thread to Listen to the RS-232 RX Port 
     # ------------------------------- TOOLTALK() 
     # ------------------------------- THREAD 
     global bool_IsALIVE, boolThreadRun 
     # 
     # 
     inbuf = []   # Clear Buffer 
     buffer = ""   # Clear Buffer 
     strFirstByte = "" 
     boolWriteCRLF = 0 
     # 
     print "\n*** Starting %s: %s" % (self.threadName, time.ctime(time.time())) 
     print "\n" 
     # 
     bool_IsALIVE = False 
     # 
     # ----------------------------------- Start of Thread Loop 
     while (boolThreadRun): 
      # ----------------------------- THREAD is Running 

      try: 
       # ------------ Read 1 byte at a time in thread 
       # Note: reads all characters, Even non-printable characters 
       strByte = str(ser.read(1)) 
       # 
       intLength = len(strByte) 
       # 
       if (intLength > 0): 
        bool_IsALIVE = True   # Indicate connected 
        # Process byte 
        # 
        if (strFirstByte == ""): 
         boolWriteCRLF = 0 
         # 
         if (strByte == '\r'): 
          strByte = ''   # Skip until we have first byte 
         elif (strByte == '\n'): 
          strByte = ''   # Skip until we have first byte 
         elif (strByte == '0'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte 
          boolWriteCRLF = 1 
         elif (strByte == 'S'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte 
          boolWriteCRLF = 1 
         elif (strByte == 'C'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte 
          boolWriteCRLF = 1 
         elif (strByte == '*'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte  # save first byte of string 
          boolWriteCRLF = 1 
         elif (strByte == '>'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte  # save first byte of string 
          boolWriteCRLF = 1 
         elif (strByte == 'M'): 
          inbuf = []      # Clear buffer first 
          inbuf.append(strByte)  # Add to inbuf 
          buffer = ''.join(inbuf)  # join the two buffers 
          strFirstByte = strByte  # save first byte of string 
          boolWriteCRLF = 1 
         else: 
          pass 
        else: 
         inbuf.append(strByte)  # Add to inbuf 
         buffer = ''.join(inbuf)  # join the two buffers 
       else: 
        # serial driver timed out producing No byte 
        # print "SKIP - NO BYTE (NO POWER?)" 
        pass 
      except: 
       bool_IsALIVE = False 
       print "[Tooltalk] Error reading Serial Port" 



if __name__ == "__main__": 
    try: 
     # *** +++++++++++++ Notice the 1 second timeout ... 
     ser = serial.Serial(comport,baudrate,8,'N',1,timeout=1) 
     boolSerOnline = True 
    except: 
     print "[Main] Serial Port NOT Connected\n" 
     boolSerOnline = False 

    boolThreadRun = True  # Flag indicating "Tooltalk" to Run 
    # 
    thread1 = myThread(1, "Tooltalk-1", 1) # Init Thread 
    thread1.start()  # Start Tooltalk Thread