Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Dominando reconocimiento y síntesis de voz en Arduino Due

Componentes y materiales

Componente Cantidad
Arduino Due 1
SparkFun Electret Microphone Breakout 1
SparkFun Mono Audio Amp Breakout 1
Altavoz: 0.25W, 8 ohmios 1
Protoboard (genérica) 1
LED 5mm: Rojo 3
Resistencia 330 ohm 3
Cables jumper (genéricos) 1

Herramientas necesarias

Aplicaciones y servicios online

Sobre este proyecto

En mi proyecto anterior mostré cómo controlar unos LEDs usando Arduino y BitVoicer Server. En este proyecto voy a complicar un poco las cosas. También voy a sintetizar voz usando el conversor digital-analógico (DAC) del Arduino DUE. Si no tienes un Arduino DUE, puedes usar otras placas Arduino, pero necesitarás un DAC externo y código adicional para operarlo (la librería BVSSpeaker no te ayudará con eso).

En el vídeo abajo verás que hago que el Arduino reproduzca una pequeña canción y parpadee los LEDs como si fueran teclas de piano. Disculpa mis habilidades de piano, ¡es lo mejor que puedo hacer! :). Los LEDs parpadean en la misma secuencia y temporización que teclas reales Do, Re, Mi, así que si tienes un piano cerca puedes seguir los LEDs y tocar la misma canción. Es un jingle de un antiguo minorista (Mappin) que ya no existe.

Los siguientes procedimientos transforman comandos de voz en actividad de LEDs y voz sintetizada:

  1. Las ondas de audio se capturan y amplifican por la placa Sparkfun Electret Breakout.
  2. La señal amplificada se digitaliza y almacena en buffer en el Arduino usando su conversor analógico-digital (ADC).
  3. Las muestras de audio se transmiten a BitVoicer Server usando el puerto serie del Arduino.
  4. BitVoicer Server procesa el stream de audio y reconoce el habla que contiene.
  5. El habla reconocida se mapea a comandos predefinidos que se envían de vuelta al Arduino. Si uno de los comandos consiste en sintetizar voz, BitVoicer Server prepara el stream de audio y lo envía al Arduino.
  6. El Arduino identifica los comandos y realiza la acción apropiada. Si se recibe un stream de audio, se encola en la clase BVSSpeaker y se reproduce usando el DAC y DMA del DUE.
  7. El SparkFun Mono Audio Amp amplifica la señal del DAC para que pueda impulsar un altavoz de 8 Ohmios.

Lista de materiales

PASO 1: Cableado

El primer paso es cablear el Arduino y la protoboard con los componentes como se muestra en las imágenes. Tuve que poner un pequeño trozo de goma debajo del altavoz porque vibra mucho y sin la goma la calidad de audio se ve considerablemente afectada.

Dominando reconocimiento y síntesis de voz en Arduino Due
Dominando reconocimiento y síntesis de voz en Arduino Due
Dominando reconocimiento y síntesis de voz en Arduino Due
Dominando reconocimiento y síntesis de voz en Arduino Due

Aquí hay una diferencia pequeña pero importante respecto a mi proyecto anterior. La mayoría de placas Arduino funcionan a 5V, pero el DUE funciona a 3.3V. Como obtuve mejores resultados alimentando el Sparkfun Electret Breakout a 3.3V, recomiendo añadir un jumper entre el pin 3.3V y el pin AREF SI usas placas Arduino de 5V. El DUE ya usa referencia analógica de 3.3V así que no necesitas jumper al pin AREF. De hecho, el pin AREF en el DUE está conectado al microcontrolador a través de un puente de resistencias. Para usar el pin AREF, la resistencia BR1 debe desoldarse del PCB.

PASO 2: Subir código al Arduino

Ahora sube el código abajo a tu Arduino. Para comodidad, el sketch también está disponible en la sección Adjuntos al final. Antes de subir, debes instalar correctamente las librerías de BitVoicer Server en Arduino IDE (Importar librería .zip).

Sketch Arduino: BVS_Demo2.ino

Este sketch tiene siete partes principales:

  1. Referencias de librerías y declaración de variables: Las primeras cuatro líneas incluyen referencias a las librerías BVSP, BVSMic, BVSSpeaker y DAC. Estas librerías las proporciona BitSophia y se encuentran en la carpeta de instalación de BitVoicer Server. La librería DAC se incluye automáticamente al referenciar BVSSpeaker. Las demás líneas declaran constantes y variables usadas en el sketch. La clase BVSP comunica con BitVoicer Server, BVSMic captura y almacena muestras de audio, y BVSSpeaker reproduce audio usando el DAC del DUE.
  2. Función setup(): Configura modos de pines y estado inicial; inicializa comunicación serie; inicializa clases BVSP, BVSMic y BVSSpeaker. También establece "manejadores de eventos" (punteros a función) para eventos frameReceived, modeChanged y streamReceived de la clase BVSP.
  3. Función loop(): Realiza cinco acciones importantes: solicita info de estado al servidor (keepAlive()); verifica si el servidor envió datos y procesa lo recibido (receive()); controla grabación y envío de streams de audio (isSREAvailable(), startRecording(), stopRecording(), sendStream()); reproduce muestras de audio encoladas en BVSSpeaker (play()); llama a playNextLEDNote() que controla cómo parpadean los LEDs tras recibir comando playLEDNotes.
  4. Función BVSP_frameReceived: Se llama cada vez que receive() identifica un frame completo recibido. Aquí ejecuto los comandos enviados desde BitVoicer Server. Los comandos que controlan LEDs contienen 2 bytes: el primero indica el pin, el segundo el valor. Uso analogWrite() para establecer el valor apropiado en el pin. También verifico si se recibió el comando playLEDNotes (tipo Byte). Si se recibió, establezco playLEDNotes a true y marco el tiempo actual. Este tiempo será usado por playNextLEDNote para sincronizar LEDs con la canción.
  5. Función BVSP_modeChanged: Se llama cada vez que receive() detecta cambio de modo en dirección saliente (Servidor → Arduino). BitVoicer Server puede enviar datos en frames o streams de audio al Arduino. Antes de cambiar de un modo a otro, BitVoicer Server envía una señal. La clase BVSP identifica esta señal y lanza evento modeChanged. En BVSP_modeChanged, si detecto que la comunicación pasa de stream mode a framed mode, sé que el audio terminó, así que le digo a la clase BVSSpeaker que deje de reproducir muestras.
  6. Función BVSP_streamReceived: Se llama cada vez que receive() identifica que se recibieron muestras de audio. Simplemente recupero las muestras y las encolo en la clase BVSSpeaker para que play() las reproduzca.
  7. Función playNextLEDNote: Solo se ejecuta si BVSP_frameReceived identifica el comando playLEDNotes. Controla y sincroniza los LEDs con el audio enviado desde BitVoicer Server. Para sincronizar LEDs con audio y saber el tiempo correcto, usé Sonic Visualizer. Este software gratuito me permitió ver las ondas de audio para saber fácilmente cuándo se presionaba una tecla de piano. También muestra una línea de tiempo y así obtuve los milisegundos usados en esta función. Suena a truco tonto y lo es. Creo que sería posible analizar el stream de audio y encender el LED correspondiente, pero está fuera de mi alcance.

PASO 3: Importar objetos de solución de BitVoicer Server

Ahora hay que configurar BitVoicer Server para trabajar con el Arduino. BitVoicer Server tiene cuatro objetos principales de solución: Locations, Devices, BinaryData y Voice Schemas.

Una de las frases en mi Voice Schema es "play a little song". Contiene dos comandos. El primero envía un byte que indica que el siguiente comando será un stream de audio. El Arduino entonces empieza a "tocar" los LEDs mientras se transmite el audio. El audio es un pequeño jingle de piano que grabé yo y puse como fuente de audio del segundo comando. BitVoicer Server solo soporta audio PCM mono 8-bit (8000 muestras/segundo), así que si necesitas convertir un archivo de audio a este formato, recomiendo: convertidor online.

Puedes importar (Importing Solution Objects) todos los objetos de solución que usé en este proyecto desde los archivos de abajo. Uno contiene el Device DUE y el otro el Voice Schema y sus Comandos.

Archivos de objetos de solución:

PASO 4: Conclusión

¡Ahí lo tienes! Enciende todo y haz lo mismo que en el vídeo.

Como en mi proyecto anterior, inicié el reconocimiento de voz habilitando el dispositivo Arduino en el BitVoicer Server Manager. En cuanto se habilita, el Arduino identifica un Speech Recognition Engine disponible y empieza a transmitir audio a BitVoicer Server. Sin embargo, ahora ves mucha más actividad en el LED RX del Arduino mientras el audio se transmite desde BitVoicer Server al Arduino.

En mi próximo proyecto, seré un poco más ambicioso. Voy a añadir comunicación WiFi a un Arduino y controlar otros dos Arduinos todos juntos por voz. Estoy pensando en algún tipo de juego entre ellos. ¡Sugerencias bienvenidas!

Código

Sketch Arduino (Arduino)

#include <BVSP.h> #include <BVSMic.h> #include <BVSSpeaker.h> #include <DAC.h> // Define el pin Arduino que se usará para capturar audio #define BVSM_AUDIO_INPUT 7 // Define pines LED #define RED_LED_PIN 6 #define YELLOW_LED_PIN 9 #define GREEN_LED_PIN 10 // Define constantes que se pasan como parámetros a // la función BVSP.begin const unsigned long STATUS_REQUEST_TIMEOUT = 3000; const unsigned long STATUS_REQUEST_INTERVAL = 4000; // Define tamaño del buffer de audio del micrófono const int MIC_BUFFER_SIZE = 64; // Define tamaño del buffer de audio del altavoz const int SPEAKER_BUFFER_SIZE = 128; // Define tamaño del buffer de recepción const int RECEIVE_BUFFER_SIZE = 2; // Inicializa nueva instancia global de la clase BVSP BVSP bvsp = BVSP(); // Inicializa nueva instancia global de la clase BVSMic BVSMic bvsm = BVSMic(); // Inicializa nueva instancia global de la clase BVSSpeaker BVSSpeaker bvss = BVSSpeaker(); // Crea buffer para leer muestras grabadas de la clase BVSMic byte micBuffer[MIC_BUFFER_SIZE]; // Crea buffer para escribir muestras de audio en la clase BVSSpeaker byte speakerBuffer[SPEAKER_BUFFER_SIZE]; // Crea buffer para leer comandos enviados desde BitVoicer Server. // Byte 0 = número de pin // Byte 1 = valor de pin byte receiveBuffer[RECEIVE_BUFFER_SIZE]; // Variables para controlar cuándo tocar "LED Notes". // Estas notas se tocarán junto con la canción transmitida desde BitVoicer Server. bool playLEDNotes = false; unsigned int playStartTime = 0; void setup() { // Configura modos de pines pinMode(RED_LED_PIN, OUTPUT); pinMode(YELLOW_LED_PIN, OUTPUT); pinMode(GREEN_LED_PIN, OUTPUT); // Estado inicial de todos los LEDs digitalWrite(RED_LED_PIN, LOW); digitalWrite(YELLOW_LED_PIN, LOW); digitalWrite(GREEN_LED_PIN, LOW); // Inicia comunicación serie a 115200 bps Serial.begin(115200); // Configura puerto serie Arduino para comunicación, timeout de petición de estado e intervalo de peticiones a BitVoicer Server. bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL); // Define función que manejará evento frameReceived bvsp.frameReceived = BVSP_frameReceived; // Define función que manejará evento modeChanged bvsp.modeChanged = BVSP_modeChanged; // Define función que manejará evento streamReceived bvsp.streamReceived = BVSP_streamReceived; // Prepara timer de la clase BVSMic bvsm.begin(); // Define DAC que usará la clase BVSSpeaker bvss.begin(DAC); } void loop() { // Verifica si intervalo de petición de estado ha pasado y si so, envía petición a BitVoicer Server bvsp.keepAlive(); // Verifica si hay datos disponibles en buffer puerto serie y procesa según especificaciones Protocolo BitVoicer Server bvsp.receive(); // Verifica si hay un SRE disponible. Si hay uno, empieza a grabar. if (bvsp.isSREAvailable()) { // Si la clase BVSMic no está grabando, configura entrada de audio y empieza a grabar if (!bvsm.isRecording) { bvsm.setAudioInput(BVSM_AUDIO_INPUT, DEFAULT); bvsm.startRecording(); } // Verifica si la clase BVSMic tiene muestras disponibles if (bvsm.available) { // Asegura que el modo entrante sea STREAM_MODE antes de transmitir stream if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE); // Lee muestras de audio de la clase BVSMic int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE); // Envía stream de audio a BitVoicer Server bvsp.sendStream(micBuffer, bytesRead); } } else { // No hay SRE disponible. Si la clase BVSMic está grabando, la para. if (bvsm.isRecording) bvsm.stopRecording(); } // Reproduce todas las muestras de audio disponibles en el buffer interno de la clase BVSSpeaker. // Estas muestras se escriben en el manejador de evento BVSP_streamReceived. // Si no hay muestras disponibles en el buffer interno, no se reproduce nada. bvss.play(); // Si playLEDNotes se ha puesto a true, // reproduce las "notas LED" junto con la música. if (playLEDNotes) playNextLEDNote(); } // Maneja evento frameReceived void BVSP_frameReceived(byte dataType, int payloadSize) { // Verifica si el frame recibido contiene datos binarios // 0x07 = Datos binarios (array de bytes) if (dataType == DATA_TYPE_BINARY) { // Si se recibieron 2 bytes, procesa el comando. if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) == RECEIVE_BUFFER_SIZE) { analogWrite(receiveBuffer[0], receiveBuffer[1]); } } // Verifica si el frame recibido contiene tipo de dato byte // 0x01 = Tipo de dato byte else if (dataType == DATA_TYPE_BYTE) { // Si el byte recibido es 255, establece playLEDNotes // y marca el tiempo actual. if (bvsp.getReceivedByte() == 255) { playLEDNotes = true; playStartTime = millis(); } } } // Maneja evento modeChanged void BVSP_modeChanged() { // Si el outboundMode (Servidor → Dispositivo) ha pasado a // FRAMED_MODE, no se supone que se reciba stream de audio. // Dice a la clase BVSSpeaker que termine de reproducir cuando su // buffer interno quede vacío. if (bvsp.outboundMode == FRAMED_MODE) bvss.finishPlaying(); } // Maneja evento streamReceived void BVSP_streamReceived(int size) { // Obtiene el stream recibido de la clase BVSP int bytesRead = bvsp.getReceivedStream(speakerBuffer, SPEAKER_BUFFER_SIZE); // Encola el stream recibido para reproducir bvss.enqueue(speakerBuffer, bytesRead); } // Enciende el LED apropiado según el tiempo // que se recibió el comando para empezar a tocar notas LED. // Los tiempos usados aquí están sincronizados con la música. void playNextLEDNote() { // Obtiene tiempo transcurrido entre playStartTime y tiempo actual. unsigned long elapsed = millis() - playStartTime; // Apaga todos los LEDs allLEDsOff(); // La última nota se ha tocado. // Apaga el último LED y para de tocar notas LED. if (elapsed >= 11500) { analogWrite(RED_LED_PIN, 0); playLEDNotes = false; } else if (elapsed >= 9900) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 9370) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 8900) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 8610) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 8230) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 7970) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 7470) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 6760) analogWrite(GREEN_LED_PIN, 255); // nota Mi else if (elapsed >= 6350) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 5880) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 5560) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 5180) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 4890) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 4420) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 3810) analogWrite(GREEN_LED_PIN, 255); // nota Mi else if (elapsed >= 3420) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 2930) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 2560) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 2200) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 1930) analogWrite(YELLOW_LED_PIN, 255); // nota Re else if (elapsed >= 1470) analogWrite(RED_LED_PIN, 255); // nota Do else if (elapsed >= 1000) analogWrite(GREEN_LED_PIN, 255); // nota Mi } // Apaga todos los LEDs. void allLEDsOff() { analogWrite(RED_LED_PIN, 0); analogWrite(YELLOW_LED_PIN, 0); analogWrite(GREEN_LED_PIN, 0); }

Esquemáticos

Dominando reconocimiento y síntesis de voz en Arduino Due

Proceso de manufactura

  1. Sistema de Asistencia RFID Fiable con Arduino y Python
  2. Proyecto Sensor DHT11 Temperatura y Humedad con Indicadores LED y Altavoz Piezo
  3. Pantalla LED Interactiva con Giroscopio, Anillo NeoPixel y Arduino
  4. Monitor de Temperatura y Reloj en Tiempo Real con Arduino Due y Pantalla TFT 3.2"
  5. Controla tu Roomba Create 2 con Arduino y Android: Guía Completa
  6. Construye un voltímetro DIY con Arduino y pantalla Nokia 5110 – Guía paso a paso
  7. Control Preciso de Servo con Arduino y MPU6050 (SG90 / MG996R)
  8. Módulo GPS u-blox LEA‑6H 02: Guía de integración con Arduino y Python
  9. Leer Temperatura y Humedad con DHT11 en Blynk – Tutorial Paso a Paso con Arduino
  10. Construye un Cubo LED 4x4x4 con Arduino Uno y 1Sheeld – Proyecto LED Interactivo
  11. Proyecto Arduino GPS y Pantalla TFT Táctil Shield: Visualización de Ubicación en Tiempo Real