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 发送另一个不同于“right”或“left”的字符串时,程序仍然可以正常工作,但在此之后它开始不再响应“right”或“left”命令。为了解决这个问题,我做了这个改变。我放了一个“其他”:

#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()块在循环的每次迭代中仅从串行缓冲区读取一个字节。结果,当您的伺服发送单词"right"时,串行缓冲区是“正确的”。第一次迭代loop()将给出"r"作为 的值kontrolstr

没有该else块,在第二个循环中,kontrolstr设置为ri, then rig, thenrigh等,并且仅在找到left或时重置right。如果另一个单词被识别,这也是导致问题的原因,left并且right无法到达 -kontrolstr将被设置为,例如"horse", this 不被识别,所以当它发送时"right",你得到"horseright",等等。

使用else块,在第一个循环中,kontrolstris "r",所以它击中else块,并重置字符串。在第二个循环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 个字符,缓冲区也没有填满)。但是,如果确实发生串行缓冲区溢出,那么您可以创建第二个字符串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 回答