2016-03-23 14 views
1

私はシリアル経由でarduinoと通信するPythonスクリプトを持っています。それは私のコンピュータ上で期待どおりに動作しますが、私は自分のRaspberry Piでスクリプトを実行すると動作しません。 「Sent:1」を印刷した後に固まってしまいます。私はそれがarduino(sendValueからの最初の行)から1バイトを待っていると思う。しかし、私はコンピュータやPiのシリアルモニタから正常に動作するので、なぜこれが起こっているのか分かりません。Arduinoとインターフェイスしてシリアル経由でラズベリーパイに作用しないPythonコード

Pythonスクリプト:

import serial 
ser = serial.Serial('/dev/ttyACM0', 9600) 

def sendValue(value): 
    ser.read(1) # Arduino will send one byte when it's ready for the value 
    ser.write(value) # Send value 
    print("Sent: {}".format(value)) 
    return; 

ser.write('1') # Select function '1' 
print("Sent: 1") 

sendValue('5000') # Send 1st parameter to function '1' 
sendValue('4000') # Send 2nd parameter to function '1' 

while True: 
    print(ser.readline()) 

Arduinoのコードは:私はそれが立ち往生だと思うところ

int task = 0; 

int val = 0; 
int val2 = 0; 
int val3 = 0; 

void task1(int length){ 
    Serial.println(length); 
    digitalWrite(13, HIGH); 
    delay(length); 
    digitalWrite(13, LOW); 
} 

void task2(int length1, int length2){ 
    Serial.print("Running task2 with parameters "); 
    Serial.print(length1); 
    Serial.print(" and "); 
    Serial.println(length2); 
    digitalWrite(13, HIGH); 
    delay(length1); 
    digitalWrite(13, LOW); 
    delay(500); 
    digitalWrite(13, HIGH); 
    delay(length2); 
    digitalWrite(13, LOW); 
} 

void waitForSerial(){ 
    while(Serial.available() == 0); 
} 

int getValue(){ 
    Serial.write(48); 
    waitForSerial(); 
    return Serial.parseInt(); 
} 

int getCommand(){ 
    if(Serial.available() == 0){ 
     return -1; 
    } 

    String in = ""; 

    in += (char)Serial.read(); 

    return in.toInt(); 
} 

void setup() { 
    Serial.begin(9600); 
    pinMode(13, OUTPUT); 
} 

void loop() { 
    task = getCommand(); 

    switch(task){ 
     case 0: 
      val = getValue(); 
      task1(val); 
      val = 0; 
      break; 
     case 1: 
      val = getValue(); 
      val2 = getValue(); 

      task2(val, val2); 
      val = val2 = 0; 
      break; 
    } 
} 

私の代わりにser.read(1)のに遅延を入れて試してみましたが、それはまだ動作しません。

これをラズベリーパイコミュニティまたはArduinoコミュニティに配置するかどうかはわかりませんでしたので、ここで説明します。

答えて

1

あなたはArduinoの自動リセットに関連する問題が発生する可能性があります。 Arduinoがリセットされると、「再起動」してメインプログラム(loop())の実行を開始するまで数秒かかります。 Unix OS(たとえばRaspberry Pi)を使用してArduinoに接続すると、自動リセットが実行されます。 Pythonスクリプトが接続後すぐにArduinoにデータを送信した場合、Arduinoプロセッサコードではなくブートローダによってこのデータが取得される可能性があります。プロセッサは準備ができていないため、Arduinoは何も起こっていないように動作します。 Windows上でArduinoをテストすると、この動作が表示されないことがあります。一部のWindows構成では、初期接続では自動リセットが実行されず、シリアル・モニタでも同じようにリセットされます。

私の解決策は、シリアル接続がPythonスクリプトで作成された後、データが送信される前に、単に5秒の遅延を追加することです。これで問題が解決したら、Arduinoの準備が整ったらホストに知らせるためのソリューションをもっと創造的にすることができます。たとえば、Arduinoスケッチ(Serial.println('READY');)のsetup()部分の最後にホストに行を印刷できます。

pinMode(13, OUTPUT); 
digitalWrite(13, HIGH); 
delay(150); 
digitalWrite(13, LOW); 
delay(150); 
digitalWrite(13, HIGH); 
delay(150); 
digitalWrite(13, LOW); 

あなたは二重点滅を見たとき、あなたは、プロセッサが知っている:あなたはまた、トラブルシューティングのための視覚的な手がかりとして、setup()ルーチンの終了時に、オンボードLEDの点滅を行い数行のコードを置くことができますホストプログラムからの通信を受信する準備ができています。

+0

あなたは 'シリアルを追加する必要があります。println( 'READY') 'を' setup() 'にします。シリアルに接続するたびに 'setup()'が実行されますか? – Marcel

+0

'setup()'ルーチンはプロセッサが起動するたびに実行されます:1)電源投入、2)ボードのリセットボタンを押す、3)内蔵USBポート自動リセット ")。自動リセットは、USB接続を介してボードをプログラムできるようにするものです。詳細はこちら[http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection]またはgoogle "arduino autoreset"を参照してください。 – mhopeng

+0

*いくつかのケースでは、Windowsホストは自動リセットを起動しませんが、LinuxまたはOS Xは常にそうするでしょう。 – mhopeng

1

無効な文字がSerial.parseInt()と指定されているため、解析が停止するという事実を利用するとよいでしょう。

数字またはマイナス記号ではない最初の文字はスキップされます。 設定可能なタイムアウト値の文字が読み込まれていないか、または数字以外の文字が読み込まれていないときに解析が停止します。 タイムアウト(Serial.setTimeout()を参照)が発生したときに有効な数字が読み取られなかった場合は、0が返されます。

https://www.arduino.cc/en/Reference/ParseInt

次に、あなたがこのような何か行うことができます:

var1 = Serial.read(); 
var2 = Serial.read(); 
var3 = Serial.read(); 

とPythonで:

ser.write('<number1>a<number2>a<number3>a') 
関連する問題