web-dev-qa-db-ja.com

開いているシリアルポートをリセットする

Arduinoから送信されたシリアルポートからデータを読み取っています。

私は2つのファイルを持っており、それらを別々に使用してコードを記述し、さまざまなことを試しています。そのうちの1つでは、データを読み取り、matplotlib図を使用して描画します。使い終わった後も、パソコンに接続してデータを送信したままです。だから、私がする必要があるのは、ポートを「リセット」することです。つまり、開いているポートを閉じて再度開き、データの送信を停止して、arduinoを使用してこのファイルのコードにいくつかの変更を加えることができるようにします。

つまり、これを実現するために、つまり、ポートをリセットするために、別のファイルを作成して次のコードを記述しました。

import serial

print "Opening port"

try:
  serial_port = serial.Serial("com4", 9600)
  print "Port is open"

except serial.SerialException:
  serial.Serial("com4", 9600).close()
  print "Port is closed"
  serial_port = serial.Serial("com4",9600)
  print "Port is open again"

print "Ready to use"

しかし、このコードは機能していないようです。ポートはまだ接続されており、データを送信しています。つまり、コードでポートを閉じてから、再度開くことができないということです。

私は何が間違っているのですか? arduinoによるデータの送信を停止するにはどうすればよいですか?または、どうすればarduinoをリセットできますか?

あなたが私を助けてくれることを願っています。

-----編集-----

私は自分が抱えている本当の問題を特定することを達成しましたが、それは私が思っていたものではありません。問題は、Pyserialが持っているclosefunctionを使用しているにもかかわらず、ポートが開いていることではありませんでした。本当のことは、私が望むようにポートが閉じているということですが、デバイス(arduino)はまだデータを送信しています。そこで、状況を再現するためにコードを変更しました。

これはコードです:

print "Abriendo puerto"

ser = serial

try:
  ser = serial.Serial("com4", 9600, timeout = 1)
  serial_port = "Open"
  print "The port %s is available" %ser

except serial.serialutil.SerialException:
  print "The port is at use"

  ser.close()
  ser.open()

while ser.read():
  print "Sending data"

ser.setBreak(True)
time.sleep(0.2)

ser.sendBreak(duration = 0.02)
time.sleep(0.2)

ser.close()
time.sleep(0.2)
print "The port is closed"

exit()

このコードで、私がすることは次のとおりです。

1)シリアルポートを開く

2)デバイスがデータを送信している場合、「データの送信」を印刷します

3)1秒後、ポートを閉じて、デバイスがデータを送信しないようにします

ポートを閉じるためにclose関数でこれらの最後の2つのことを試し、上記のコードでわかるようにsetBreaksendBreakで試したドキュメントを読みました(iわざと残しました)。ただし、デバイスはまだデータを送信しているため、コードは機能しません。

それで、arduinoに「データの送信を停止する」ように伝える方法はありますか、それともデバイスをリセットできますか?

3
Pablo Flores

私は非常によく似たことをします。2つの方法で成功します。

最初の方法は、Arduinoにデータを継続的に送信させることです。ここでの問題は、pythonコードがウェイクアップしてシリアルポートから読み取りを開始すると、Arduinoがプロシージャのどこかにある可能性があることです。簡単な解決策は、Arduinoコードを変更して、ある種の「再起動」行を送信することです。この場合、pythonコードで行う必要があるのは、「再起動」を待ってから、再び「再起動」が表示されるまで実際のデータを読み取ることだけです。ノイズの多い行があったため、コードが複数のサイクルで読み取られ(そして解析され)、適切なデータが取得されたことを確認しました。

resetCount = 0;
while resetCount < 3:
    line = s.readline().rstrip("\r\n")
    if string.find(line, "restart") != -1 :
        resetCount += 1
    Elif resetCount > 0 :
        fields = string.split(line, " ")
        dict[fields[0]] = fields

2番目の方法は、Arduinoでコマンド応答プロトコルを実装することです。Arduinoは、要求された場合にのみデータを送信します。この場合、pythonコードはコマンドをArduino(以下の例では「RT」)に送信し、「完了した」行が表示されるかタイムアウトになるまでArduinoからデータを読み取ります。

        dict = {}
        regex = re.compile('28-[0-9A-Fa-f]{12}') # 28-000005eaa80e

        s = serial.Serial('/dev/ttyS0', 9600, timeout=5)
        s.write("RT\n");

        while True:
            line = s.readline().rstrip("\r\n")
            print line
            if string.find(line, "completed") != -1:
                break;

            fields = string.split(line)
            if (regex.match(fields[0]) != None and len(fields) == 4) :
                dict[fields[0]] = fields
        s.close()
2
Eric Nelson

ポートを閉じても、データはまだarduinoから送信されており、オペレーティングシステムによってバッファリングされている可能性があります。 close()を呼び出すスクリプトと、デバイスドライバーが実際にシャットダウンするまでの間に短い遅延があります。

すぐに再度開くと、ドライバーはバッファーをリセットせずに続行できます。これはデバイスドライバーバッファーであり、Pythonシリアルポートインスタンスで見られるものではありません。

Close()の呼び出し後、open()の呼び出しを試みる前に、少なくとも2、3秒待つと、期待どおりの動作になります。

私は一日のほとんどを、これが私のコードが正しく機能するのを妨げていた原因であると考えて過ごしました。

0
Peter Harrison

コンストラクターを再度呼び出すのではなく、ハンドルを使用してポートを閉じてみてください。ポートが開いていて、serial.Serial( "com4"、9600)を呼び出すと、ポートを再度開いて失敗します。

Serial_portが正常に割り当てられた場合、serial_port.close()はそれを閉じる必要があります。

0
maxlazar

実際にポートを開くには、作成直後にserial_port.open()を実行する必要があると思います。

また、ポートを開いて成功すると終了するようにも見えます。多分私はここで何かが欠けています。私はpySerialを使用したことがありません、私はただドキュメントを読んでいます。

0
Perry