Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Освоение распознавания и синтеза речи на Arduino Due

Компоненты и материалы

Arduino Due×1
SparkFun Electret Microphone Breakout×1
SparkFun Mono Audio Amp Breakout×1
Динамик 0.25 Вт, 8 Ом×1
Макетная плата×1
LED 5 мм красный×3
Резистор 330 Ом×3
Перемычки×1

Инструменты

Программное обеспечение

О проекте

В предыдущем проекте я показывал управление LED через BitVoicer Server. Здесь усложняем задачу: добавляем синтез речи с помощью встроенного в Arduino Due 12-битного ЦАП (DAC) и DMA. На других Arduino потребуется внешний ЦАП и доп. код (библиотека BVSSpeaker не поможет).

В демо Arduino играет мелодию и мигает LED как клавиши пианино (ноты C, D, E). Мелодия — джингл старого ритейлера Mappin.

Поток данных

  1. Звук захватывается и усиливается SparkFun Electret Breakout.
  2. Сигнал оцифровывается ADC Arduino и буферизируется.
  3. Аудиопоток передаётся в BitVoicer Server по Serial (115200 бод).
  4. Сервер распознаёт речь, сопоставляет с командами, шлёт ответы.
  5. Если команда требует синтеза речи — сервер готовит аудиопоток (8-битный моно PCM, 8 кГц) и отправляет на Arduino.
  6. Arduino ставит сэмплы в очередь BVSSpeaker, воспроизводит через DAC+DMA.
  7. SparkFun Mono Audio Amp усиливает сигнал для 8-Ом динамика.

Список материалов и стоимость

Шаг 1: Сборка

Соберите по фото. Под динамик подложите резиновую прокладку — вибрация сильно влияет на качество звука.

Важно: Большинство Arduino работают на 5 В, но Due — на 3.3 В. Electret Breakout лучше работает от 3.3 В. На 5-вольтовых платах добавьте перемычку 3.3V → AREF. На Due AREF подключён через делитель — для использования AREF нужно отпаять резистор BR1.

Шаг 2: Загрузка скетча

Скетч BVS_Demo2.ino (в прикреплённых файлах). Предварительно установите библиотеки BitVoicer Server в Arduino IDE (Import .zip Library).

Скетч состоит из 7 частей:

  1. Библиотеки и переменные: BVSP, BVSMic, BVSSpeaker, DAC. BVSP — связь с сервером, BVSMic — захват звука, BVSSpeaker — воспроизведение через DAC.
  2. setup(): пины, Serial 115200, инициализация классов, установка обработчиков событий frameReceived, modeChanged, streamReceived.
  3. loop(): keepAlive(), receive(), контроль записи/передачи аудио (isSREAvailable, startRecording, stopRecording, sendStream), воспроизведение (play()), синхронизация LED с музыкой (playNextLEDNote).
  4. BVSP_frameReceived: обработка бинарных команд (2 байта: пин, значение) через analogWrite(). Команда playLEDNotes (байт 255) запускает синхронизацию LED.
  5. BVSP_modeChanged: при переходе из стримингового режима в фреймовый — останавливает воспроизведение аудио.
  6. BVSP_streamReceived: приём аудиосэмплов от сервера, постановка в очередь BVSSpeaker.
  7. playNextLEDNote: синхронизация LED с музыкой по таймингам, полученным через Sonic Visualizer (бесплатный аудио-анализатор).

Шаг 3: Импорт объектов решения BitVoicer Server

Четыре типа объектов: Locations, Devices, BinaryData, Voice Schemas.

Файлы для импорта: Device.sof, VoiceSchema.sof.

Шаг 4: Заключение

Включите устройство в BitVoicer Server Manager — Arduino найдёт доступный движок распознавания и начнёт стриминг. RX LED будет активно мигать при приёме аудио от сервера.

В следующем проекте добавлю WiFi на одной Arduino и управление двумя другими — идеи для игры приветствуются!

Код

BVS_Demo2.ino (Arduino)

#include 
#include 
#include 
#include 

#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;
BVSMic bvsm;
BVSSpeaker bvss;
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);
}

Схема подключения

Схема: Electret Mic → A7, Audio Amp → DAC0, LED: D6 (Red), D9 (Yellow), D10 (Green). Питание микрофона от 3.3V Due.

Производственный процесс

  1. Надежная система учета рабочего времени на Arduino с RFID и Python
  2. Проект с датчиком DHT11: индикация температуры светодиодами и пьезо-динамиком на Arduino
  3. Интерактивный гироскопический LED-дисплей на NeoPixel Ring и Arduino
  4. Монитор температуры и реальные часы на Arduino Due с TFT-дисплеем 3.2"
  5. Управление Roomba Create 2 через Arduino и Android: пошаговое руководство
  6. Сборка вольтметра на Arduino с дисплеем Nokia 5110 — Пошаговое руководство
  7. Точное управление сервоприводом через MPU6050 (Arduino, SG90, MG996R)
  8. Модуль GPS u-blox LEA-6H 02: Интеграция с Arduino и Python
  9. Чтение температуры и влажности DHT11 через Blynk — пошаговый урок для Arduino
  10. Создание интерактивного 4x4x4 светодиодного куба на Arduino Uno и 1Sheeld