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
,等等,并且仅在找到 left
或 right
时重置。这也是导致 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()
迭代可能会在发送过程中触发,在这种情况下,串行缓冲区可能类似于 [=不匹配 "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);
}
#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
,等等,并且仅在找到 left
或 right
时重置。这也是导致 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()
迭代可能会在发送过程中触发,在这种情况下,串行缓冲区可能类似于 [=不匹配 "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);
}