Archive for category Speech

Simple talking robot

 Giving the voice to a toy always has been a dream when I was a child. There weren’t talking toys and the dream was destinated to stay a dream. With the power of the modern microcontrollers, like Arduino, to have a talking robot is one of the things that always I desidered to do. You can build a talking robot in two ways:

  • with the tex-to-speech, writing a text that the robot says
  • recording some audio files with inside the voice already recorded that the robot repeats

The text-to-speech is the best way to do a robot talking. You write a text, and he reads the text: this is the fastest way, but you need a chip that implements the text-to-speech. It is easy if your language is English, not easy if your language is different. For me, the language is the Italian and I haven’t found any cheap chip for italian text-to-speech.

So I used the second method, recording the voice. The method is more complex, but at the end the result is the same.
I built a simple robot, that can be made by every beginner, that does 2 things:

  • it goes around, avoiding obstacles with an ultrasound sensor
  • it talks, thanks to an audio chip

The robot is basically a toy, that fascinates my son, a little child of few months old. He enjoys to see the robot turn around, talking with robotic voice. I did it just for that. Let me to introduce Geronimo 2, the little talking robot:

Geronimo in action:

The little robot is based on two projects already presented in the past: this and this. In these links you can find some details on the building and the hardware. It uses a DFRobot URM37 Ultrasound sensor and a SOMO-14D audio chip, used to talk. This audio chip is low cost (20 euros) and it works with few components (only one 220uf capacitor) and it can be set with an Arduino.
The SOMO-14D plays only files codified with a proprietary format (AD4). But it is available a practical sw that converts MP3 in AD4 format.
In order to allows to talk to the robot, I used a software for italian speech(called Er Finestra), but you can use the speech software you want. For almost all the languages a similar little utility is available.
One problem resolved is due to the fact that Er Finestra can only say something. It can’t at the same time to say and to record. So I downloaded Audacity, an editor audio free, that can record every sound that pass in the sound card.
So you have to start Er Finestra and at the same time to start Audacity that records the phrases read by Er Finestra. Then you can convert the Phrase from MP3 to AD4. The process could be seem complex, but it is more difficult to say than to do.
I read with Er Finestra 40 pieces, I converted them and the robot can say them randomly.
It is possible to use an intelligent algorithm in order to say something responding to external stimulus. For example, to say ‘turn right’, ‘turn left’ or something of similar. The audio chip can play also musical pieces, songs, so it is possible to see the robot going around singing !

The code used for Arduino is simple and it is organized in two parts:
– one for the robot navigation
– one for audio playing
The code is commented, so I don’t think you will have comprehension problems:

//Semplice robot autonomo con sensore ad ultrasuoni per evitare gli ostacoli e chip audio per parlare o suonare una canzone.
//Simple autonomous robot with ultrasonic sensor for obstacles avoidance and audio player chip. It can speak or play a song. 
// written by alegiaco
// Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
//include URM Library - Includi la libreria URM
#include "URMSerial.h"
#include//include servo library - includi la libreria del servo
Servo sservo;
Servo dservo;
Servo uservo;
int ang=0;
int angolomax=0;
int distmax=0;
int value=100;
int ind=0;
int rotazione=0;

// Definizione delle misure per il sensore ad ultrasuoni URM37
// Measures definition for ultrasound URM37
#define DISTANCE 1
#define TEMPERATURE 2
#define ERROR 3
#define NOTREADY 4
#define TIMEOUT 5

//angolo di riposo dei servi delle ruote
// standing angle for servos
#define RIPOSOS 93
#define RIPOSOD 93

// inizializza l'oggetto della libreria urm del sensore ultrasuoni
// initialize object for urm library
URMSerial urm;

//parte relativa al SOMO-14D - Chip Audio - SOMO-14D initial variables assegnation
const unsigned int minVol= 0xfff0;    // Minimum volume - Volume minimo
const unsigned int maxVol= 0xfff7;    // Max Volume - Volume massimo
const unsigned int PlyPse = 0xfffe;   // Play or Pause
const unsigned int Stop= 0xFFFF;      // Stop
const int pinClock= 4;                // clock sul pin dell'arduino - Clock on Arduino pin
const int pinData =5;                 // data sul pin dell'arduino - Data on arduino pin
const int pinBusy =8;                 // busy sul pin dell'arduino - Byte on Arduino pin
const int pinReset=12;                // reset sul pin dell'arduino - Reset on arduino pin
unsigned int volLevel=0x0005;         // imposta massimo livello volume - volume max level
int Song;                             // current Song - canzone attuale
unsigned int vol;                     // volume
int secondi=0, ultimotempo=0;         // varibili per durata brani - variables for songs time
int brano=0;                          // brano riprodotto - song played
int durata[40]={
7,8,14,19,5,8,33,28,5,5,5,5,6,5,5,5,5,6,6,7,6,5,7,8,8,10,4,6,5,6,5,10,5,6,7,6,4,5,6,5}; // durata singoli brani - single songs time

//****************** fine variabili iniziali ************************************
//****************** end initial variables **************************************

void setup()
{
Serial.begin(9600);                          // baud rate - 9600
urm.begin(6,7,9600);                         // RX Pin, TX Pin, Baud Rate
sservo.attach(10);                           // Attacca il servo sinistro al pin 10 - servo left to pin 10
dservo.attach(9);                            // Attacca il servo destro al pin 9 - - servo right to pin 9
uservo.attach(3);                            // Attacca il servo degli ultrasuoni al pin 3 - ultrasonic sensor servo to pin 3
delay(100);
uservo.write(90);                            // metti il servo degli ultrasuoni dritto - ultrasonic servo straight

pinMode(pinData,OUTPUT);                     // set pin 4 to output for Data -
pinMode(pinClock,OUTPUT);                    // set pin 3 to output for clock
pinMode(pinReset,OUTPUT);                    // set pin 7 to allow software reset - imposta pin 7 per il sw reset
pinMode(pinBusy,INPUT);                      // set pin 6 to monitor while Song is playing - pin 6 di monitoraggio mentre il brano è suonato
Reset();                                     // resetta il somo-14D chip audio - somo-14d chip audio reset
}

void loop()
{

playSOMO14D();                                 // suona un brano con chip audio - play song with chip audio
delay(30);                                     // attendi allineamento dei servi - wait for servo alignement
sempreDritto();                                // fai andare il robot sempre dritto - always straight
getMeasurement(DISTANCE);                      // richiedi una nuova lettura della distanza - ask for new distance reading

if (value 0)                    // se il valore e' < 20 cm stiamo per sbattere - if the value is < 20 we are crashing
{
fermaServi();                                // ferma il robot mentre controlla gli ostacoli intorno - stop servos
scandisciAmbiente();                         // controlla gli ostacoli ogni 30 gradi - control obstacles every 30 degrees
ruotaServi();                                // fai girare i servi nella direzione della max strada libera - turn servos in the free direction

}
}

// ------------------ ferma i servi dei motori: robot fermo -----------------------
// ------------------ stop robot - stop servos -----------------------
void fermaServi()
{
sservo.write(RIPOSOS); // ferma ruota sinistra - stop left wheel
dservo.write(RIPOSOD); // ferma ruota destra - stop right wheel
}

// ------------------ fai andare il robot sempre dritto -----------------------
// ------------------ go straight -----------------------
void sempreDritto()
{
sservo.write(RIPOSOS + 80); // fai andare il robot dritto - go straight
dservo.write(RIPOSOD - 80); // fai andare il robot dritto - go straight
}

// ------------------ controlla gli ostacoli ogni 30 gradi -----------------------
// ------------------ control obstacles every 30 degrees -----------------------
void scandisciAmbiente()
{
angolomax=0; // imposta l'angolo di migliore uscita a zero - set exit angle to zero
distmax=0;   // imposta la distanza di uscita migliore a zero - set max distance read to zero
for (ang=0; ang<=6; ang++) // fai un ciclo per controllare dove sono gli ostacoli - cycle to control where are the obstacles
{
delay(100); //attendi allineamento servo ultrasuoni - wait for ultrasonic sensor alignment
uservo.write(ang*30); // imposta il servo degli ultrasuoni sul valore assunto da ang - set to ultrasonic sensor servo to value of ang variable
float sommadist=0;
int contavalori=0;
// 5 letture della distanza. sommale e fai la media
// read 5 time the distance, sum and average
for (int lettura=1; lettura<=5; lettura++)
{
value=-2;
getMeasurement(DISTANCE); //richiedi una nuova lettura della distanza - ask for a new distance read
delay(20);
if (value >= -1 && value < 300) // solo se la distanza è tra -1 e 300 - only if the distance is between -1 and 300
{
if (value==-1) value=1000; //-1 = infinito
sommadist = sommadist + value;
contavalori++;
}
}
int dist=sommadist/contavalori;
if (dist > distmax) // verifica che la distanza letta sia maggiore del max - distance read > max
{
angolomax=ang;  // se e' maggiore del max imposta il nuovo angolo max e - if > max, set new angle max
distmax=dist;  // la nuova distanza max - new max distance

}
}
uservo.write(90); //rimetti il servo degli ultrasuoni dritto - ultrasonic servo straight
}

// ------------------ ruota i servi nella direzione di massimo spazio libero -----------------------
// ------------------ turn servos to max free distance -----------------------
void ruotaServi()
{
for (ind=1; ind < (abs(angolomax-3))*3; ind++)
{
if (angolomax <= 3) { //tra 0 e 90 gradi. between 0 and 90 degrees
sservo.write(RIPOSOS-90);
dservo.write(RIPOSOD-90);
}
else // tra 90 e 180 gradi - between 90 and 180 degrees
{
sservo.write(RIPOSOS+90);
dservo.write(RIPOSOD+90);
}
delay (50); // attendi allineamento servi - wait for servos alignment
}
}

// ------------------ acquisisci misurazione distanza -----------------------
// ------------------ take distance -----------------------
int getMeasurement(int mode)
{
// Request a distance reading from the URM37 - richiedi distanza da URM37
switch(urm.requestMeasurementOrTimeout(mode, value)) // Find out the type of request - verifica tipo richiesta
{
case DISTANCE: // Double check the reading we recieve is of DISTANCE type - doppio check che sia una distanza
return value;
break;
case TEMPERATURE:
return value;
break;
case ERROR:
Serial.println("Error");
break;
case NOTREADY:
Serial.println("Not Ready");
break;
case TIMEOUT:
Serial.println("Timeout");
break;
}

return -2;
}

 

This is the SOMO-14D code part:

 

// ------------------ play song on SOMO-14D -----------------------
void playSOMO14D()
{
if (int(millis()/1000) > ultimotempo + durata[brano]) { //verifica se il brano precedente è terminato - verify if previous song is finished
ultimotempo=int(millis()/1000);
brano=int(random(1, 41)); // prendi un brano a caso - take random song
PlaySong(brano); // suona brano - play song

}
}

/************************************************** ********************************
Send Sequence - Invia sequenza
************************************************** ********************************/

void sendData(int ThisSong)
{
int TheSong = ThisSong;
int ClockCounter=0;
int ClockCycle=15;//0x0f;

digitalWrite(pinClock,HIGH);     // Hold (idle) for 300msec to prepare data start
delay(300);
digitalWrite(pinClock,LOW);       //Hold for 2msec to signal data start
delay(2);  //2msec delay

while(ClockCounter <= ClockCycle)
{ digitalWrite(pinClock,LOW);
if (TheSong & 0x8000)
{digitalWrite(pinData,HIGH);
}
else
{digitalWrite(pinData,LOW);
}
TheSong = TheSong << 1;
delayMicroseconds(200);      //Clock cycle period is 200 uSec - LOW
digitalWrite(pinClock,HIGH);
ClockCounter++;
delayMicroseconds(200);      //Clock cycle period is 200 uSec - HIGH
}

digitalWrite(pinData,LOW);
digitalWrite(pinClock,HIGH);    // Place clock high to signal end of data
}

/************************************************** ********************************
Plays Stored Song by Number - Suona un brano per numero del brano
************************************************** ********************************/

void PlaySong(int numero)
{ sendData(Stop);
int SongNumber=numero;
if (SongNumber >= 0 && SongNumber < 512){     // Song is within range limit
Serial.print("-> Song No.");
Serial.println(SongNumber);
sendData(SongNumber);}

}

/************************************************** ********************************
Reset SOMO
************************************************** ********************************/
void Reset()
{
//Serial.println("RESET.");
digitalWrite(pinReset,LOW);
delay(50);
digitalWrite(pinReset,HIGH);
Song=0;
}

 

Simple audio player with Arduino

A small audio chip is available on the market at low cost (20 euros) that allows to build  an audio player managed with buttons or via serial port, for example with Arduino.

 

This chip is manufactured by 4DSystems  (www.4dsystems.com.au), an Australian company (ahhh the globalization!) which works mainly on LCD graphical modules. Among others, the company also produces the SOMO-14D (link), an audio chip that can play back pre-stored audio files such as voice and music from a micro-SD memory card (max. 2 gb).

The files are saved in ADPCM format, that isn’t a popular format, but it is available a practical conversion sw that in a fast mode can convert .WAV, MP3 etc.

The module SOMO-14D can be managed in: SERIAL-MODE and KEY-MODE.

Using the KEY-MODE the chip works stand-alone and it can be piloted with 3 buttons. 3V for the power and a little speaker (0.5W) are enough.

I made the circuit in a breadboard, but I forgot to take a photo, so I  have nothing to show about the KEY-MODE.

The other possibility is to use the SERIAL-MODE, which allows you to drive the chip with a small microcontroller. Arduino is perfect. There are 4-wires connections and then you can use directly the Arduino to set the play, stop etc.

Is available on the internet (link) a sketch that shows all potential of the chip. I got this chip because i’m interested on to make a talking robot.

I searched in internet for a chip that may allows to implement a text-to-speech in italian on Arduino, but without good results. It is possible to use a sw on a PC windows to make the text-to-speech. After that you can save the audio file obtained on the SOMO-14D  to let the robot to say the right word at the right moment.

In particular, I used the the SW DSpeech, that is a good text-to-speech sw.

I made a little video in order to see the SOMO-14D in action with Arduino. I’m sorry for bad video quality, but I’ve taken it with the cell phone

 

 

Tags: , ,