2017-01-01 30 views
0

数週間、シリアルCOMポートをスレッドからオープンする方法、つまり を別のスレッドから書き込み/読み込めるようにしています。私の例では、別のスレッドからポートに書き込むと、アクセスが拒否されています。 メインGUIからポートを開くと、正常に動作し、スレッドから書き込むことができますが、ユーザーにCOM番号を選択させる必要があります。 これは、あなたがポートを複数回開くしようとしている...誰もが見て、助けることができるならば、それは素晴らしいことだ、Pythonのスレッドからシリアルポートを開く方法

class Connect(QThread): 
    connectResult = QtCore.pyqtSignal(str) 
    position1 = QtCore.pyqtSignal(str) 
    actuPosResult = QtCore.pyqtSignal(str) 
    def __init__(self, myvar, parent=None): 
     QThread.__init__(self, parent) 
     self.myvar = str(myvar) # value from spinbox 
    def run(self): 
     self.pserial = serial.Serial() 
     try: 
      COMnumber= self.myvar 
      self.pserial = serial.Serial('COM'+COMnumber, 115200,timeout=None) 
      r='COM '+COMnumber+' connected.' 
      self.pserial.write("c".encode('ascii')+"\n".encode('ascii')) 
      incomingByte = self.pserial.read() 
      decodedByte = incomingByte.decode("utf-8") 
      if decodedByte == ('c'): 
       r='Atmega On-Line' 
       self.connectResult.emit(r) 
       pos1='---' 
       self.position1.emit(pos1) 
      else : 
       r=' No answer from Atmega.' 
       self.connectResult.emit(r) 
    def stop(self): 
     self.terminate() 
class ReadingEncoder(QThread): 
    actuPosResult = QtCore.pyqtSignal(str) 
    def __init__(self, mojazmienna, parent=None): 
     QThread.__init__(self, parent) 
     self.mojazmienna = str(mojazmienna) 
    def run(self): 
    Try: 
      self.pserial = serial.Serial() 
      self.pserial = serial.Serial('COM3', 115200,timeout=1) 
      self.pserial.write("p".encode('ascii')+"\n".encode('ascii')) 
      incomingByte = self.pserial.read() 
      decodedByte = incomingByte.decode("utf-8") 
      actualPos = '' 
     if decodedByte == ('a'):   
       while decodedByte != ('\n'): 
        incomingByte = self.pserial.read() 
        decodedByte = incomingByte.decode("utf-8") 
        actualPos = actualPos + decodedByte 
       pos= actualPos.rstrip('\n')# pozycja w formacie string 
       print(pos) 
      self.actuPosResult.emit(pos) 
     except (EOFError, OSError, IOError, ValueError, RuntimeError, BrokenPipeError, InterruptedError, TimeoutError): 
      print('Thread readingEncoder error') 
     self.pserial.close() 
+0

TL; TRを簡略化し、短い例を投稿してください。何が問題ですか?スタックトレース? –

+0

問題は、接続スレッドからシリアルポートを開くと、私はReadingEncoderスレッドからアクセスできないということです。 – Art

答えて

0

私のコードです。

これを行う代わりに、いくつかの選択肢があります。

  • Serialオブジェクトを一度作成し、それを使用するスレッドに渡します。
  • 使用するスレッドに使用するシリアルポートの名前を指定し、ポートをオープンさせます。

どちらの場合も、終了時にスレッドがポートを正しく閉じることを確認してください。

0

シリアルポートを開いてスレッドを開始するだけです。

import atexit 

class SerialPort(QThread): 
    connectResult = QtCore.pyqtSignal(str) 
    position1 = QtCore.pyqtSignal(str) 
    actuPosResult = QtCore.pyqtSignal(str) 

    def __init__(self, port=None, baud=115200, timeout=1): 
     super().__init__() 

     self.ser = serial.Serial() 
     self.ser.port = port 
     self.ser.baudrate = baud 
     self.ser.timeout = timeout 
     self.running = False 
     atexit.register(self.ser.close) # Make sure the serial port closes when you quit the program. 

    def set_port(port_num): 
     self.ser.port = "COM"+str(port_num) 

    def start(self, *args, **kwargs): 
     self.running = True 
     self.ser.open() 
     super().start() 
     self.ser.write("c\n".encode("ascii")) 

    def run(self): 
     while self.running: 
      try: 
       incomingByte = self.ser.read() 
       decodedByte = incomingByte.decode("utf-8") 
       if decodedByte == ('c'): 
        r='Atmega On-Line' 
        self.connectResult.emit(r) 
        pos1='---' 
        self.position1.emit(pos1) 
       else: 
        r=' No answer from Atmega.' 
        self.connectResult.emit(r) 
      except: 
       pass 
      # time.sleep(0.01) # You may want to sleep or use readline 

このクラスを使用するには、startメソッドを呼び出すボタンを使用します。

serial = SerialPort("COM3") 
btn = QtGui.QPushButton("Connect") 
btn.clicked.connect(serial.start) 

通常、シリアルポートは、両端を利用できることが分かっていない限り、1回だけ開くことができます。

シリアルポートはメインスレッド上に存在し、すべての時間が存在します。シリアルポートを連続して開閉する必要はありません。すべての読みはスレッドで発生します。ちょうどserial.write(b"c\n")を呼び出して書く。スレッド内で書かれている必要はありません。

ユーザにcomポートを選択させるには、QLineEditを使用します。

myserial = QtGui.QLineEdit("3") 
myserial.textChanged.connect(serial.set_port) 
+0

HashSplatありがとう、それを再構築し、あなたに知らせる/もっと尋ねます... – Art

+0

それは動作するように見えます。どうもありがとう。私は私の必要性に少し変更を加えましたが、コミュニケーションとエンコーディングはうまく動作します。件名を閉じる前に、別の質問があります:アプリを終了した後。私はメッセージを持っています: "StdErr:QThread:スレッドがまだ動いている間に破棄されました"。アプリケーションを閉じる前にスレッドを停止する方法は?私に教えてください。この質問で新しいトピックを作成する必要がある場合... – Art

+0

これは、アプリケーションが終了してもQThreadが実行中であることを意味します。上記のコードでは、atexitを使用してシリアルポートを閉じます。 atexitは、スレッドを停止してシリアルポートを閉じる関数を登録する必要があります。 'self.running = False'を設定してスレッドを停止し、QThreadがrunメソッドを終了して閉じるのを待つことができます。また、QThreadでstopまたはterminateを呼び出さなければならない場合もあります。 – HashSplat

関連する問題