Members | Sign In
Legacy MOVI User Community Forum (readonly) > MOVI Question & Answers
avatar

Doing something while Movi is talking

posted Apr 03, 2016 03:37:31 by dmworking247
I'm hoping to have a Servo moving an animatronic 'mouth' while Movi is talking. In previous projects I've simply checked whether a certain pin was HIGH to determine that a wave file was playing, and performed my function (cycling through some mouth animations on a LCD) while this was true.

Can anyone recommend the best way to code a 'while' routine that loops for the duration of Mobi speaking?
page   1
7 replies
avatar
GeraldFriedland said Apr 03, 2016 20:46:31
Take a look at MOVI's user manual, Appendix D. It shows the different event categories that MOVI returns in addition to recognized sentences. In order to detect that MOVI is speaking, all you need to do is 'catch' the BEGIN_SAY and END_SAY event.

However, you can't really run a while loop in the form 'while (movitalking) {...}' inside Arduino's loop() function. You need to allow the Arduino to run it's outer loop and exit the loop() function as quickly as you can. Otherwise, you would be stalling Arduino's main loop and you will never receive any further information from the Arduino (including the information that MOVI stopped talking). So you need to do the steps that would be in your 'while (movitalking)' loop as part of the loop() function.

This would be example code to do that:

bool movitalking=false;

void loop() // run over and over
{
    int result=recognizer.poll(); // See if the recognizer got something
    if (result==1) {
       // recognized first sentence
    }
    if (result==BEGIN_SAY) {
       // MOVI started talking
       movitalking=true;
    }
    if (result==END_SAY) {
       // MOVI stopped talking
       movitalking=false;
       // maybe reset the servo here.
    }
    if (movitalking==true) {
        // do something but make sure you don't stall the loop() method
        // for example, create and call a function servostep() that moves 
        // the servo one step at a time.
    }
}
[Last edited Apr 03, 2016 20:50:37]
avatar
Splitfirz Awesome said Apr 14, 2016 18:19:06
Hi,

I'm trying to achieve something similar with LED strips (displaying messages on my led matrix when MOVI talks).
Tried implementing something similar to what was discussed above but somehow, my LED code doesn't get executed, though MOVI talks and reacts fine.
Understand that the MOVI loop has to be running in the background. Hence, I've re-written my LED loop in the non-blocking code form, using the milli() function. Not sure what I did wrong here. Any advise would be helpful!


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#include "MOVIShield.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(37, 8, 6, NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800);

const uint16_t colors[] = {matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255) };

#ifdef ARDUINO_ARCH_AVR
#include <SoftwareSerial.h>
#endif

MOVI recognizer(true);

void setup()
{

recognizer.init();
recognizer.callSign("Robot");
Serial.begin(9600);
matrix.begin();
matrix.setTextWrap(false);
matrix.setBrightness(40);
matrix.setTextColor(colors[0]);

recognizer.addSentence(F("What is the canteen special")); //1
recognizer.addSentence(F("So tell me the current happenings")); //2
recognizer.addSentence(F("Are there any meeting rooms available")); //3


recognizer.train();
recognizer.setVoiceGender(FEMALE_VOICE);
recognizer.setThreshold(30);
//recognizer.setVolume(50);
}

int x = matrix.width();
int pass = 0;
bool movitalking=false;


void loop()
{
int result=recognizer.poll();
unsigned long my_time = millis();

if (result==1) {
recognizer.say(F("I strongly recommend the Salad Stall"));
}

if (result==2) {
recognizer.say(F("Glad you asked."));
recognizer.say(F("There's a campus career fair happening today!"));
}

if (result==3) {
recognizer.say(F("Thank your lucky stars"));
recognizer.say(F("Four meeting rooms are currently unoccupied"));
}

if (result==BEGIN_SAY){
movitalking=true;
}

if (result==END_SAY){
movitalking=false;
matrix.show(); //off all pixels
}

if (movitalking==true) {
if (result==1)
{
if (my_time % 40 == 0)
{
matrix.fillScreen(0);
matrix.setCursor(x, 0);
String message = "Salad Stall";
int messageScrollLength = (message.length())*8;
matrix.print(message);

if(--x < -messageScrollLength)
{ // number of characters * 6
x = matrix.width();
pass = pass+1;

if (pass == 3)
{
pass = 0;
}
matrix.setTextColor(colors[pass]);
}
matrix.show(); //off all pixels. might be missed out since jumps out of loop when movitalking == false
}

}

if (result==2)
{
if (my_time % 40 == 0)
{
matrix.fillScreen(0);
matrix.setCursor(x, 0);
String message = "Campus career fair";
int messageScrollLength = (message.length())*8;
matrix.print(message);

if(--x < -messageScrollLength)
{ // number of characters * 6
x = matrix.width();
pass = pass+1;

if (pass == 3)
{
pass = 0;
}
matrix.setTextColor(colors[pass]);
}
matrix.show(); //off all pixels. might be missed out since jumps out of loop when movitalking == false
}

}
if (result==3)
{
if (my_time % 40 == 0)
{
matrix.fillScreen(0);
matrix.setCursor(x, 0);
String message = "4 free rooms now";
int messageScrollLength = (message.length())*8;
matrix.print(message);

if(--x < -messageScrollLength)
{ // number of characters * 6
x = matrix.width();
pass = pass+1;

if (pass == 3)
{
pass = 0;
}
matrix.setTextColor(colors[pass]);
}
matrix.show(); //off all pixels. might be missed out since jumps out of loop when movitalking == false
}

}
}
}
[Last edited Apr 15, 2016 02:48:31]
avatar
GeraldFriedland said Apr 14, 2016 22:28:02
It's a bug: You forgot to check for the BEGIN_SAY event to set movitalking to true.

Gerald
avatar
Splitfirz Awesome said Apr 15, 2016 02:50:03
Sorry, missed out pasting that over while copying the code over here. In my actual program, both EVENTS are already defined. Having this issue still. Thanks!

PS: Have edited the code above to complete the picture.
avatar
GeraldFriedland said Apr 17, 2016 14:28:01
I see. What I don't understand is why you are having the
if (result==1) 

and
if (result==2)

twice in your code. Also MOVI will not give you a result while it's talking (obviously since it won't recognize anything during that time).

So I would put all that matrix initialization code into the first two 'if result==' statements and then set a variable depending on whether result was 1 or 2 several iterations before to make the message your are printing dependent on the sentence recognized.

Makes sense?
avatar
JeffreyRick said Sep 04, 2017 01:59:17
I'm also trying to run a servo motor to synch up with the voice. I've tested on other audio products worth some luck, but I'm wondering if I can simply connect a direct line from the speaker to the analog pins on the arduino. I don't want to mess with the impedance to much, because I know how sensitive the MOVI is about that. Should i consider using a resistor (1K) between the speaker output and the analog pin to get my analog signal from MOVI?
Also, I see the recommended speaker impedance is 32 ohms. Would a 25 ohm (unamplified) speaker work? Or still to low?
avatar
GeraldFriedland said Sep 07, 2017 02:09:14
I don't know the impedance of the Arduino analog pins but it's probably in the mega ohms. So you should be fine connecting MOVI's output directly. Even before that: I am not sure the analog pins are fast enough to catch an audio signal though -- but it's worth a shot.

25 ohms should work fine.

Gerald
Login below to reply: