Welcome to Synthiam!

Program robots using technologies created from industry experts. ARC is our free-to-use robot programming software that makes features like vision recognition, navigation and artificial intelligence easy.

Get Started
Asked — Edited

Text To Servo Speech Engine

Here is a little project I have been working on with fellow forum member Bob Houston.... It was originally written by another forum member Louis Vazquez.... who really did a good job on this... I have tweaked it a little to try and make it more adaptable from project to project.... It works like sound servo, but using text to drive the servo instead of sound....

I have Luis' permission to post so here it is...


I have posted it to the cloud as well...

Thanks -- By reading the script it will be very useful. I was thinking of tying this up the arms too for arm movement when talking. Will give the bot some more animation.

The Sound servo can control concurrent servos?

@aliusa Just download the script, load it into ARC connect a servo to your V4 and try it out for yourself...

You can drive more than one servo port with the script too...
A cool effect would be for the sound servo to control arms and this script to control mouth. This would let them be different from each other, allowing the arms to be based on volume.
While testing this with a 2800 character string (traffic feed from london) this didnt produce good results. It also took about 3 minutes to process the text to figure out the mouth movements. It looks like the purchase of the board I was looking at is still on the books.

I am not bashing this at all as it is great for short phrases, but long text takes too long to parse and it doesn't work nearly as well.
d. cochran, That's good to know. I have not tried it with really long text. Could the time it takes to parse be related to the speed of the computer? I would think that has something to do with it. What is this "board" you are referring to and what does it do?
Yes, it could but I am running the fastest possible config. I7, 32 GB ram, SSD drives for storage that are in an array. It would be hard to find a faster computer than I have, so I dont think that is the issue. I had 86% free memory while running.

The board i am looking at is

If you feel like building it, here are the details.
build one for about $20 USD

edit to add more info
string length 2559

CPU at 35%
Memory at 21%
Disk activity at 1%

Parsing string and building OWC string.
Started at 2:01:35
Finished at 2:05:24

While not running this process, CPU at 30%

Here is the text that was being parsed.
"M5 J4A M42One lane closed due to broken down vehicle on M5 Southbound between J4A M42 and J5 A38 Droitwich / Wychbold. M61 J8 A674 ChorleyQueueing traffic and Main carriageway closed due to multi-vehicle accident on M61 Northbound between J6 A6027 Horwich and J8 A674 Chorley. Royston - A10 A505A10 both ways closed due to accident, two vehicles involved between A505 and Royston Road Melbourn turn off. Earith - A1123 Hill Row Causeway Long DroveA1123 Hill Row Causeway both ways closed due to serious accident between Long Drove Earith and Church Lane Haddenham. M6 J10 A454 / B4464 Wolverhampton / WalsallOne lane closed and heavy traffic due to accident on M6 Northbound between J10 A454 / B4464 Wolverhampton / Walsall and J10A M54. Hollym - A1033 Hollym Road Tithe Barn LaneA1033 Hollym Road both ways closed due to serious accident between Tithe Barn Lane and South Carr Dales Road. M40 J3 A40 / A4094 High Wycombe East / LoudwaterQueueing traffic and lane blocked on exit slip road due to accident, motorcyclist involved on M40 Northbound at J3 A40 / A4094 High Wycombe East / Loudwater, congestion on M40 to J2 A355 Beaconsfield. Burford - A456 Forresters RoadA456 both ways closed due to serious accident near Forresters Road. M1 J15A A43 / A5123 Towcester / Northampton ServicesQueueing traffic due to earlier accident, around eight cars involved on M1 Southbound at J15A A43 / A5123 Towcester / Northampton Services, congestion on M1 to Watford Gap Services. All lanes have been re-opened. Kennford - A38 A380 Splatford SplitSlow traffic due to earlier accident on A38 Northbound near A380 Splatford Split. In the roadworks area. All lanes have been re-opened. Croydon - A212 Wellesley Road Station RoadA212 Wellesley Road Northbound closed, queueing traffic due to burst water main between Station Road and A222 St James's Road, congestion on A212 Park Lane to A232 Barclay Road. M20 J7 A249 Maidstone/Detling HillSlip road onto motorway closed due to queues of lorries on M20 coastbound at J7 A249 Maidstone / Detling Hill. M25 J6 A22 / B2235 GodstoneOne lane closed and very slow traffic due to barrier repairs on M25 anticlockwise between J6 A22 / B2235 Godstone and J5 M26 / A21 Sevenoaks. M20 J8 A20 Leeds Castle / Maidstone ServicesM20 coastbound closed, delays due to Operation Stack between J8 A20 Leeds Castle / Maidstone Services and J9 A20 Ashford. M25 J6 A22 / B2235 GodstoneOne lane closed and heavy traffic due to barrier repairs on M25 anticlockwise between J6 A22 / B2235 Godstone and J5 M26 / A21 Sevenoaks. "
Just a thought, I ran into an issue like this with the text-to-speech(audio) module I worked on back on the V3. I don't know how the script is handling the parsing but if it parses everything and then sends the data out to the servos you could have an issue there. When I was working on the text-to-speech(audio) module the board I was using had a limit on the number of characters you could send in each packet. My work around was to send each character singularly as I parsed. This way it can be processing the text as it is implementing it to the servos. Just a thought.
I updated the script in the Cloud and moved all Variables to the top of the file for easy tweaking.


$pauseForLetters = 85
$pauseForvowels = 85
$pauseBetweenWords = 90

$mouthServoPin = D0
$mouthServoOpenAngle = 60
$mouthServoClosedAngle = 90

The top of the file looks like this now.
Here's a couple of ideas on how we can make this "Text to Speech" engine Command Control even better.

1. Is it possible to make it so that the command control doesn't have to be put in after every line of text? Perhaps,a way to put it once at the beginning of the script and then any text in that script would be "spoken".

2. Is there a way to get the sound to come out of the EZB rather than the computer? For example a "$SentEZB" command, kind of like "SayEZB".
# Mouth servo is on D2
# speech settings - medium rate of speaking
say($sent2) # or sayEZB(

Change this line from say to sayEZB and the sound will come out of the ezb.
In the new script

would be changed to
Man, this community is great! Thanks d.cochran, I knew it would be EZ to do !
One down one to go.
I posted this question awhile ago and didn't get a response. So I'll post it again just in case someone had a thought on it.

Is it possible to make it so that the command control doesn't have to be put in after every line of text? Perhaps, a way to put it once at the beginning of the script and then any text in that script would be "spoken".
Make a script that is called to handle the function of evaluating the text. This one does that.

In your other scripts, set the $sent = "whatever you want to say"


Call this script.
You could also use waitforchange on the $sent.... The draw back is you couldn't say the same phrase twice in a row.....


sayezb("What you want to say")

would be changed to if you are using the Script Manager which I would recommend.


$sent = "What you want to say"
ControlCommand("Script Manager", ScriptStart, "Text Speech Engine")
SLEEP(2000) #added to wait for the script to process. May not be needed.

The WaitForChange($Sent) would need to be added to the Text Speech Engine. As soon as it got done speaking or maybe just before, you could
$Sent = "" so that the script would have time to evaluate what it needs to before the variable is set to "" again.

This would allow you to just use

$sent = "What you want to say" instead of SAYEZB( "What you want to say" )

you would need to put the Text Speech Engine in a loop and call it at the start of the project in an init or startup script.

Good point Rich and Richard.
United Kingdom
@Richard Unless you have the $sent variable "reset" to something immediately after waitforchange
Ok... I figured a repeatuntil loop in the speech engine (to keep it running) could be used and a waitforchange right after the repeatuntil command...