#include <Servo.h>
Servo myservo; // create servo object to control a servoint 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);
}
Он работает с voice_command.py (который я написал) на терминале Linux. Когда код подобен этому, сразу после загрузки этого кода в arduino он работает хорошо, пока распознавание голоса не поймет другое слово из «правого» или «левого». Когда голосовая команда отправляет в arduino другую строку, отличную от «правая» или «левая», программа по-прежнему работает без каких-либо ошибок, но после этой точки она больше не отвечает на «правую» или «левую» команду. Чтобы решить это, я сделал это изменение. Я положил «еще»:
#include <Servo.h>
Servo myservo; // create servo object to control a servoint 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
и т.д., и сбрасывается только тогда, когда 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()
Итерация запускается в середине отправки, и в этом случае последовательный буфер может быть что-то вроде "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);
}
Конечно, это предполагает, что вы в порядке, позволяя накапливать дополнительные слова в последовательном буфере (кажется, все в порядке, поскольку буфер не заполнялся, даже когда вы читали только 1 символ каждые 100 мс). Однако если случится так, что последовательный буфер переполнен, то вы можете создать вторую строку bufferstring
и всегда добавляйте к этой строке все, что находится в буфере Serial, затем на каждой итерации цикла извлекайте самую старую команду, давая:
#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);
}
Других решений пока нет …