Need help, Arduino uno with the EasyVR(VRbot) voice recognition module.

Attached is a program i use for working with EasyVR and it is not working even thoe there are no errors. any help is appreciated.

LED2.pde (3.24 KB)

You probably only need ONE serial port.

The first loop in setup() is bad.

Must call serial.available() to see if there are any characters available or serial.read() will return -1.

#include <NewSoftSerial.h>		// communicate with VRBOT
int i;
char reader;
NewSoftSerial tx(30,11); //tx on 14   declaring tx and rx
NewSoftSerial rx(12,30); //rx on 12
void setup()
{							
  for(i=2; i=11; i++)			//set up all 10 Pins for outputs leave pin 0 and 1 for serial communication
    pinMode(i, OUTPUT);		//from the computer. Used for debugging.
  reset();					// sub rutin resets, put all pins to low.
  Serial.begin(9600);
  tx.begin (9600);			//9600 bits per seconds. can make it higher or lower for BAUD rate
  rx.begin(9600);
  delay(1000);				//One Second Delay.
  tx.print('b');				//sending a b wakes up the VRBOT. Recommended..
  for (i=0;i<100;i++){			//no buffer, so we have to listen to pin and catch it right away because if a bit flys into a software pin it's not going to stay 
    here
      if(rx.read()=='o'){			//the for loop will do this 100 to catch the b and it will send a o if it is a success
      Serial.println("awake");
      break;					//break the the loop.
    }
    delay(1);        // 1 ms delay
  }//for
  tx.print('x');				//Transmit the X to confirm a firmware I.D. Check
  for(i=0; i<100;i++){
    if(rx.read()=='x'){
      Serial.println('x received');		//Should get X when success.
      break;
    }
    delay(1);
  }//for
  tx.print(' ');				//send space so that it can acknowledge and you can recieve another byte.
  for (i=0; i<100; i++) {
    if(rx.read()=='A') {			//Next bit recieve is a A 
      Serial.println("firmware good");        //let us know firmware is in.
      break;
    }
    delay(1);
  } //for 
  tx.print ('l');				//setting up the language, send l to select langage
  rx.print ('A');                         // A=0 for English
  for(i=0;i<100; i++) {
    if(rx.read()=='o') {                // o for success
      Serial.println("language set");      // language set is a success
      break;
    }
    delay(1);
  } // for
  tx.print('o');          // send o for timeout
  rx.print('A');            // A = 0 infinite "always listen"
  for(i=0;i<100;i++) {
    if(rx.read()=='o') {      // o for success
      Serial.println ("Infinited Timeout");
      break;
    }
    delay(1);
  } // for
  tx.print('i');    // command recognition SI (any of the wordsets)
  tx.print('D');      // D = 3 for wordset 3
  Serial.println ( "Wordset 3");     // nothing back now it's listening

} // setup
void loop()
{
  reader=rx.read();      // constantly reading what is coming out of the rx 
  if (reader=='s') {      // recognize word
    delay (100); 
    tx.print (' ');       // space acknowledge s, then it will send out a letter anwhere from A-K, 0-10
  } // read 
  if(reader=='B'); 
  {    // send letter B 
    reset (); 
    digitalWrite (2, HIGH);    // resets sets all pins low
  }
  if (reader=='C') {
    reset ();
    digitalWrite (3, HIGH);
  }
  if (reader=='D') {
    reset ();
    digitalWrite(4, HIGH);
  }
  if (reader=='E') {
    reset (); 
    digitalWrite (5, HIGH);
  }
  if(reader=='F') {
    reset (); 
    digitalWrite(6, HIGH);
  }
  if(reader=='G') {
    reset (); 
    digitalWrite (7, HIGH);
  }
  if (reader=='H') {
    reset (); 
    digitalWrite(8, HIGH);
  }
  if(reader=='I') {
    reset ();
    digitalWrite(9, HIGH);
  }
  if (reader=='J') {
    reset ();
    digitalWrite(10, HIGH);
  }
  if(reader=='K') {
    reset ();
    digitalWrite(11, HIGH);
  }
  if(reader=='t')    // t is timeout error
    reset ();
  if(reader=='e')    // e is all other errors
    reset (); 

} // loop

void reset(){
  for(i=2; i<=11; i++)
    digitalWrite (i, LOW);
  delay (100);
  tx.print('i');     // send i and D to put vrbot back in listening mode
  tx.print('D');
}

johnwasser,

so I should just add, Serial.available() or Serial.read() before the for loop? I'm pretty new at programming, how would I add that?

I'm having a similar problem and wondering if the EasyVR module is not working properly.

The following sketch should finish with "awake" but it just hangs after "setup() complete\nWaking EasyVR..."

I have the following pin connections:
ArduinoUno P 5V -> EasyVR VCC
ArduinoUno P Gnd -> EasyVR Gnd
ArduinoUno D 2 -> EasyVR ETX
ArduinoUno D 3 -> EasyVR ERX

What am I missing? Any pointers would be greatly appreciated.

This is running on Debian Linux 5.0.6 w/Arduino 0022.

/*
 * NewSoftSerialInput sketch
 * Read data from a software serial port
 * adapted for EasyVR
 */
#include <NewSoftSerial.h>
#include <Streaming.h>
const int rxpin = 2; // pin used to receive from EasyVR
const int txpin = 3; // pin used to send to EasyVR
NewSoftSerial serial_vr(txpin, rxpin); // new serial port on pins 2 and 3

void setup()
{
  Serial.begin(9600); // 9600 baud for the built-in serial port
  serial_vr.begin(9600); // initialize the port, EasyVR at power on uses 9600 baud, 8 bit, no parity, 1 stop bit
  Serial << "setup() complete" << endl;
}

void loop()
{
  serial_vr.active(); // activate EasyVR
  serial_vr.print('b'); // wake up EasyVR
  Serial << "Waking EasyVR...";
  while (serial_vr.read() != 'o') // received awake response?
  {
    delay(1); // wait for 1 millisecond
  }
  Serial << "awake" << endl;
}

Thu 02Jun2011 update:

Additional attempts tonight were unsuccessful and lead me to believe the EasyVR is faulty. To start with, after connecting up both Arduino Uno and EasyVR and then plugging in the USB Std-B cable, any uploads consistently failed with:

avrdude: stk500_recv(): programmer is not responding

I tried disconnecting the USB Std-B cable to power down, disconnecting the EasyVR from the Arduino Uno and then powering it up with the USB Std-B cable and still got the same error.

After perusing the Arduino troubleshooting page at http://www.arduino.cc/en/Guide/Troubleshooting#upload , I managed to get the upload to work by pressing the reset button on the Arduino Uno after clicking the upload button on Arduino 0022 and after that the uploads succeeded, so it looks like I only needed to do that once, funny how that works...that wouldn't work out in the field if a person wasn't there to hit the reset button!

I also tried swapping the values for rxpin, txpin in the sketch to make sure I didn't have them switched and still no awake response from the EasyVR.

Just for the record, this is what is logged when I initially plugged in the Arduino Uno / EasyVR assembly via USB Std-B:

Jun 1 23:38:07 spectre kernel: [ 130.543595] usb 1-2: new full speed USB device using uhci_hcd and address 2
Jun 1 23:38:07 spectre kernel: [ 130.739353] usb 1-2: configuration #1 chosen from 1 choice
Jun 1 23:38:07 spectre kernel: [ 130.744052] usb 1-2: New USB device found, idVendor=2341, idProduct=0001
Jun 1 23:38:07 spectre kernel: [ 130.744059] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Jun 1 23:38:07 spectre kernel: [ 130.744064] usb 1-2: Product: Arduino Uno
Jun 1 23:38:07 spectre kernel: [ 130.744068] usb 1-2: Manufacturer: Arduino (www.arduino.cc)
Jun 1 23:38:07 spectre kernel: [ 130.744072] usb 1-2: SerialNumber: 6493534323335171F111
Jun 1 23:38:07 spectre kernel: [ 130.913503] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
Jun 1 23:38:07 spectre kernel: [ 130.914834] usbcore: registered new interface driver cdc_acm
Jun 1 23:38:07 spectre kernel: [ 130.914839] cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters

...looks to me like everything is fine there.

If anyone out there who has an Arduino Uno / EasyVR working assembly can try out the sketch I wrote to make sure that works and let me know, that would be greatly appreciated.

At this point, to isolate the EasyVR, I'm just going to verify pins D2 and D3 on the Arduino Uno work correctly via Text LCD and if they do, I'm going to have to consider returning the EasyVR via RMA.

Any other ideas would be greatly appreciated. Thanks.

bump

could your problem be because you are using pin 2 and 3 for tx and rx? from what I understand you have to short pins 2 and 3 or 2 and 4 for usage... you should tx and rx somewhere else.

...not sure what you mean by shorting the pins, but as far as I know that is unnecessary, for example I have successfully used a serial LCD on these pins without issue, so it still looks to me like the EasyVR is faulty.

sharamun:
ArduinoUno D 2 <- EasyVR ETX
ArduinoUno D 3 -> EasyVR ERX

const int rxpin = 2; // pin used to receive from EasyVR

const int txpin = 3; // pin used to send to EasyVR
NewSoftSerial serial_vr(txpin, rxpin); // new serial port on pins 2 and 3
[/quote]

I think part of the problem is that NewSoftSerial takes the RECEIVE pin first and the TRANSMIT pin second.

...looks like I got it working. I had tried swapping txpin and rxpin in the NewSoftSerial declaration and that did not work according to my earlier post, but I confirmed the correct declaration by testing w/serial LCDs, used hexadecimal to send the commands and declared the receiving loop differently in the event the sketch was taking too long to read the reply, which was likely the root cause.

Here is the sketch:

/*
 * NewSoftSerialInput sketch
 * Read data from a software serial port
 * adapted for EasyVR
 */
#include <NewSoftSerial.h>
#include <Streaming.h>
const int rxpin = 2; // pin used to receive from EasyVR
const int txpin = 3; // pin used to send to EasyVR
int loop_counter = 0;
NewSoftSerial serial_vr(rxpin, txpin); // new serial port on pins 2 and 3

void setup()
{
  Serial.begin(9600); // 9600 baud for the built-in serial port
  serial_vr.begin(9600); // initialize the port, EasyVR at power on uses 9600 baud, 8 bit, no parity, 1 stop bit
  Serial << "setup() complete" << endl;
}

void loop()
{
  if (loop_counter == 0)
  {
    serial_vr.print(0x62, BYTE); // send 'b' to wake up EasyVR
    boolean received = false;
    char c = 0;
    while (!received)
    {
      if (serial_vr.available() > 0)
      {
        c = serial_vr.read();
        received = true;
      }
    }
    Serial << "awake response: " << c << endl;
    ///
    serial_vr.print(0x78, BYTE); // send 'x' to request firmware identification
    received = false;
    c= 0;
    while (!received)
    {
      if (serial_vr.available() > 0)
      {
        c = serial_vr.read();
        received = true;
      }
    }
    Serial << "firmware identification response: " << c << endl;
    ///
    serial_vr.print(0x20, BYTE); // send ' ' to read next status argument
    received = false;
    c= 0;
    while (!received)
    {
      if (serial_vr.available() > 0)
      {
        c = serial_vr.read();
        received = true;
      }
    }
    Serial << "version identifier: " << c << endl;
  }
  Serial << "loop " << loop_counter++ << ": ";
  delay(1000); // wait one second
  Serial << endl;
}

Here is the output:
setup() complete
awake response: o
firmware identification response: x
version identifier: B
loop 0:
loop 1:
...

Note that the version identifier is returning 'B' (1), which according to the latest VeeaR EasyVR Datasheet Release 2.3 http://download.tigal.com/veear/EasyVR_User_Manual_2.3.pdf indicates correctly that this is an EasyVR device rather than a VRbot device which would return 'A' (0).

This block of code:

    received = false;
    c= 0;
    while (!received)
    {
      if (serial_vr.available() > 0)
      {
        c = serial_vr.read();
        received = true;
      }
    }

is functionally equivalent to these two statements:

    while (serial_vr.available() == 0)
        /* Do Nothing */ ;  // Waiting for a character
    c = serial_vr.read();   // Read the character

...awesome! ...leaner and faster, just the way I like it. Thanks John!

Here's the sketch which includes constants definitions, setting the language and recognition timeout as well as setting it to listen and respond to recognized words from trigger wordset 1. This should be enough to get anyone off the ground using this awesome device (comments/additions are welcome):

/*
 * NewSoftSerialInput sketch
 * Read data from a software serial port
 * adapted for EasyVR
 *
 * Revision History
 * Sergei Haramundanis bog10222@bogatir.com | Sun 12Jun2011 | initial version
 * Sergei Haramundanis bog10222@bogatir.com | Thu 16Jun2011 | include constants, set language and recognition timeout
 */
#include <NewSoftSerial.h>
#include <Streaming.h>
const int rxpin = 2; // pin used to receive from EasyVR
const int txpin = 3; // pin used to send to EasyVR
// argument constants
const byte MINUS_ONE = '@'; // 0x40
const byte ZERO = 'A'; // 0x41
const byte ONE = 'B'; // 0x42
const byte TWO = 'C'; // 0x43
const byte THREE = 'D'; // 0x44
const byte FOUR = 'E'; // 0x45
const byte FIVE = 'F'; // 0x46
const byte SIX = 'G'; // 0x47
const byte SEVEN = 'H'; // 0x48
// command constants
const byte CMD_BREAK = 'b'; // 0x62
const byte CMD_SLEEP = 's'; // 0x73
const byte CMD_KNOB = 'k'; // 0x6B
const byte CMD_LEVEL = 'v'; // 0x76
const byte CMD_LANGUAGE = 'l'; // 0x6C
const byte CMD_TIMEOUT = 'o'; // 0x6F
const byte CMD_RECOG_SI = 'i'; // 0x69
const byte CMD_TRAIN_SD = 't'; // 0x74
const byte CMD_GROUP_SD = 'g'; // 0x67
const byte CMD_UNGROUP_SD = 'u'; // 0x75
const byte CMD_RECOG_SD = 'd'; // 0x64
const byte CMD_ERASE_SD = 'e'; // 0x65
const byte CMD_NAME_SD = 'n'; // 0x6E
const byte CMD_COUNT_SD = 'c'; // 0x63
const byte CMD_DUMP_SD = 'p'; // 0x70
const byte CMD_MASK_SD = 'm'; // 0x6D
const byte CMD_RESETALL = 'r'; // 0x72
const byte CMD_RESETALL_CONFIRM = 'R'; // 0x52
const byte CMD_ID = 'x'; // 0x78
const byte CMD_DELAY = 'y'; // 0x79
const byte CMD_BAUDRATE = 'a'; // 0x61
const byte CMD_QUERY_IO = 'q'; // 0x71
const byte CMD_PLAY_SX = 'w'; // 0x6E
const byte CMD_DUMP_SX = 'h'; // 0x68
// status constants
const byte STS_MASK = 'k'; // 0x6B
const byte STS_COUNT = 'c'; // 0x63
const byte STS_AWAKEN = 'w'; // 0x77
const byte STS_DATA = 'd'; // 0x64
const byte STS_ERROR = 'e'; // 0x65
const byte STS_INVALID = 'v'; // 0x76
const byte STS_TIMEOUT = 't'; // 0x74
const byte STS_INTERR = 'i'; // 0x69
const byte STS_SUCCESS = 'o'; // 0x6F
const byte STS_RESULT = 'r'; // 0x72
const byte STS_SIMILAR = 's'; // 0x73
const byte STS_OUT_OF_MEM = 'm'; // 0x6D
const byte STS_ID = 'x'; // 0x78
const byte STS_PIN = 'p'; // 0x70
const byte STS_TABLE_SX = 'd'; // 0x64
// convenience constants
const byte CMD_ACK = ' '; // 0x20
const byte VRBOT = 'A'; // 0x41
const byte EASYVR = 'B'; // 0x42
// trigger wordset 1 constants
const byte WORDSET_1_ACTION = 'A'; // 0x41
const byte WORDSET_1_MOVE = 'B'; // 0x42
const byte WORDSET_1_TURN = 'C'; // 0x43
const byte WORDSET_1_RUN = 'D'; // 0x44
const byte WORDSET_1_LOOK = 'E'; // 0x45
const byte WORDSET_1_ATTACK = 'F'; // 0x46
const byte WORDSET_1_STOP = 'G'; // 0x47
const byte WORDSET_1_HELLO = 'H'; // 0x48
//
int loop_counter = 0;
NewSoftSerial serial_vr(rxpin, txpin); // new serial port on pins 2 and 3
char c;

void setup()
{
  Serial.begin(9600); // 9600 baud for the built-in serial port
  serial_vr.begin(9600); // initialize the port, EasyVR at power on uses 9600 baud, 8 bit, no parity, 1 stop bit
  Serial << "setup() complete" << endl;
}

void loop()
{
  if (loop_counter == 0)
  {
    //serial_vr.print(0x62, BYTE); // send 'b' to wake up EasyVR
    serial_vr.print(CMD_BREAK); // send 'b' to wake up EasyVR
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    Serial << "awake response: " << c << " ";
    if (c == STS_SUCCESS) { Serial << "(STS_SUCCESS)"; }
    Serial << endl;
    ///
    //serial_vr.print(0x78, BYTE); // send 'x' to request firmware identification
    serial_vr.print(CMD_ID); // send 'x' to request firmware identification
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    Serial << "firmware identification response: " << c << " ";
    if (c == STS_ID) { Serial << "(STS_ID)"; }
    Serial << endl;
    ///
    //serial_vr.print(0x20, BYTE); // send ' ' to acknowledge and read next reply status byte
    serial_vr.print(CMD_ACK); // send ' ' to acknowledge and read next reply status byte
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    Serial << "version identifier: " << c << " ";
    if (c == VRBOT) { Serial << "(VRBOT)"; }
    else if (c == EASYVR) { Serial << "(EASYVR)"; }
    Serial << endl;
    ///
    //serial_vr.print(0x6C, BYTE); // send 'l' to set SI language
    //serial_vr.print(0x41, BYTE); // send 'A' (0) for English
    serial_vr.print(CMD_LANGUAGE); // send 'l' to set SI language
    serial_vr.print(ZERO); // send 'A' (0) for English
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    Serial << "set SI language: " << c << " ";
    if (c == STS_SUCCESS) { Serial << "(STS_SUCCESS)"; }
    Serial << endl;
    ///
    //serial_vr.print(0x6F, BYTE); // send 'o' to set recognition timeout
    //serial_vr.print(0x46, BYTE); // send 'F' (5) for five seconds
    serial_vr.print(CMD_TIMEOUT); // send 'o' to set recognition timeout
    serial_vr.print(FIVE); // send 'F' (5) for five seconds
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    Serial << "set recognition timeout: " << c << " ";
    if (c == STS_SUCCESS) { Serial << "(STS_SUCCESS)"; }
    Serial << endl;
  }
  
  Serial << endl;
  Serial << "speak one of the following words to the EasyVR:" << endl;
  Serial << "action" << endl;
  Serial << "move" << endl;
  Serial << "turn" << endl;
  Serial << "run" << endl;
  Serial << "look" << endl;
  Serial << "attack" << endl;
  Serial << "stop" << endl;
  Serial << "hello" << endl;
  Serial << endl;
  Serial << "loop " << loop_counter++ << ": " << endl;
  ///
  serial_vr.print(CMD_RECOG_SI); // send 'i' to start recognition in wordset 1
  serial_vr.print(ONE); // send 'B' (1) for trigger wordset 1
  while (serial_vr.available() == 0) { } // wait for reply or exit if wait time greater than recognition timeout
  c = serial_vr.read(); // read reply byte
  // 'hello' is command index 7 in trigger wordset 1
  if (c == STS_SIMILAR)
  {
    Serial << "successful recognition (STS_SIMILAR)" << endl;
    serial_vr.print(CMD_ACK); // send ' ' to acknowledge and read next reply status byte
    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte
    if (c == STS_TIMEOUT) { Serial << "(STS_TIMEOUT)" << endl; }
    else if (c == STS_ERROR)
         {
           Serial << "(STS_ERROR) ";
           serial_vr.print(CMD_ACK); // send ' ' to acknowledge and read next reply status byte
           while (serial_vr.available() == 0) { } // wait for reply
           c = serial_vr.read(); // read reply byte
           Serial << c;
           serial_vr.print(CMD_ACK); // send ' ' to acknowledge and read next reply status byte
           while (serial_vr.available() == 0) { } // wait for reply
           c = serial_vr.read(); // read reply byte
           Serial << c << endl;
         }
    else
    {
      if (c == WORDSET_1_ACTION) { Serial << c << " (WORDSET_1_ACTION)" << endl; }
      if (c == WORDSET_1_MOVE) { Serial << c << " (WORDSET_1_MOVE)" << endl; }
      if (c == WORDSET_1_TURN) { Serial << c << " (WORDSET_1_TURN)" << endl; }
      if (c == WORDSET_1_RUN) { Serial << c << " (WORDSET_1_RUN)" << endl; }
      if (c == WORDSET_1_LOOK) { Serial << c << " (WORDSET_1_LOOK)" << endl; }
      if (c == WORDSET_1_ATTACK) { Serial << c << " (WORDSET_1_ATTACK)" << endl; }
      if (c == WORDSET_1_STOP) { Serial << c << " (WORDSET_1_STOP)" << endl; }
      if (c == WORDSET_1_HELLO) { Serial << c << " (WORDSET_1_HELLO)" << endl; }
    }
  }
  ///
  delay(1000); // wait one second
  Serial << endl;
}

Time to learn the 'switch' stetement:

  while (serial_vr.available() == 0) { } // wait for reply or exit if wait time greater than recognition timeout
  if (serial_vr.read() ==  STS_SIMILAR)
    {
    Serial << "successful recognition (STS_SIMILAR)" << endl;
    serial_vr.print(CMD_ACK); // send ' ' to acknowledge and read next reply status byte

    while (serial_vr.available() == 0) { } // wait for reply
    c = serial_vr.read(); // read reply byte

    switch (c)
      {
    case STS_TIMEOUT: Serial << "(STS_TIMEOUT)" << endl;  break;
    case STS_ERROR:
        Serial << "(STS_ERROR) ";
        serial_vr.print(CMD_ACK); 
        while (serial_vr.available() == 0) { } // wait for reply
        c = serial_vr.read(); // read reply byte
        Serial << c;
        serial_vr.print(CMD_ACK);
        while (serial_vr.available() == 0) { } // wait for reply
        c = serial_vr.read(); // read reply byte
        Serial << c << endl;
        break;

      case WORDSET_1_ACTION:  Serial << c << " (WORDSET_1_ACTION)" << endl;  break;
      case WORDSET_1_MOVE:    Serial << c << " (WORDSET_1_MOVE)" << endl;   break;
      case WORDSET_1_TURN:    Serial << c << " (WORDSET_1_TURN)" << endl;   break;
      case WORDSET_1_RUN:      Serial << c << " (WORDSET_1_RUN)" << endl;   break;
      case WORDSET_1_LOOK:     Serial << c << " (WORDSET_1_LOOK)" << endl;  break;
      case WORDSET_1_ATTACK:  Serial << c << " (WORDSET_1_ATTACK)" << endl;  break;
      case WORDSET_1_STOP:      Serial << c << " (WORDSET_1_STOP)" << endl;  break;
      case WORDSET_1_HELLO:    Serial << c << " (WORDSET_1_HELLO)" << endl;   break;

     default:
         Serial << c << " Unrecognized response" << endl;   break;
    }
  }

Re: use of switch statement

I've always avoided any conditionals that rely on breaks, because like gotos they disconnect continuity of logic flow. Thanks for the suggestion though.