2013-02-25 92 views
1

我已經使用串口編寫了一個簡單的串口控制器 - 實際上,這是更多Frankstein代碼,其他人寫的代碼片段和我拼湊在一起。隨意嘲笑我的無能,但任何方向將不勝感激。它運行在我的Linux上運行原路返回,Python 2.6中很好,但是當我嘗試在樹莓派,Python 2.7版運行它,我得到這些錯誤:機器人控制器代碼:加載時出錯

Traceback (most recent call last):Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner 
    self.run() 
    File "/usr/lib/python2.7/threading.py", line 504, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 147, in rx 
    self.ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1, bytesize=8, stopbits=1) 
    File "/usr/local/lib/python2.7/dist-packages/serial/serialutil.py", line 260, in __init__ 
    self.open() 
    File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 276, in open 
    raise SerialException("could not open port %s: %s" % (self._port, msg)) 
SerialException: could not open port /dev/ttyUSB0: [Errno 2] No such file or directory: '/dev/ttyUSB0' 

File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 185, in <module> 
    client = ThreadedClient(root) 
    File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 113, in __init__ 
    self.periodicCall() 
    File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 119, in periodicCall 
    self.gui.processIncoming() 
AttributeError: GuiPart instance has no attribute 'processIncoming' 

我的代碼是:

import Tkinter 
import time 
import threading 
import random 
import Queue 
import serial 
import readline 
#import xbee 
import sys 

x="" 

class GuiPart: 
    def __init__(self, master, queue, endApplication): 
     self.sonar = Tkinter.StringVar() # Feeds sonar sensor data to label  
     self.lm = Tkinter.StringVar() # Feeds left motor speed to label  
     self.rm = Tkinter.StringVar() # Feeds right motor speed to label  


     self.queue = queue 
     # Set up the GUI 
     frame1 = Tkinter.Frame(master, bd=200) #Setup frame. 
     frame1.bind("<Key>", key) # Allow frame to handle keypresses. 
     frame1.focus_set() #Set focus of frame so that keypresses activate event. 
     frame1.pack() #Show it. 

     #Button 
     console = Tkinter.Button(frame1, text='Close', command=endApplication) 
     console.pack() 

     # Add more GUI stuff here 
     self.lm.set(0) # Initializes left motor label 
     self.rm.set(0) # Initializes right motor label 
     self.sonar.set(0) # Initializes sonar label 

     #Sonar label 
     sonarLbl = Tkinter.Label(frame1, textvariable=self.sonar) 
     sonarLbl.pack() 

     #Right motor label 
     rmLbl = Tkinter.Label(frame1, text="Left Motor Speed: ", textvariable=self.rm) 
     rmLbl.pack() 

     #Left motor label 
     lmLbl = Tkinter.Label(frame1, textvariable=self.lm) 
     lmLbl.pack() 


def key(self, event): 
     #print "pressed", repr(event.char) 
     #self.sonar = repr(event.char) <------ This should be the line to handle keypresses 
     global x  
     x = repr(event.char) 

def processIncoming(self): 
     """ 
     Handle all the messages currently in the queue (if any). 
     """ 
     while self.queue.qsize(): 
      try: 
       msg = self.queue.get(0) 
       # Check contents of message and do what it says 
       # As a test, we simply print it 

      # Below is where I will parse the "msg" variable, splitting 
      # it (msg.rsplit) to pull out sensor data and update labels. 

       lm, rm, sonar, mknt = msg.rsplit(",") 
       lm = "Left Motor Speed: "+lm 
       rm = "Right Motor Speed: "+rm 
       sonar = "Sonar: "+sonar+" CMs away" 

       self.sonar.set(sonar) # Setting the labels with latest sensor info. 
       self.lm.set(lm) # Setting the labels with latest sensor info. 
       self.rm.set(rm) # Setting the labels with latest sensor info. 

      except Queue.Empty: 
       pass 

class ThreadedClient: 
    """ 
    Launch the main part of the GUI and the worker thread. periodicCall and 
    endApplication could reside in the GUI part, but putting them here 
    means that you have all the thread controls in a single place. 
    """ 
    def __init__(self, master): 
     """ 
     Start the GUI and the asynchronous threads. We are in the main 
     (original) thread of the application, which will later be used by 
     the GUI. We spawn a new thread for the worker. 
     """ 
     self.master = master 

     # Create the queue 
     self.queue = Queue.Queue() 

     # Set up the GUI part 
     self.gui = GuiPart(master, self.queue, self.endApplication) 

     # Set up the thread to do asynchronous I/O 
     # More can be made if necessary 
     self.running = 1 

     self.thread1 = threading.Thread(target=self.workerThread1) 
     self.thread1.start() 

     #Start receiving thread.  
     self.rx = threading.Thread(target=self.rx) 
     self.rx.start() 

     # Start the periodic call in the GUI to check if the queue contains 
     # anything 
     self.periodicCall() 

    def periodicCall(self): 
     """ 
     Check every 100 ms if there is something new in the queue. 
     """ 
     self.gui.processIncoming() 
     if not self.running: 
      # This is the brutal stop of the system. You may want to do 
      # some cleanup before actually shutting it down. 
      import sys 
      sys.exit(1) 
     self.master.after(100, self.periodicCall) 

    def workerThread1(self): 
     """ 
     This is where we handle the asynchronous I/O. For example, it may be 
     a 'select()'. 
     One important thing to remember is that the thread has to yield 
     control. 
     """ 
     while self.running: 
      # To simulate asynchronous I/O, we create a random number at 
      # random intervals. Replace the following 2 lines with the real 
      # thing. 
      time.sleep(rand.random() * 0.3) 
      msg = rand.random() 

     #self.queue.put(msg) 


    # Continuously read and print packets 
    def rx(self): 
     global x 
     self.ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1, bytesize=8, stopbits=1) 
     self.ser.flush() 
     while(1): 
      response = str(self.ser.readline()) 

      # Send movement codes.  
      if x == "'a'" or x == "'A'": # or "'A'": # Turn left. 
      self.ser.write('4') 
      elif x == "'w'" or x == "'W'": #Go forward. 
      self.ser.write("3") 
      elif x == "'d'" or x == "'D'": #Turn right. 
      self.ser.write("2") 
      elif x == "'s'" or x == "'S'": #Go back. 
      self.ser.write("1") 
      elif x == "'x'" or x == "'X'": #Stop. 
      self.ser.write("5") 
      elif x == "'1'": #Raise speed. 
      self.ser.write("7") 
      elif x == "'2'": #Lower speed. 
      self.ser.write("6") 

      x = "" 

      if len(response) > 10: 
       self.ser.flushInput() #If you don't flush the buffer, then it'll try to read out all 
           #the sensor readings, so the reaction time will be extrordinary. 
       time.sleep(.1)# This scales back the CPU usage. 
       self.queue.put(response) 

    def endApplication(self): 
     print "Closing" 
     self.running = 0 
     self.ser.close()  
     sys.exit(1) 

rand = random.Random() 
root = Tkinter.Tk() 

client = ThreadedClient(root) 
root.mainloop() 

回答

1

您的self.guiGuiPartGuiPart沒有processIncoming

0

在你的代碼片段顯示的線條

def key(self, event): 

def processIncoming(self): 

以上是不再由四個空格縮進,因爲他們也許應該成爲你GuiPart類的方法。

來自其他語言的Python新手經常會錯過縮進是Python編程語言中語法非常重要的部分的細節。因此避免混合TAB和空間也是非常重要的。 (尤其是當複製來自各種源的代碼片段,否則 是學習和嘗試新事物的好機會)

另一件事是:在Python中,您還可以定義模塊級全局函數。 執行此操作的語法實際上與用於在類中定義方法的語法(除了縮進級別之外)相同。

因此,在您的示例代碼片段中,以前的方法key()processIncoming()已成爲模塊全局函數定義,而不是簡單地通過錯誤縮進方法。

方法是類對象的屬性。將這兩種方法從類名稱空間一級移動到模塊名稱空間的 。 因此下面的錯誤信息:

AttributeError: GuiPart instance has no attribute 'processIncoming'