arduino:其他程序不工作

arduino: program with else not working

#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 之后,它运行良好,直到语音识别从 "right" 或 "left" 理解不同的词。当语音命令向 arduino 发送另一个不同于 "right" 或 "left" 的字符串时,程序仍然可以正常工作,但在这之后它开始不再响应 "right" 或 "left" 命令.为了解决这个问题,我做了这个改变。我放了一个 '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);
}

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

问题

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

的值

没有 else 块,在第二个循环中,kontrolstr 设置为 ri,然后是 rig,然后是 righ,等等,并且仅在找到 leftright 时重置。这也是导致 leftright 问题的原因,如果另一个词已被识别 - 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() 迭代可能会在发送过程中触发,在这种情况下,串行缓冲区可能类似于 [=不匹配 "right""left" 的 41=] 将被重置,然后在下一个循环中您将获得 "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);
}