Friday, 13 April 2012

SpeakJet and Sensors

I finished off the last post with a working speak jet which can be sent commands to say stuff or change pitch/speed/bend/volume. However all it could do was repeat the same phrase once per second. The obvious next step is to get it responding to sensors. Well actually the next step was to make it tell Dave his physics engine was bouncy every second, but that's another story. I've not got much code here as I changed a lot by the time I wrote this post.

I download the SpeakJet software which has a little dictionary of common words and work out the commands to make it say 'I Can See You' in a spooky robot voice, then change the pitch based on the reading from the ping sensor. Both the PING and motion sensor are plugged in, so we now have this circuit (I've left off some of the less relavent connections to the speak jet to keep it simple):

PING, Motion and SpeakJet connected to Arduino
RCX (serial) is connected to GPIO3

Changing the pitch is quite simply a case of sending the SpeakJet a pitch change command (22), followed by a number from 0 to 255 (although 100 to 255 seem to work more effectively). Since the ping sensor is plugged in, all I need to do is modify the code to:
  • Read the PING sensor value
  • Map it to a range between 100 and 255
  • Send the pitch change command to the new value
  • Send commands to say the message
This works wonderfully, and I proudly show Dave, who promptly declares it's just not worth doing unless the pitch can change for every word, not just the whole phrase. This seems easy and I change the code to read the sensor and set pitch before each word. However there is a problem with this approach - it doesn't work. This is because I'm attempting to send all the commands at once. It's true that I take a reading from the ping sensor before each word, but in the real world what's happening is:
  1. Read PING and set pitch
  2. Send say 'I' command
  3. Read PING and set pitch
  4. Send say 'Can' command
  5. Read PING and set pitch
  6. Send say 'See' command
  7. Read PING and set pitch
  8. Send Say 'You' command
  9. Speak jet says 'I Can See You'
The first 8 steps take less than a few ms to execute as we're just reading ping values and sending commands. Hence all the readings come out roughly the same. What we actually needed was:
  1. Read PING and set pitch
  2. Send say x command
  3. Wait for Speak Jet To Finish Saying It
  4. Read PING and set pitch
  5. etc etc etc
So how do I know when the speak jet has finished talking? Well, remember the extra output pins on the speak jet - Ready, Speaking and Buffer 1/2 full? If I connect the Speaking pin back into the Arduino I will be able to detect when the Speak Jet is actually saying words. The circuit modification is very simple:

Add caption

And with a bit code to add the wait it works! After each word is said the pitch will be set base on how close something is to the ping sensor. This video demonstrates it quite nicely (if vid broken check here):

All good! Now for one final trick I hook up a push button to the code that can be hit to say hello just for fun (if broken check here):

I spend the rest of the day neatening up my wiring so it's not a hideous mess of knots and tangles and will actually fit in a robot when I put it there.


No comments:

Post a Comment