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

#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);
}

但是,现在它也没有响应"右"和"左"命令。如何解决这个问题?

问题

您遇到的问题是,Serial.available()块在循环的每次迭代中仅从串行缓冲区读取一个字节。因此,当您的伺服发送单词"right" 时,串行缓冲区是"正确的"。通过 loop() 的第一次迭代给出 "r" 作为kontrolstr的值。

如果没有else块,在第二个循环中,kontrolstr设置为 ri ,然后是 rig ,然后是 righ 等,并且仅在找到leftright时才重置。这也是导致left的问题,如果识别出另一个单词,则无法到达right - kontrolstr将被设置为 ,例如 "horse",这是无法识别的,所以当它发送"right"时,你会得到"horseright",等等。

对于else块,在第一个循环中,kontrolstr "r",因此它命中else块,并重置字符串。在第二个循环中,kontrolstr "i",它击中else块并重置字符串等,从未到达相关的控制块。

可能的解决方案

解决方案的开始是在处理之前读取整个Serial缓冲区,因此将if(Serial.available()开头的块替换为:

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

这将在第一个循环中读取整个缓冲区,因此只要在循环迭代之间发送了所有数据,您的问题就会得到解决。但是,通过串行端口发送数据需要非零时间,因此您的loop()迭代可能会在发送过程中触发,在这种情况下,串行缓冲区可能类似于 "rig" ,它不会匹配"right""left",将被重置,然后在下一个循环中你会得到"ht", 它将再次重置 - 触发器将被错过。

如果可能的话,我认为最好的解决方案是让您的伺服发送控制字,并在它们之间带有分隔符,例如 n .如果您的伺服发送"rightnanother wordnleftn",那么您可以在处理它们之前等待整个单词进入。为此,您可以将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);
}

最新更新