En la actualidad podemos disponer de una enorme variedad de formas para representar información de manera visual. Desde simples presentadores de LED a pantallas gráficas complejas, pero que sucede cuando necesitamos que nuestra electrónica "hable", desde siempre ese ha sido un punto complicado, lograr que una máquina reproduzca sonidos humanos fue siempre un tema desafiante. El chip S1V30120 de Epson contiene todos los codecs analógicos, memoria y algoritmos incorporados para imitar la voz humana controlando todo el chip a través de un bus SPI. El sonido de voz resultante se puede ajustar para que se escuche como ingles americano, español clásico o español latino, también dispone de varios ajustes finos para ajustar el tono y velocidad de tal forma que se puede llevar su funcionamiento a un punto en que la voz resultante es muy parecida a la voz humana. (Ninguno de estos ajustes se han realizado en este ejemplo, lo que se escucha es la configuración "de fábrica".) Presenta una solución económica y relativamente simple, siendo el único cuidado la selección del tipo de microcontrolador a utilizar que tiene que disponer de por lo menos 45 KB de flash. La razón de ello son los datos de inicialización que se deben cargar para que el sintetizador vocal funcione.
En el ejemplo propuesto estamos usando una placa provista por Mikroelektronika denominada TextToSpeech click. Esta placa monta un chip S1V30120 con toda su electrónica periférica lista para ser conectada y empezar a trabajar. El controlador que estamos usando es un STM32F407vg montado sobre un Shield para la entrenadora Discovery con cuatro puertos MiKroBus. Un barómetro provee los datos de temperatura y humedad que el sintetizador vocal leerá, e informar estos datos de manera hablada.
El siguiente es el código completo de funcionamiento.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/****************************************************************************** Descripción : Programa ejemplo para el sintetizador vocal S1V30120* Target : STM32F407VG* ToolChain : MiKroC para ARM V5.0* www.firtec.com.ar*****************************************************************************/// NOTA: Activar Tools-> Options-> Output-> Case Sensitive//----------------------------------------------------------------------------#include "text_to_speech.h"// Pines usados en la pantalla LCDsbitLCD_RSatGPIOE_ODR.B0;//<<<<sbitLCD_ENatGPIOE_ODR.B6;sbitLCD_D4atGPIOC_ODR.B12;sbitLCD_D5atGPIOC_ODR.B13;sbitLCD_D6atGPIOC_ODR.B14;sbitLCD_D7atGPIOC_ODR.B15;// Pines usados en S1V30120sbitTTS_RSTatGPIOE_ODR.B4;sbitTTS_CSatGPIOE_ODR.B5;sbitTTS_MUTEatGPIOC_ODR.B5;sbitTTS_RDYatGPIOD_IDR.B2;voidhardware_init(void);voidS1V30120_config(void);voidmsg_blk(uint16_t*req,uint16_t*err);voidfatal_err(uint16_t*err);voidsystem_init(void);chartxt[12];unsignedcharI2C_LeerRegistro(char);voidI2C_EscribirRegistro(char,char);floatLPS25HB_LeerTemperatura(void);floatLPS25HB_LeerPresMilibares(void);charLPS25HB_LeerStatus(void);unsignedchardevice_id=0;unsignedchartemporal_datos[12];volatilefloattemperatura,presion;#define I2C_ADR 0x5D//=====================================================// Esta función lee el registro Status del sensor// ====================================================charLPS25HB_LeerStatus(){returnI2C_LeerRegistro(0x27);}//======================================================// Esta función lee el valor del barómetro y retorna la// presión medida en milibares.// El valor barométrico se lee de tres registros.// =====================================================floatLPS25HB_LeerPresMilibares(){chartemporal;unsignedlongresultado;temporal=I2C_LeerRegistro(0x2A);resultado=(unsignedlong)temporal;temporal=I2C_LeerRegistro(0x29);resultado=(resultado<<8)|temporal;temporal=I2C_LeerRegistro(0x28);resultado=(resultado<<8)|temporal;return(float)resultado/4096;}//=====================================================// Esta función escribe en los registros internos// del sensor.// ====================================================voidI2C_EscribirRegistro(charwrDir,charwrDato){temporal_datos[0]=wrDir;temporal_datos[1]=wrDato;I2C1_Start();I2C1_Write(I2C_ADR,temporal_datos,2,END_MODE_STOP);}//=====================================================// Esta función lee el valor de temperatura desde el// sensor.// ====================================================floatLPS25HB_LeerTemperatura(){unsignedchartemporal;intresultado;temporal=I2C_LeerRegistro(0x2C);resultado=(int)temporal;temporal=I2C_LeerRegistro(0x2B);resultado=(resultado<<8)|temporal;return((float)resultado/480)+42.5;}//=====================================================// Esta función lee en los registros internos// del sensor.// ====================================================unsignedcharI2C_LeerRegistro(charrDir){temporal_datos[0]=rDir;I2C1_Start();I2C1_Write(I2C_ADR,temporal_datos,1,END_MODE_RESTART);I2C1_Read(I2C_ADR,temporal_datos,1,END_MODE_STOP);returntemporal_datos[0];}voidmsg_blk(uint16_t*req,uint16_t*err){}voidfatal_err(uint16_t*err){GPIOD_ODR.B14=1;tts_init();tts_fatal_err_callback(fatal_err);}voidS1V30120_config(){tts_init();tts_msg_block_callback(msg_blk);tts_fatal_err_callback(fatal_err);tts_image_load((uint8_t*)TTS_INIT_DATA,sizeof(TTS_INIT_DATA));tts_image_exec();tts_interface_test();tts_power_default_config();tts_audio_default_config();tts_volume_set(0);tts_default_config();tts_config(0x04,false,TTSV_LS,0x0200);}voidhardware_init(){GPIO_Digital_Output(&GPIOE_ODR,_GPIO_PINMASK_4);GPIO_Digital_Output(&GPIOE_ODR,_GPIO_PINMASK_5);GPIO_Digital_Output(&GPIOC_ODR,_GPIO_PINMASK_5);GPIO_Digital_Input(&GPIOD_IDR,_GPIO_PINMASK_2);Delay_ms(200);SPI3_Init_Advanced(_SPI_FPCLK_DIV128,_SPI_MASTER|_SPI_8_BIT|_SPI_CLK_IDLE_HIGH|_SPI_SECOND_CLK_EDGE_TRANSITION|_SPI_MSB_FIRST|_SPI_SS_DISABLE|_SPI_SSM_ENABLE|_SPI_SSI_1,&_GPIO_MODULE_SPI3_PB345);Delay_ms(200);}voidISR_init(){GPIO_Digital_Input(&GPIOA_BASE,_GPIO_PINMASK_0);// PA0 como entradaSYSCFGEN_bit=1;// RCC APB2 reloj de periféricos activoSYSCFG_EXTICR1=0x00000000;// Mapa de pines para PA0EXTI_RTSR=0x00000000;// Flanco de subida para PA0 desabilitadoEXTI_FTSR=0x00000001;// Flanco de bajado para PA0EXTI_IMR|=0x00000001;// Set de la máscara para PA0NVIC_IntEnable(IVT_INT_EXTI0);// Habilita interrupciónes EXTI0}voidmain(){GPIO_Digital_Output(&GPIOD_BASE,_GPIO_PINMASK_14);GPIO_Digital_Output(&GPIOD_BASE,_GPIO_PINMASK_12);GPIOD_ODR.B14=0;hardware_init();S1V30120_config();Lcd_Init();ISR_init();Lcd_Cmd(_LCD_CLEAR);Lcd_Cmd(_LCD_CURSOR_OFF);I2C1_Init_Advanced(100000,&_GPIO_MODULE_I2C1_PB87);Lcd_Out(1,2,"Sensor Barometrico");Lcd_Out(2,7,"LPS25HB");Lcd_Out(3,1,"Temperatura: ");Lcd_Out(4,1,"P/Milibares:");device_id=I2C_LeerRegistro(0x0F);// Lee ID del sensor Barométricoif(device_id!=0xBD){Lcd_Out(2,1,"ERROR de Sensor");while(1);}I2C_EscribirRegistro(0x20,0xB0);GPIOD_ODR.B12=0;while(1){unsignedcharstatus;status=LPS25HB_LeerStatus();if(status&0x01){temperatura=LPS25HB_LeerTemperatura();// Lee temperaturasprintf(temporal_datos,"%2.1f",temperatura);Lcd_Out(3,13,temporal_datos);}Delay_ms(250);if(status&0x02){presion=LPS25HB_LeerPresMilibares();// Lee presión en milibaressprintf(temporal_datos,"%4.0f",presion);Lcd_Out(4,13,temporal_datos);}Delay_ms(1000);}}voidExtInt()ivIVT_INT_EXTI0icsICS_AUTO{EXTI_PR.B0=1;// Borra la bandera de interrupciónGPIOD_ODR.B12=~GPIOD_ODR.B12;sprintf(txt,"Temperatura %2.1f",temperatura);tts_speak(txt);sprintf(txt,"Presion %4.0f",presion-1);tts_speak(txt);}
Para poder compilar este código se necesita la biblioteca para el TextToSpeech click que se descarga desde el mismo sitio de Mikroelektronika. Para reproducir la lectura de los valores del barómetro se oprime el botón de usuario (PA0) que se ha vinculado a una de interrupción externa.
Esto es solo un ejemplo de uso, no se ha ajustado ningún parámetro del sintetizador vocal para refinar el sonido o hacer que la voz escuchada suene natural.