Emic 2 Text-to-Speech / Arduino
I am having trouble "Stoping" playback and unfortunately for me there seems to be very little documentation via a google search.
I downloaded a basic Arduino sketch which worked perfectly.
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/30016-Emic2-Arduino.zip
The text is sent to the serial port like this:
emicSerial.print('S');
emicSerial.print("This is button number two!");
emicSerial.print('\n');
According to the PDF specifications 'X' is supposed to "Stop playback (while message is playing)".
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/30016-Emic2TextToSpeech-v1.0.pdf
The PDF also states "Each command must be terminated with a CR or LF."
QUESTIONS:
1. I don't know the Arduino equivalent of "CR" or "LF"
I tried:
emicSerial.print('X');
emicSerial.print('\n');
but this didn't work.
I also tried:
emicSerial.print('\r');
emicSerial.print('\cr');
emicSerial.print('\l');
Any help would be greatly appreciated.
I downloaded a basic Arduino sketch which worked perfectly.
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/30016-Emic2-Arduino.zip
The text is sent to the serial port like this:
emicSerial.print('S');
emicSerial.print("This is button number two!");
emicSerial.print('\n');
According to the PDF specifications 'X' is supposed to "Stop playback (while message is playing)".
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/30016-Emic2TextToSpeech-v1.0.pdf
The PDF also states "Each command must be terminated with a CR or LF."
QUESTIONS:
1. I don't know the Arduino equivalent of "CR" or "LF"
I tried:
emicSerial.print('X');
emicSerial.print('\n');
but this didn't work.
I also tried:
emicSerial.print('\r');
emicSerial.print('\cr');
emicSerial.print('\l');
Any help would be greatly appreciated.
Comments
I am making the program on a Mac (No I am not a Mac addict).
#include <SoftwareSerial.h> #define rxPin 5 // Serial input (connects to Emic 2 SOUT) #define txPin 6 // Serial output (connects to Emic 2 SIN) #define ledPin 13 // Most Arduino boards have an on-board LED on this pin SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); // set up a new serial port const int buttonPin2 = 2; // the number of the pushbutton pin const int buttonPin3 = 3; // the number of the pushbutton pin const int buttonPin4 = 4; // the number of the pushbutton pin // variables will change: int buttonState2 = 0; // variable for reading the pushbutton status int buttonState3 = 0; int buttonState4 = 0; void setup() { // define pin modes pinMode(ledPin, OUTPUT); pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); // initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initialize the pushbutton pin as an input: pinMode(buttonPin2, INPUT_PULLUP); pinMode(buttonPin3, INPUT_PULLUP); pinMode(buttonPin4, INPUT_PULLUP); // set the data rate for the SoftwareSerial port emicSerial.begin(9600); Serial.begin(9600); emicSerial.print('\n'); // Send a CR in case the system is already up while (emicSerial.read() != ':'); // When the Emic 2 has initialized and is ready, it will send a single ':' character, so wait here until we receive it delay(10); // Short delay emicSerial.flush(); // Flush the receive buffer } void loop(){ buttonState2 = digitalRead(buttonPin2); buttonState3 = digitalRead(buttonPin3); buttonState4 = digitalRead(buttonPin4); if (buttonState2 == LOW) { Serial.println("buttone number one"); emicSerial.print('S'); emicSerial.print("This is button number one!"); emicSerial.print('\n'); digitalWrite(ledPin, HIGH); // Turn on LED while Emic is outputting audio while (emicSerial.read() != ':'); // Wait here until the Emic 2 responds with a ":" indicating it's ready to accept the next command digitalWrite(ledPin, LOW); } if (buttonState3 == LOW) { Serial.println("Stop button pressed"); emicSerial.print('X\n'); } if (buttonState4 == LOW) { Serial.println("button 4 pressed"); digitalWrite(ledPin, HIGH); emicSerial.print('S'); emicSerial.print("This is button number three. More text will go here."); // Send the desired string to convert to speech emicSerial.print('\n'); digitalWrite(ledPin, HIGH); // Turn on LED while Emic is outputting audio while (emicSerial.read() != ':'); // Wait here until the Emic 2 responds with a ":" indicating it's ready to accept the next command digitalWrite(ledPin, LOW); } }
The desired affect is that when when I pressed my button attached to pin#3 that the text-to-speech will stop.
Based on the PDF specification sheet (linked above), it states that by sending 'X' + 'CR' or 'LR' The Emic will... "Stop playback (while message is playing)".
I put a tracer inside the button attached to pin#3 to see when it was pressed but the button isn't even isn't recognized until after text-to-speech has finished.
It seemed to me that I could interrupt the software serial by sending 'X' but it doesn't seem to work that way. I can't figure out how to stop playback while Emic is speaking.
It's 8:20 Here in Sweden. Time to get dome diner and get some sleep!
Thanks very much for your input. Greatly appreciated!
while (emicSerial.read() != ':'){ if(buttonState2 == LOW || buttonState3 == LOW || buttonState4 == LOW){ emicSerial.print('X\r'); Serial.print("stoped!"); break; } }
just to reiterate. I have three buttons with three different spoken text strings. My intention is to be able to interrupt any button speaking if another button is pressed. Here is all of the code:
#include <SoftwareSerial.h> #define rxPin 5 // Serial input (connects to Emic 2 SOUT) #define txPin 6 // Serial output (connects to Emic 2 SIN) #define ledPin 13 // Most Arduino boards have an on-board LED on this pin SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); // set up a new serial port const int buttonPin2 = 2; // the number of the pushbutton pin const int buttonPin3 = 3; const int buttonPin4 = 4; // variables will change: int buttonState2 = 0; // variable for reading the pushbutton status int buttonState3 = 0; int buttonState4 = 0; void setup() { // define pin modes pinMode(ledPin, OUTPUT); pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); // initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initialize the pushbutton pin as an input: pinMode(buttonPin2, INPUT_PULLUP); pinMode(buttonPin3, INPUT_PULLUP); pinMode(buttonPin4, INPUT_PULLUP); // set the data rate for the SoftwareSerial port emicSerial.begin(9600); Serial.begin(9600); emicSerial.print('\n'); // Send a CR in case the system is already up while (emicSerial.read() != ':'); // When the Emic 2 has initialized and is ready, it will send a single ':' character, so wait here until we receive it delay(10); // Short delay emicSerial.flush(); // Flush the receive buffer } void loop(){ buttonState2 = digitalRead(buttonPin2); buttonState3 = digitalRead(buttonPin3); buttonState4 = digitalRead(buttonPin4); if (buttonState2 == LOW) { Serial.println("buttone number one"); emicSerial.print('S'); emicSerial.print("This is button number one!"); emicSerial.print('\n'); digitalWrite(ledPin, HIGH); checking(); digitalWrite(ledPin, LOW); } if (buttonState3 == LOW) { Serial.println("buttone number two"); emicSerial.print('S'); emicSerial.print("This is button number two!"); emicSerial.print('\n'); digitalWrite(ledPin, HIGH); checking(); digitalWrite(ledPin, LOW); } if (buttonState4 == LOW) { Serial.println("button 4 pressed"); digitalWrite(ledPin, HIGH); emicSerial.print('S'); emicSerial.print("This is button number three. More text will go here."); emicSerial.print('\n'); digitalWrite(ledPin, HIGH); checking(); digitalWrite(ledPin, LOW); } } void checking() { while (emicSerial.read() != ':'){ if(buttonState2 == LOW || buttonState3 == LOW || buttonState4 == LOW){ emicSerial.print('X\r'); Serial.print("stoped!"); break; } } }
I tried to start the speech and I to interrupt it after a short delay before it was finished.
In the PDF documentation is says "X" + "CR" or "LF" will Stop playback while message is playing.
But I think the specification sheet is wrong?
I don't think it is possible to actually interrupt it while it is speaking.
Does anyone one know if it is possible to interrupt Emic While it is speaking?
void loop(){ emicSerial.print('S'); emicSerial.print("This is text-to-speech please feel free to interrupt me before I finish this long speech"); emicSerial.print('\n'); //delay(100); emicSerial.print('X\r'); emicSerial.print('\n'); emicSerial.flush(); }
Yes, it is possible to stop or pause the Emic 2 while speaking. This is demonstrated in my Emic 2-to-Elmo code in the Example section on my site:
http://www.grandideastudio.com/portfolio/emic-2-text-to-speech-module/
The code is written for the PIC12F675, but you should be able to get a general understanding of how it works. Here's a snippet:
case PLAYING: // While the Emic 2 is speaking... while (!emic2_check()) { if (!input(SW_SHUFFLE)) { delay_ms(DB_TIME); // Poor man's debounce while (!input(SW_SHUFFLE)); // Wait for button to be released printf("Z\n"); // Send Pause command } else if (!input(SW_STOP)) { delay_ms(DB_TIME); // Poor man's debounce while (!input(SW_STOP)); // Wait for button to be released printf("X\n"); // Send Stop command } } break;
The "stop" and "pause" features are also demonstrated at the 3:50 mark of the following video:
http://www.youtube.com/watch?v=Ot1MgBch0MA
You shouldn't need a CR after the X (stop) and Z (pause) commands as you can see from the video. But, I use them in my Emic 2-to-Elmo code and it functions fine.
I don't have much Arduino experience (besides writing the example code for the Emic 2). To test your system, here's a modified version of your code. Note that Emic 2 requires a hard stop (such as a '.') after the text. Also, you had print('X\r') which should use double quotes instead of single.
void loop(){ emicSerial.print('S'); emicSerial.print("This is text-to-speech please feel free to interrupt me before I finish this long speech."); emicSerial.print('\n'); delay(500); // let Emic 2 start speaking emicSerial.print("X\n"); // Emic 2 should stop // end program here }
Have fun!
Joe
I tried the code but I can't seem to figure out how to "stop" the play.
Maybe this is an Arduino problem. I am a student. I don't have a lot of experience with serial communication so I will try and get some help form the faculty on Monday.
Thanks again for your input.
Joe we tried your code but it didn't work.
Despite sending the "stop" via the emicSerial it is impossible to interrupt it.
One of the guys here tried a more sophisticated test. He built a sketch starting the audio durring the set-up.
A button is coded to "stop" the playback but the button is never registered until after emic finishes speaking.
Just so you know, we were using an Arduino Uno board. The Arduino sketch was compiled on Linux, Mac and Windows. None of them worked.
Of course we may have overlooked something at this point it doesn't seem like there is a practical solution.
[LIST=1] [*][COLOR=#000000][COLOR=#339933]#include <SoftwareSerial.h>[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000][COLOR=#339933]#define rxPin 5 // Serial input (connects to Emic 2 SOUT)[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#339933]#define txPin 6 // Serial output (connects to Emic 2 SIN)[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#339933]#define ledPin 13 // Most Arduino boards have an on-board LED on this pin[/COLOR][/COLOR] [*][COLOR=#000000]SoftwareSerial emicSerial [COLOR=#339933]=[/COLOR] SoftwareSerial[COLOR=#009900]([/COLOR]rxPin[COLOR=#339933],[/COLOR] txPin[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// set up a new serial port[/I][/COLOR][/COLOR] [*][COLOR=#000000]boolean isSpeaking [COLOR=#339933]=[/COLOR] [B]false[/B][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000]String para1 [COLOR=#339933]=[/COLOR] [COLOR=#FF0000]"The boundless blue on every side expanding."[/COLOR][COLOR=#339933]; [/COLOR] [/COLOR] [*][COLOR=#000000][COLOR=#993333]const[/COLOR] [COLOR=#993333]int[/COLOR] buttonPin2 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]2[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// the number of the pushbutton pin[/I][/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#993333]const[/COLOR] [COLOR=#993333]int[/COLOR] buttonPin3 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]3[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// the number of the pushbutton pin[/I][/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#993333]const[/COLOR] [COLOR=#993333]int[/COLOR] buttonPin4 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]4[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// the number of the pushbutton pin[/I][/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000][COLOR=#666666][I]// variables will change:[/I][/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#993333]int[/COLOR] buttonState2 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]0[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// variable for reading the pushbutton status[/I][/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#993333]int[/COLOR] buttonState3 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]0[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#993333]int[/COLOR] buttonState4 [COLOR=#339933]=[/COLOR] [COLOR=#0000DD]0[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000][COLOR=#993333]void[/COLOR] setup[COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR][/COLOR] [*][COLOR=#000000] [COLOR=#666666][I]// define pin modes[/I][/COLOR][/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]ledPin[COLOR=#339933],[/COLOR] OUTPUT[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]rxPin[COLOR=#339933],[/COLOR] INPUT[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]txPin[COLOR=#339933],[/COLOR] OUTPUT[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] [COLOR=#666666][I]// initialize the LED pin as an output:[/I][/COLOR][/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]ledPin[COLOR=#339933],[/COLOR] OUTPUT[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [/COLOR] [*][COLOR=#000000] [COLOR=#666666][I]// initialize the pushbutton pin as an input:[/I][/COLOR][/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]buttonPin2[COLOR=#339933],[/COLOR] INPUT_PULLUP[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]buttonPin3[COLOR=#339933],[/COLOR] INPUT_PULLUP[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [/COLOR] [*][COLOR=#000000] pinMode[COLOR=#009900]([/COLOR]buttonPin4[COLOR=#339933],[/COLOR] INPUT_PULLUP[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000] [COLOR=#666666][I]// set the data rate for the SoftwareSerial port[/I][/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]begin[/COLOR][COLOR=#009900]([/COLOR][COLOR=#0000DD]9600[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] Serial.[COLOR=#202020]begin[/COLOR][COLOR=#009900]([/COLOR][COLOR=#0000DD]9600[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]'[COLOR=#000099][B]\n[/B][/COLOR]'[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// Send a CR in case the system is already up[/I][/COLOR][/COLOR] [*][COLOR=#000000] [COLOR=#B1B100]while[/COLOR] [COLOR=#009900]([/COLOR]emicSerial.[COLOR=#202020]read[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR] [COLOR=#339933]!=[/COLOR] [COLOR=#FF0000]':'[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// When the Emic 2 has initialized and is ready, it will send a single ':' character, so wait here until we receive it[/I][/COLOR][/COLOR] [*][COLOR=#000000] delay[COLOR=#009900]([/COLOR][COLOR=#0000DD]10[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// Short delay[/I][/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]flush[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]// Flush the receive buffer[/I][/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]println[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"W300"[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"S"[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR]para1[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"[COLOR=#000099][B]\n[/B][/COLOR]"[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#009900]}[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000][COLOR=#993333]void[/COLOR] loop[COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900]{[/COLOR][/COLOR] [*][COLOR=#000000] buttonState2 [COLOR=#339933]=[/COLOR] digitalRead[COLOR=#009900]([/COLOR]buttonPin2[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] buttonState3 [COLOR=#339933]=[/COLOR] digitalRead[COLOR=#009900]([/COLOR]buttonPin3[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] [/COLOR] [*][COLOR=#000000] [COLOR=#B1B100]if[/COLOR][COLOR=#009900]([/COLOR]buttonState3 [COLOR=#339933]==[/COLOR] LOW[COLOR=#009900])[/COLOR][COLOR=#009900]{[/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"X"[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] emicSerial.[COLOR=#202020]print[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"[COLOR=#000099][B]\n[/B][/COLOR]"[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000] Serial.[COLOR=#202020]println[/COLOR][COLOR=#009900]([/COLOR][COLOR=#FF0000]"stopping..."[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#666666][I]// sayThis(para1);[/I][/COLOR][/COLOR] [*][COLOR=#000000] [COLOR=#009900]}[/COLOR][/COLOR] [*][COLOR=#000000][COLOR=#009900]}[/COLOR][/COLOR] [/LIST]
Check it, http://forums.parallax.com/discussion/150699/emic-arduino-problems-solutions-bohemian-rhapsody
Take a look at the PrintEmicNoWait function and used in the first section of void loop() shown under //Stop Demo