2
#include <Servo.h> 

Servo myservo;  // create servo object to control a servo 


int pos = 90;
String kontrolstr = "";
char kontrol;

void setup() 
{ 
  Serial.begin(9600);
  myservo.attach(9);// attaches the servo on pin 9 to the servo object 
} 

void loop()
{
  if(Serial.available())
    {
      kontrol=Serial.read(); // it reads from python voice recognition
      kontrolstr.concat(kontrol); 
    }
     if(kontrolstr== "right")
       {pos += 30;
       kontrol = '0';
       kontrolstr = "";
       }
     else if(kontrolstr== "left")
       {pos -= 30;
       kontrol= '0';
       kontrolstr = ""; 
     }

     myservo.write(pos);
     delay(100);
}

Linux 端末の voice_command.py (私が書いたもの) で動作します。コードがこのような場合、このコードを arduino にアップロードした直後に、音声認識が「右」または「左」とは別の単語を理解するまではうまく機能します。音声コマンドが「右」または「左」とは異なる別の文字列をarduinoに送信すると、プログラムはエラーなしで引き続き動作しますが、この時点以降、「右」または「左」コマンドに応答しなくなります。これを解決するために、この変更を行いました。私は「else」を入れました:

#include <Servo.h> 

Servo myservo;  // create servo object to control a servo 


int pos = 90;
String kontrolstr = "";
char kontrol;

void setup() 
{ 
  Serial.begin(9600);
  myservo.attach(9);// attaches the servo on pin 9 to the servo object 
} 

void loop()
{
  if(Serial.available())
    {
      kontrol=Serial.read();
      kontrolstr.concat(kontrol);
    }
     if(kontrolstr== "right")
       {pos += 30;
       kontrol = '0';
       kontrolstr = "";
       }
     else if(kontrolstr== "left")
       {pos -= 30;
       kontrol= '0';
       kontrolstr = ""; 
     }
     else {              // I write this to make it work..
       kontrol = '0';  
       kontrolstr = "";
     }

     myservo.write(pos);
     delay(100);
}

ただし、「右」および「左」コマンドも応答しません。どうすればこの問題を解決できますか?

4

1 に答える 1

1

問題

あなたが抱えている問題は、Serial.available()ブロックがループの各反復でシリアル バッファから 1 バイトしか読み取っていないことです。結果として、サーボがワードを送信する"right"と、シリアル バッファは「正しい」状態になります。の最初の反復は の値としてloop()与えます。"r"kontrolstr

elseブロックがなければ、 2 番目のループで、 then 、 thenなどにkontrolstr設定され、またはが見つかった場合にのみリセットされます。これは、別の単語が認識された場合に到達しないという問題の原因でもあります。たとえば、これは認識されないため、送信すると が取得されます。ririgrighleftrightleftrightkontrolstr"horse""right""horseright"

ブロックではelse、最初のループでkontrolstr"r"であるため、ブロックにヒットしelse、文字列をリセットします。2 番目のループkontrolstris"i"では、ブロックにヒットしelseて文字列をリセットするなどして、関連する制御ブロックに到達することはありません。

可能な解決策

ソリューションの開始点は、処理する前にバッファ全体を読み取ることです。そのため、次Serialのブロックで始まるブロックを次のように置き換えますif(Serial.available()

while(Serial.available())
  {
    kontrol = Serial.read();
    kontrolstr.concat(kontrol);
  }

これにより、最初のループでバッファ全体が読み取られるため、ループの反復間ですべてのデータが送信されている限り、問題は解決されます。ただし、シリアル ポート経由でデータを送信するにはゼロ以外の時間がかかるためloop()、送信の途中で反復がトリガーされる可能性があり"rig"ます"right""left"、リセットされ、次のループで が取得"ht"され、再びリセットされます-トリガーが失われます。

可能であれば、サーボに区切り文字を付けて制御ワードを送信させるのが最善の解決策だと思います\n。サーボが を送信する場合、"right\nanother word\nleft\n"処理する前に単語全体が入ってくるのを待つことができます。これを行うには、次のように変更しますloop()

void loop()
{
  kontrolstr = "";    // Reset on each iteration of the loop
  while(Serial.available())
  {
    kontrol = Serial.read();
    // If we reach the delimiter, stop reading from the Serial buffer
    if (control == '\n') {
      break;
    }
    kontrolstr.concat(kontrol);
  }
  if(kontrolstr== "right") {
    pos += 30;
  } else if(kontrolstr== "left") {
    pos -= 30; 
  }

  myservo.write(pos);
  delay(100);
}

もちろん、これは余分な単語がシリアル バッファに蓄積されることを許可していることを前提としています (100 ミリ秒ごとに 1 文字しか読み取っていない場合でもバッファがいっぱいにならなかったため、問題ないようです)。ただし、シリアル バッファがオーバーフローしている場合は、2 番目の文字列を作成bufferstringし、シリアル バッファにあるものを常にその文字列に追加してから、ループの各反復で最も古いコマンドを引き出して、次のようにします。

#include <Servo.h> 

Servo myservo;  // create servo object to control a servo 

int pos = 90;
String kontrolstr = "";
String bufferstring = "";
char kontrol;

void setup() 
{ 
  Serial.begin(9600);
  myservo.attach(9);// attaches the servo on pin 9 to the servo object 
} 

void loop()
{
  // Read whatever's in the Serial port into the buffer string
  while(Serial.available())
  {
    kontrol = Serial.read();
    // If we reach the delimiter, stop reading from the Serial buffer
    bufferstring.concat(kontrol);
  }

  // Split the string by the delimiter
  int delimiter_loc = bufferstring.indexOf('\n');
  if (delimiter_loc != -1) {
    // Get the first delimiter_loc characters (doesn't include the delimiter)
    kontrolstr = bufferstring.substring(0, delimiter_loc);

    // Remove all the characters up to and including the delimiter_loc
    bufferstring.remove(0, delimiter_loc + 1);
  }

  if(kontrolstr== "right") {
    pos += 30;
  } else if(kontrolstr== "left") {
    pos -= 30;
  }

  // Reset on each iteration of the loop
  kontrolstr = "";

  myservo.write(pos);
  delay(100);
}
于 2016-03-28T00:58:18.043 に答える