web-dev-qa-db-ja.com

python to arduino serial read&write

私はいくつかのpythonコードとarduinoコードの間で情報をやり取りするために「ピンポン」情報を試みています。定期的に(たとえば、分)に2つのセットポイントをarduinoコードに送信したいそれらをarduinoおよび更新変数で送信し、次にarduinoからpythonに定期的に(30秒など)にステータス情報を送信します。最終的にpython mySQL db(後の開発者)から情報を引き出します。

今のところ、確実に行き来する情報を得ることができません。検索でこれに近いものが見つからず、変更しようとしたすべてが機能していません。私が持っている最も近いものはこれです(そして実際に送信と受信を切り替えません):

Python

#!/usr/bin/python
import serial
import syslog
import time

#The following line is for serial over GPIO
port = '/dev/ttyS0'


ard = serial.Serial(port,9600,timeout=5)

i = 0

while (i < 4):
    # Serial write section

    setTempCar1 = 63
    setTempCar2 = 37
    ard.flush()
    setTemp1 = str(setTempCar1)
    setTemp2 = str(setTempCar2)
    print ("Python value sent: ")
    print (setTemp1)
    ard.write(setTemp1)
    time.sleep(4)

    # Serial read section
    msg = ard.readline()
    print ("Message from arduino: ")
    print (msg)
    i = i + 1
else:
    print "Exiting"
exit()

Arduino:

// Serial test script

int setPoint = 55;
String readString;

void setup()
{

  Serial.begin(9600);  // initialize serial communications at 9600 bps

}

void loop()
{
  while(!Serial.available()) {}
  // serial read section
  while (Serial.available())
  {
    if (Serial.available() >0)
    {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    }
  }

  if (readString.length() >0)
  {
    Serial.print("Arduino received: ");  
    Serial.println(readString); //see what was received
  }

  delay(500);

  // serial write section

  char ard_sends = '1';
  Serial.print("Arduino sends: ");
  Serial.println(ard_sends);
  Serial.print("\n");
  Serial.flush();
}

私が取得するのは、同じ値が繰り返されることです(実際に送信されたものではなく、文字列またはバイトの問題であるかどうかは不明です)pythonスクリプト。ありがとう。

編集:以下に示すように、現在実行しているものにコードを変更しました。 Arduinoは、minicomによって検証された正常なシリアル通信を受信して​​います。ただし、pythonスクリプトは、「arduinoからのメッセージ:」の後に空白行を出力します。

14
Boombrewer

Python書き込みと読み取りの間でシリアルポートを閉じるべきではありません。Arduinoが応答するときにポートがまだ閉じている可能性があります。その場合、データは失われます。

while running:  
    # Serial write section
    setTempCar1 = 63
    setTempCar2 = 37
    setTemp1 = str(setTempCar1)
    setTemp2 = str(setTempCar2)
    print ("Python value sent: ")
    print (setTemp1)
    ard.write(setTemp1)
    time.sleep(6) # with the port open, the response will be buffered 
                  # so wait a bit longer for response here

    # Serial read section
    msg = ard.read(ard.inWaiting()) # read everything in the input buffer
    print ("Message from arduino: ")
    print (msg)

Python Serial.read関数はデフォルトで1バイトのみを返すため、ループで呼び出すか、データが送信されるのを待ってからバッファ全体を読み取る必要があります。

Arduino側では、使用可能なデータがないときにloop関数で何が起こるかを考慮する必要があります。

void loop()
{
  // serial read section
  while (Serial.available()) // this will be skipped if no data present, leading to
                             // the code sitting in the delay function below
  {
    delay(30);  //delay to allow buffer to fill 
    if (Serial.available() >0)
    {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    }
  }

代わりに、データが到着するまでloop関数の先頭で待機します。

void loop()
{
  while (!Serial.available()) {} // wait for data to arrive
  // serial read section
  while (Serial.available())
  {
    // continue as before

編集2

PythonのArduinoアプリとインターフェイスするときに得られるものを次に示します。

>>> import serial
>>> s = serial.Serial('/dev/tty.usbmodem1411', 9600, timeout=5)
>>> s.write('2')
1
>>> s.readline()
'Arduino received: 2\r\n'

だからそれはうまく機能しているようです。

Pythonスクリプトのテストでは、シリアルポートを開くとArduinoがリセットされる(少なくとも私のUnoはリセットする)ので、問題が発生するまで数秒待つ必要があるようです。また、応答の1行のみを読み取るため、以下のコードでも修正しました。

#!/usr/bin/python
import serial
import syslog
import time

#The following line is for serial over GPIO
port = '/dev/tty.usbmodem1411' # note I'm using Mac OS-X


ard = serial.Serial(port,9600,timeout=5)
time.sleep(2) # wait for Arduino

i = 0

while (i < 4):
    # Serial write section

    setTempCar1 = 63
    setTempCar2 = 37
    ard.flush()
    setTemp1 = str(setTempCar1)
    setTemp2 = str(setTempCar2)
    print ("Python value sent: ")
    print (setTemp1)
    ard.write(setTemp1)
    time.sleep(1) # I shortened this to match the new value in your Arduino code

    # Serial read section
    msg = ard.read(ard.inWaiting()) # read all characters in buffer
    print ("Message from arduino: ")
    print (msg)
    i = i + 1
else:
    print "Exiting"
exit()

次に、上記の出力を示します。

$ python ardser.py
Python value sent:
63
Message from arduino:
Arduino received: 63
Arduino sends: 1


Python value sent:
63
Message from arduino:
Arduino received: 63
Arduino sends: 1


Python value sent:
63
Message from arduino:
Arduino received: 63
Arduino sends: 1


Python value sent:
63
Message from arduino:
Arduino received: 63
Arduino sends: 1


Exiting
8
Peter Gibson

まず、モジュール呼び出しシリアルをインストールする必要があります。これを行うには、pythonインストール済みフォルダーにあるScriptsを呼び出します。Python 3バージョンを使用している場合、通常は以下の場所にあります。

C:\Python34\Scripts  

そのフォルダーを開いたら、Shiftキーを使用してそのフォルダーを右クリックします。次に、[ここでコマンドウィンドウを開く]をクリックします。その後、cmdがポップアップ表示されます。そのcmdウィンドウに次のコードを記述し、

pip install PySerial

enterキーを押します。その後 PySerial モジュールがインストールされます。モジュールをインストールすることを忘れないでください。インターネット接続が必要です。


モジュールを正常にインストールした後、python IDLEを開き、以下のコードを書き留めて実行します。

import serial
# "COM11" is the port that your Arduino board is connected.set it to port that your are using        
ser = serial.Serial("COM11", 9600)
while True:
    cc=str(ser.readline())
    print(cc[2:][:-5])   
1