Help needed with voice command

Hello dear Arduino community,

I am working on a voice command project for my future R2D2 droid and need help with one part of my sketch.
So I am using an app that is called AMR Voice on my S4 that is sync by Bluetooth to a HC05 module, connected to the Uno board.
Then from there my Uno will do various actions, like playing MP3 on a DFPlayer or sending signal to various drive motors.

Everything is working OK, except that some times, the words output string coming out of the Voice app is not always consistent and is not recognised by my sketch.

For example, sometime it will output '' R2D2 play Leah message '' and another time it will output ''R2-D2 play Leah message"or even '' r2d2 play Leah message ''

So my question, is there a way to add more then 1 key phrase to the sketch to do the same actions like this?

else if(voice == "*R2D2 play Leah message")
else if(voice == "*R2-D2 play Leah message")
else if(voice == "*r2d2 play Leah message")

{
digitalWrite(10, HIGH); // triggering play function on the projector
delay(200);
digitalWrite(10, LOW);
Serial.println("PLAYING LEA MESSAGE");
delay(5000); // DELAY INSERTED HERE TO SYNC THE VIDEO FROM THE PROJECTOR STARTUP AND THE FILE ON DFPLAYER
Serial.write(File6,sizeof(File6));

Here is my full sketch and thank you in advance for you advice's,

Sergio

//VOICE COMMAND CONTROL SKETCH WITH ANDROID AMR VOICE COMMAND
//HC05 controling DFPlayer and various motors actions
//HC05 on pin 2 RX and 3 TX of UNO
//DFPlayer RX on pin 1 TX of UNO

#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX, TX

byte File1[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x01,0xEF};
byte File2[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x02,0xEF};
byte File3[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x03,0xEF};
byte File4[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x04,0xEF};
byte File5[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x05,0xEF};
byte File6[] = {0x7E,0xFF,0x06,0x0F,0x00,0x01,0x06,0xEF};
byte Vol20[] = {0x7E,0xFF,0x06,0x06,0x00,0x00,0x20,0xEF};

String voice;

void setup()

// setting pin 5 to 10 as output and PMW output for various controls and motors actions from voice command prompt

{
pinMode(5, OUTPUT); //left motor drive trigger
pinMode(6, OUTPUT); //right motor drive trigger
pinMode(7, OUTPUT); //left motor direction
pinMode(8, OUTPUT); //right motor direction
pinMode(9, OUTPUT); //dome motor drive trigger
pinMode(10, OUTPUT); //projector play trigger

Serial.begin(9600);
BTserial.begin(9600);
}

void loop()
{
while (BTserial.available()) //Check if there is an available byte to read
{ delay(10); //Delay added to make thing stable
char c = BTserial.read(); //Conduct a serial read
if (c == '#')
{
break; //Exit the loop when the # is detected after the word
}
voice += c;
}
if (voice.length() > 0)
{
if(voice == "*R2D2 play file number one")

{
Serial.write(File1,sizeof(File1));
delay(50);
Serial.println("FILE NUMBER 1");
}

else if(voice == "*R2D2 play file number two")

{
Serial.write(File2,sizeof(File2));
delay(50);
Serial.println("FILE NUMBER 2");
}

else if(voice == "*R2D2 play file number 3")

{
Serial.write(File3,sizeof(File3));
delay(50);
Serial.println("FILE NUMBER 3");
}

else if(voice == "*R2D2 play file number four")

{
Serial.write(File4,sizeof(File4));
delay(50);
Serial.println("FILE NUMBER 4");
}

else if(voice == "*R2D2 play file number five")

{
Serial.write(File5,sizeof(File5));
delay(50);
Serial.println("FILE NUMBER 5");
}

else if(voice == "*R2D2 play Leah message")

{
digitalWrite(10, HIGH); // triggering play function on the projector
delay(200);
digitalWrite(10, LOW);
Serial.println("PLAYING LEA MESSAGE");
delay(5000); // ***DELAY INSERTED HERE TO SYNC THE VIDEO FROM THE PROJECTOR STARTUP AND THE FILE ON DFPLAYER***
Serial.write(File6,sizeof(File6));
delay(40000); // just so we can enjoy the show and not being disturbed :)

}

else if(voice == "*set volume 20")

{
Serial.write(Vol20,sizeof(Vol20));
delay(50);
Serial.println("Volume set at 20");
}

else if(voice == "*R2D2 move forward")

{
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(50);
Serial.println("MOVE FORWARD");
delay(3000);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
Serial.println("STOP MOVING FORWARD");
}

else if(voice == "*R2D2 move backward")

{
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
delay(50);
Serial.println("MOVE BACKWARD");
delay(3000);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);

Serial.println("STOP MOVING BACKWARD");
}

else if(voice == "*R2D2 spin on yourself")

{
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
delay(50);
Serial.println("SPINNING AROUND");
delay(3000);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
Serial.println("STOP SPINNING AROUND");
}

else if(voice == "*R2D2 turn your head around")

{
digitalWrite(9, HIGH);
delay(50);
Serial.println("SPINNING DOME");
delay(5000);
digitalWrite(9, LOW);
Serial.println("STOP SPINNING DOME");
}

voice=""; //Reset variable
}
}

Actually the app cannot always detect speech accurately. It highly depends on our accents. For example, I said 'left' but the app detected 'let' and my robot stood still rather than moving to left. This is the app's drawback. Not your code's.

Hello,

probably me "French accent" doesn't help. So that is why I was wondering how to come around that, like finding a way to add multiple ''else if'' together before that specific action to be done or to recreate an entire separate paragraph with the other ''else if'' and the entire action code for that same action.

Thanks

You can link multiple conditions like

(voice == "*R2D2 play Leah message")

with the OR-operator which is a double vertical line "||"

if(   (voice == "*R2D2 play Leah message") || (voice == "*R2-D2 play Leah message") ||(voice == "*r2d2 play Leah message") {

{

or you can set a command-flag

boolean playLeaFlag;

playLeaFlag = false;

if(voice == "*R2D2 play Leah message") {
  playLeaFlag = true;
}
  
if(voice == "*R2-D2 play Leah message") {
  playLeaFlag = true;
}

if(voice == "*r2d2 play Leah message")  {
  playLeaFlag = true;
}

whenever one of the three conditions is true the flag is set true

if (playLeaFlag == true) {
  // take action to play Lea-message
}

best regards Stefan

It looks like you can't trust the system's punctuation or capitalization. I would pre-process the 'voice' string to remove all punctuation and capitalization (anything that isn't a digit or letter). Then you can cover every variation with:
if(voice == "r2d2playleahmessage")

Thank you so much, I did that modification in my sketch and it works like a charm now.

Sergio

Yeah. I also did the same in one of my projects. Not a very good solution but still it works.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.