Arduino: Parla!

Tempos atrás, em abril especificamente, comprei uma placa de som chamada GinSing, da http://www.ginsingsound.com/. Quando eu já havia me esquecido da dita, eis que a Receita Federal me comunica que eu poderia retirá-la nos Correios, pagando para isso um imposto equivalente ao custo da plaquinha...

Fui lá na semana passada e retirei-a. No fim de semana comecei a utilizá-la. Ela é construída em torno de um CI chamado BabbleBot, que é um sintetizador de sons muito poderoso, com seis canais e uma gama de efeitos invejável.

Eu resolvi "investir" nessa plaquinha porque qdo eu era adolescente eu fiz algumas montagens de circuitos para efeitos especiais em som de danceterias, houve um tempo em que eu alugava os troços que eu montava e também um "jogo de luzes" para festas. Não que eu tenha a intenção de me tornar um DJ tardio, mas acho que a plaquinha será útil para games, robots e outras brincadeiras.

Resolvi começar a testá-la pelo que mais chama a atenção: a capacidade de síntese de voz. Criei então um modelo relógio digital para deficientes visuais, que poderiam, ao pressionar um botão, ouvir as horas faladas pelo relógio.

Pois taí o bicho funcionando:


A plaquinha funciona em quatro modos: efeitos sonoros, sintetizador de voz, modelagem de instrumentos e modulador sonoro.

No modo sintetizador de voz trabalha com Allophones, que são fonemas codificados, quer dizer, um tipo de alfabeto fonético. Com ele a gente consegue compor frases fonéticas. Os fonemas são mais ou menos específicos da linguagem, no caso, inglês,  mas dá para falar em português, ainda que com um sotaque americano. Fiz alguns testes. Como esse foi o primeiro uso, fiz em inglês. Mas já testei em português também, fica bem inteligível, em outros posts vou usar a nossa inculta e bela.

A plaquinha tem recursos de pausas, entonações, consegue até mesmo cantar. Mas essas features ficam para outros posts.

Abaixo, como é regra nesse blog, o código fonte comentado.

#include "LiquidCrystal.h"
// essa é a classe que interfaceia com a plaquinha
GinSing       GS;                                  

// abaixo os pinos de comunicação. Uma boa característica dessa placa é que
// tem jumpers para configurar os pinos, com duas alternativas para cada,
// o que adiciona muita flexibilidade na combinação com outros shields.

#define rcvPin  4                           
#define sndPin  3                           
#define ovfPin  2                                  


 // botão para acionar a voz
#define sayTimePin 10

// como não tenho um chip de timer, o relógio é iniciado com essa gambi abaixo
long __hour = 21;long __minutes = 12;
long initialSecs = __hour * 3600 + (__minutes * 60);
long _now;
long _hour;
long _minutes;
long _secs;

// esse ponteiro vai para a estrutura de voz, qdo a classe for criada
GinSingVoice * voice = 0x0;                         

// inicializa o display
LiquidCrystal lcd(12, 11, 9, 8, 7, 6); 

// define os sons dos números com os fonemas
GSAllophone one[] = {_W,_U,_NE,_ENDPHRASE};
GSAllophone two[] = {_T,_UE,_ENDPHRASE};
GSAllophone three[] = {_THH,_R,_EE,_ENDPHRASE};
GSAllophone four[] = {_F,_OR,_ENDPHRASE};
GSAllophone five[] = {_F,_IE,_V,_ENDPHRASE};
GSAllophone six[] = {_SE,_I,_KE,_SE,_ENDPHRASE};
GSAllophone seven[] = {_SE,_E,_V,_I,_NE,_ENDPHRASE};
GSAllophone eight[] = {_AE,_T,_ENDPHRASE};
GSAllophone nine[] = {_NE,_IE,_NE,_ENDPHRASE};
GSAllophone ten[] = {_T,_E,_NE,_ENDPHRASE};
GSAllophone eleven[] = {_I,_LE,_E,_V,_E,_NE,_ENDPHRASE};
GSAllophone twelve[] = {_T,_W,_E,_LE,_V,_ENDPHRASE};
GSAllophone thirteen[] = {_TH,_ER,_T,_EE,_NE,_ENDPHRASE};
GSAllophone fourteen[] = {_F,_OR,_T,_EE,_NE,_ENDPHRASE};
GSAllophone fifteen[] = {_F,_I,_F,_T,_EE,_NE,_ENDPHRASE};
GSAllophone sixteen[] = {_SE,_I,_KE,_SE,_T,_EE,_NE,_ENDPHRASE};
GSAllophone seventeen[] = {_SE,_E,_V,_I,_NE,_T,_EE,_NE,_ENDPHRASE};
GSAllophone eighteen[] = {_AE,_T,_EE,_NE,_ENDPHRASE};
GSAllophone nineteen[] = {_NE,_IE,_NE,_T,_EE,_NE,_ENDPHRASE};
GSAllophone twenty[] = {_T,_W,_E,_NE,_T,_EE,_ENDPHRASE};
GSAllophone thirty[] = {_TH,_ER,_T,_EE,_ENDPHRASE};
GSAllophone fourty[] = {_F,_OR,_T,_EE,_ENDPHRASE};
GSAllophone fifty[] = {_F,_I,_F,_T,_EE,_ENDPHRASE};
// palavras
GSAllophone hour[] = {_OU,_R,_ENDPHRASE};
GSAllophone minute[] = {_M,_I,_NE,_I,_T,_ENDPHRASE};
GSAllophone second[] = {_SE,_E,_PITCHDN,_KO,_PITCHDN,_U,_NE,_OD,_ENDPHRASE};
GSAllophone hours[] = {_OU,_R,_SE,_SE,_ENDPHRASE};
GSAllophone minutes[] = {_M,_I,_NE,_I,_T,_SE,_SE,_ENDPHRASE};
GSAllophone seconds[] = {_SE,_E,_PITCHDN,_KO,_PITCHDN,_U,_NE,_PITCHDN,_OD,_SE,_SE,_ENDPHRASE};


void setup (){
  Serial.begin
(9600);
  
Serial.println(initialSecs);

// "pega" a interface de voz
  
voice = GS.getVoice();                            

// inicializa o LCD
  
cd.begin(16, 2);
  
lcd.clear();
  
pinMode(sayTimePin,INPUT);
  
GS.begin ( rcvPin, sndPin, ovfPin );             


}

void loop (){
  
// escreve a hora
  
printTime();
  
delay(1000);
  
// se apertou-se o botão, diz a hora
  
if (digitalRead(sayTimePin) == HIGH)
  
{
    sayTime
();
  
}
}


// calcula a hora atual
void calcTime(){
  _now
= initialSecs + (millis()/1000);
  
_hour = _now / 3600;
  
_minutes = (_now / 60) - (_hour * 60);
  
_secs = _now % 3600 - (_minutes * 60);}


// escreve a hora no display
void printTime(){
  calcTime
();
  
lcd.clear();
  
lcd.print(_hour); lcd.print(":"); lcd.print(_minutes); lcd.print(":"); lcd.print(_secs);

}

// diz a hora, considerando inclusive o plural/singular das palavras
void sayTime(){
  voice
->setNote( C_2 );
  
sayTimeNumbers(_hour);
  
if (_hour > 1)
    
say(hours);
  
else
    
say(hour);
  
sayTimeNumbers(_minutes);  
  
if (_minutes > 1)
    
say(minutes);
  
else
    
say(minute);
  
sayTimeNumbers(_secs);  
  
if (_secs > 1)
      
say(seconds);
  
else
    
say(second);

}

void say(GSAllophone phrase[])
{
  
// diz o texto em phrase
  
voice->speak( phrase);
  
// espera o fim da fala
  
delay ( voice->getMillis( phrase ) );   

}

void sayANumber(byte num)
{
  
// diz um determinado número
  
Serial.println(num);
  
switch(num)
  
{
    
case  1say(one); break;
    
case  2: say(two); break;
    
case  3: say(three); break;
    
case  4: say(four); break;
    
case  5: say(five); break;
    
case  6: say(six); break;
    
case  7: say(seven); break;
    
case  8: say(eight); break;
    
case  9: say(nine); break;
    
case 10: say(ten); break;
    
case 11: say(eleven); break;
    
case 12: say(twelve); break;
    
case 13: say(thirteen); break;
    
case 14: say(fourteen); break;
    
case 15: say(fifteen); break;
    
case 16: say(sixteen); break;
    
case 17: say(seventeen); break;
    
case 18: say(eighteen); break;
    
case 19: say(nineteen); break;
    
case 20: say(twenty); break;
    
case 30: say(thirty); break;
    
case 40: say(fourty); break;
    
case 50: say(fifty); break;
  
}
}


// diz os números do tempo
void sayTimeNumbers(byte number){
  
int n=number / 10;
  
if (n > 1)
  
{
    sayANumber
(n * 10);
    
n=number % 10;
    
sayANumber(n);
  
}
  
else
    
sayANumber(number);  




Comentários

  1. Legal Mauro,

    Pois é! Sorte sua.

    Comprei uma em janeiro/2012 e até hoje a receita (correios?) não me comunicou nada. Mandei um e-mail para o pessoal da ginsing reclamando de extravio e muito solícitos, pediram desculpas e me enviaram outra, mas sem tracking. Até hoje estou a ver navios. Nenhuma das duas aportou por aqui.

    Foda que não tenho cara-de-pau de reclamar e passar vergonha por saber que a causa do problema de "extravios" está aqui na terrinha.

    Enquanto isso, você brinca e eu leio os seus posts! :>)

    []s

    ResponderExcluir
    Respostas
    1. Amigão,

      Na paz?

      Suas placas estão na boca do Leão, pode estar certo. Comigo aconteceu o mesmo, a placa sumiu, eles me mandaram outra, só que eu pedi que enviassem para um parceiro americano que estava vindo cá para um papo. Resultado: as duas chegaram na mesma semana!
      Se vc quiser uma delas emprestada, é só mandar o endereço para o meu e-mail assismauro@hotmail.com.

      É diversão garantida!

      Abracadabraço!

      Mauro

      Excluir
  2. Este comentário foi removido pelo autor.

    ResponderExcluir
  3. Poderia tirar uma dúvida minha? Quando compro um RFID-USB ele já vem com o software para programa-lo ou tem que fazer o download?

    ResponderExcluir
    Respostas
    1. Stephanie, o que eu usei não tem não. Ele emula uma porta serial no USB, como o Arduino. Isso significa que vc pode se comunicar com ele com qualquer programa que leia uma porta serial, ou mesmo vc pode fazer um que se comunique com ele.

      Excluir
  4. Muito show!
    Mas acho qe deve ser mto dificil de fazer :/

    ResponderExcluir
  5. Nada... a depender de sua experiência com programação, é até muito fácil.

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte III

Dividindo um programa (sketch) do Arduino em mais de um arquivo

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I