Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Dominando Reconhecimento e Síntese de Fala no Arduino Due

Componentes e Materiais

ComponenteQuantidade
Arduino Due1
SparkFun Electret Microphone Breakout1
SparkFun Mono Audio Amp Breakout1
Alto-falante: 0.25W, 8 ohms1
Protoboard (genérica)1
LED 5mm Vermelho3
Resistor 330 Ω3
Jumpers (genéricos)1

Ferramentas Necessárias

Aplicativos e Serviços Online

Sobre o Projeto

No meu projeto anterior, mostrei como controlar alguns LEDs usando Arduino e BitVoicer Server. Neste, complico um pouco mais: também vou sintetizar fala usando o conversor digital-analógico (DAC) do Arduino Due. Se não tiver um Due, pode usar outras placas, mas precisará de um DAC externo e código adicional (a biblioteca BVSSpeaker não ajudará com isso).

No vídeo, o Arduino toca uma musiquinha e pisca os LEDs como teclas de piano. Peço desculpas pelas habilidades de piano, mas é o melhor que consigo :) Os LEDs piscam na mesma sequência e tempo das teclas C, D e E reais; se tiver um piano, pode seguir os LEDs e tocar a mesma música. É um jingle de um antigo varejista (Mappin) que nem existe mais.

Procedimentos para Transformar Comandos de Voz em Atividade de LEDs e Fala Sintetizada

  1. Ondas de áudio capturadas e amplificadas pelo SparkFun Electret Breakout.
  2. Sinal amplificado digitalizado e bufferizado no Arduino via ADC.
  3. Amostras de áudio transmitidas ao BitVoicer Server pela porta serial.
  4. BitVoicer Server processa o stream e reconhece a fala.
  5. Fala reconhecida mapeada a comandos pré-definidos, enviados de volta ao Arduino. Se o comando for síntese de fala, o servidor prepara o stream de áudio e envia ao Arduino.
  6. Arduino identifica comandos e executa ações. Se recebe stream de áudio, enfileira na classe BVSSpeaker e reproduz usando DAC e DMA do Due.
  7. SparkFun Mono Audio Amp amplifica o sinal do DAC para驱动 alto-falante de 8 Ohms.

Lista de Materiais (Preços Aproximados)

Passo 1: Fiação

Monte o Arduino e a protoboard com os componentes conforme as imagens. Coloquei uma pequena borracha sob o alto-falante porque vibra muito e sem ela a qualidade de áudio fica consideravelmente afetada.

Dominando Reconhecimento e Síntese de Fala no Arduino Due
Dominando Reconhecimento e Síntese de Fala no Arduino Due
Dominando Reconhecimento e Síntese de Fala no Arduino Due
Dominando Reconhecimento e Síntese de Fala no Arduino Due

Diferença importante: A maioria dos Arduinos opera a 5V, mas o Due roda a 3.3V. Obtive melhores resultados rodando o SparkFun Electret Breakout a 3.3V. Se usar placas Arduino 5V, recomendo jumper entre pino 3.3V e AREF. O Due já usa referência analógica 3.3V, então não precisa jumper no AREF. Na verdade, o pino AREF do Due é conectado ao microcontrolador através de ponte de resistores; para usar AREF, o resistor BR1 deve ser dessoldado da PCB.

Passo 2: Carregando o Código no Arduino

Carregue o sketch abaixo (também disponível em anexos). Antes, instale corretamente as bibliotecas do BitVoicer Server na Arduino IDE (Importar Biblioteca .zip).

Sketch Arduino: BVS_Demo2.ino

O sketch tem sete partes principais:

  1. Referências de bibliotecas e declaração de variáveis: Inclui BVSP.h, BVSMic.h, BVSSpeaker.h, DAC.h. Bibliotecas fornecidas pela BitSophia na pasta de instalação do BitVoicer Server. A biblioteca DAC é incluída automaticamente ao referenciar BVSSpeaker. Declara constantes e variáveis. Classes: BVSP (comunicação), BVSMic (captura/armazenamento de amostras), BVSSpeaker (reprodução via DAC do Due).
  2. Função setup(): Configura modos de pinos e estado inicial; inicia comunicação serial; inicializa classes BVSP, BVSMic, BVSSpeaker. Define "event handlers" (ponteiros de função) para eventos frameReceived, modeChanged, streamReceived da classe BVSP.
  3. Função loop(): Cinco ações: solicita status ao servidor (keepAlive()); verifica dados recebidos e processa (receive()); controla gravação e envio de streams de áudio (isSREAvailable(), startRecording(), stopRecording(), sendStream()); reproduz amostras enfileiradas no BVSSpeaker (play()); chama playNextLEDNote() que controla piscar dos LEDs após comando playLEDNotes.
  4. BVSP_frameReceived(): Chamada quando receive() identifica frame completo. Executa comandos do servidor. Comandos de LEDs contêm 2 bytes: pino e valor. Usa analogWrite(). Verifica se comando playLEDNotes (tipo Byte) foi recebido; se sim, define playLEDNotes=true e marca tempo atual para sincronização.
  5. BVSP_modeChanged(): Chamada quando receive() detecta mudança de modo na direção outbound (Servidor → Arduino). BitVoicer Server pode enviar dados enquadrados ou streams de áudio. Antes de mudar modo, envia sinal. Classe BVSP identifica e dispara evento. Se comunicação muda de stream para framed, sabe que áudio acabou e manda BVSSpeaker parar quando buffer esvaziar.
  6. BVSP_streamReceived(): Chamada quando amostras de áudio recebidas. Recupera amostras e enfileira no BVSSpeaker para reprodução via play().
  7. playNextLEDNote(): Executa apenas se BVSP_frameReceived identificar comando playLEDNotes. Controla e sincroniza LEDs com áudio enviado do servidor. Para sincronizar, usei Sonic Visualizer (software livre) para ver ondas de áudio e identificar quando tecla de piano era pressionada. Também mostra timeline, de onde obtive os milissegundos usados. Parece truque bobo, mas funciona. Analisar stream de áudio e acender LED correspondente seria possível, mas foge do escopo.

Passo 3: Importando Objetos da Solução BitVoicer Server

Configure o BitVoicer Server para trabalhar com o Arduino. Quatro objetos principais: Locations, Devices, BinaryData, Voice Schemas.

Uma das frases no Voice Schema é "play a little song". Contém dois comandos: primeiro envia byte indicando que o próximo comando será stream de áudio; Arduino inicia "tocada" dos LEDs enquanto áudio é transmitido. O áudio é um jingle de piano que gravei e defini como fonte do segundo comando. BitVoicer Server suporta apenas áudio PCM mono 8-bit (8000 amostras/seg). Para converter arquivos, recomendo: audio.online-convert.com.

Importe todos os objetos da solução usados neste projeto nos arquivos abaixo:

Passo 4: Conclusão

Pronto! Ligue tudo e faça as mesmas coisas do vídeo.

Como no projeto anterior, iniciei o reconhecimento de fala habilitando o dispositivo Arduino no BitVoicer Server Manager. Assim que habilitado, o Arduino identifica um Speech Recognition Engine disponível e começa a transmitir áudio ao servidor. Agora há muito mais atividade no LED RX do Arduino enquanto áudio é transmitido do servidor para o Arduino.

No próximo projeto, serei mais ambicioso: adicionarei comunicação WiFi a um Arduino e controlarei outros dois Arduinos todos juntos por voz. Estou pensando em algum tipo de jogo entre eles. Sugestões são bem-vindas!

Código

Sketch Arduino (Arduino)

#include <BVSP.h>
#include <BVSMic.h>
#include <BVSSpeaker.h>
#include <DAC.h>

#define BVSM_AUDIO_INPUT 7
#define RED_LED_PIN 6
#define YELLOW_LED_PIN 9
#define GREEN_LED_PIN 10

const unsigned long STATUS_REQUEST_TIMEOUT = 3000;
const unsigned long STATUS_REQUEST_INTERVAL = 4000;
const int MIC_BUFFER_SIZE = 64;
const int SPEAKER_BUFFER_SIZE = 128;
const int RECEIVE_BUFFER_SIZE = 2;

BVSP bvsp = BVSP();
BVSMic bvsm = BVSMic();
BVSSpeaker bvss = BVSSpeaker();

byte micBuffer[MIC_BUFFER_SIZE];
byte speakerBuffer[SPEAKER_BUFFER_SIZE];
byte receiveBuffer[RECEIVE_BUFFER_SIZE];

bool playLEDNotes = false;
unsigned int playStartTime = 0;

void setup() {
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(YELLOW_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(YELLOW_LED_PIN, LOW);
  digitalWrite(GREEN_LED_PIN, LOW);
  Serial.begin(115200);
  bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
  bvsp.frameReceived = BVSP_frameReceived;
  bvsp.modeChanged = BVSP_modeChanged;
  bvsp.streamReceived = BVSP_streamReceived;
  bvsm.begin();
  bvss.begin(DAC);
}

void loop() {
  bvsp.keepAlive();
  bvsp.receive();
  if (bvsp.isSREAvailable()) {
    if (!bvsm.isRecording) {
      bvsm.setAudioInput(BVSM_AUDIO_INPUT, DEFAULT);
      bvsm.startRecording();
    }
    if (bvsm.available) {
      if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE);
      int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE);
      bvsp.sendStream(micBuffer, bytesRead);
    }
  } else {
    if (bvsm.isRecording) bvsm.stopRecording();
  }
  bvss.play();
  if (playLEDNotes) playNextLEDNote();
}

void BVSP_frameReceived(byte dataType, int payloadSize) {
  if (dataType == DATA_TYPE_BINARY) {
    if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) == RECEIVE_BUFFER_SIZE) {
      analogWrite(receiveBuffer[0], receiveBuffer[1]);
    }
  } else if (dataType == DATA_TYPE_BYTE) {
    if (bvsp.getReceivedByte() == 255) {
      playLEDNotes = true;
      playStartTime = millis();
    }
  }
}

void BVSP_modeChanged() {
  if (bvsp.outboundMode == FRAMED_MODE) bvss.finishPlaying();
}

void BVSP_streamReceived(int size) {
  int bytesRead = bvsp.getReceivedStream(speakerBuffer, SPEAKER_BUFFER_SIZE);
  bvss.enqueue(speakerBuffer, bytesRead);
}

void playNextLEDNote() {
  unsigned long elapsed = millis() - playStartTime;
  allLEDsOff();
  if (elapsed >= 11500) { analogWrite(RED_LED_PIN, 0); playLEDNotes = false; }
  else if (elapsed >= 9900) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 9370) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 8900) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 8610) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 8230) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 7970) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 7470) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 6760) analogWrite(GREEN_LED_PIN, 255);
  else if (elapsed >= 6350) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 5880) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 5560) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 5180) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 4890) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 4420) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 3810) analogWrite(GREEN_LED_PIN, 255);
  else if (elapsed >= 3420) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 2930) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 2560) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 2200) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 1930) analogWrite(YELLOW_LED_PIN, 255);
  else if (elapsed >= 1470) analogWrite(RED_LED_PIN, 255);
  else if (elapsed >= 1000) analogWrite(GREEN_LED_PIN, 255);
}

void allLEDsOff() {
  analogWrite(RED_LED_PIN, 0);
  analogWrite(YELLOW_LED_PIN, 0);
  analogWrite(GREEN_LED_PIN, 0);
}

Esquemático

Dominando Reconhecimento e Síntese de Fala no Arduino Due

Processo de manufatura

  1. Sistema de Presença RFID Confiável com Arduino e Python
  2. Projeto DHT11: Sensor Temperatura/Umidade com LEDs Indicadores e Buzzer
  3. Display Interativo de Giroscópio com Anel NeoPixel e Arduino
  4. Monitor de Temperatura e Relógio Tempo Real com Arduino Due e Display TFT 3.2"
  5. Controlar Roomba Create 2 com Arduino e Android: Guia Passo a Passo
  6. Construa um Voltímetro DIY com Arduino e Display Nokia 5110 – Guia Passo a Passo
  7. Arduino e MPU6050: Controle Preciso de Servomotores SG90 e MG996R
  8. Módulo GPS u-blox LEA‑6H 02: Guia de Integração com Arduino e Python
  9. Leitura de Temperatura e Umidade com DHT11 no Blynk – Tutorial Arduino Passo a Passo
  10. Construa um Cubo de LED 4x4x4 com Arduino Uno e 1Sheeld – Projeto Interativo de LED