пятница, 17 апреля 2015 г.

Голосовой модуль беспроводного управления Буратиной

Данная библиотека (далее DLL) предназначена для голосового контроля дискретных I/O платы Arduino по каналу Bluetooth с верхнего уровня, с возможностью индивидуального задания голосовых команд на каждый из 0...53 каналов. Работа библиотеки основана использовании сервиса GoogleSpeech Recognize через библиотеку GoogleSpeechRecognizeAPI3.DLL и последующей передачи команд по прозрачному UART over Bluetooth на основе модуля HC-05. По сути, VoiceControlArduino.DLL является управляющей надстройкой над нижним уровнем GoogleSpeechRecognizeAPI3.DLL. Распознавание осуществляется REALTIME в автоматическом режиме, по задаваемому пользователем пороговому уровню шума и задержке отслеживания окончания фразы (триггера "тишины"). Для корректной работы обязательно наличие Интернет-канала, качественного микрофона/гарнитуры и сопряженного Bluetooth-модуля. Также возможен голосовой контроль через Интернет при использовании сервисов голосового общения, к примеру Zello.

На машине (ПК/нетбук), с сопряженным к ней блютуз-модулем, запускаем десктопный Zello-клиент, на смарте (андроиде) аналогично мобильный Zello-клиент, создаем чат-комнату или разрешаем непосредственное общение абонентов друг с другом, при этом в микшере аудиоустройств меняем активацию записи с микрофона на стерео-микшер для перенаправления аудиопотока.

Видеодемонстрация работы голосового контроля:



Системные требования и зависимости:
  1. Win32/64 (NT/2003/XP/7/8).
  2. Требуется наличие Интернет-канала.
  3. Качественный микрофон или гарнитура/Bluetooth-гарнитура.
  4. Наличие модуля Arduino Mega 2560 c прошитым авторским скетчем BTSerialControl.
Для использования DLL в своих проектах соблюдайте соглашение об stdcall-вызовах. Тип соглашения о вызове объявляется после прототипа функции, будь то объявление функционального типа или же объявление функции.

 Таблица расшифровок параметров экспортируемой функции StartStop() библиотеки 'VoiceControlArduino.DLL':

Пример использования через DynWrapX в VBS:
' регистрируем COM объект DynamicWrapperX в тихом режиме
WshShell.Run ("regsvr32.exe dynwrapx.dll /s"),3, true
' создаем объект DynamicWrapperX.2
Set Wrap = CreateObject("DynamicWrapperX.2")
' создаем объект WScript.Shell
Set WshShell = WScript.CreateObject("WScript.Shell")

Wrap.Register "VoiceControlArduino.dll", "startstop", "i=l", "f=s", "r=l"
res = Wrap.startstop(1)

Do ' бесконечный цикл
  ' задержка на 1000 мс

  wscript.sleep 1000
Loop
Пример использования в Excel (макроса в VBA):
Declare Function startstop Lib "VoiceControlArduino.dll" (ByVal scan As Integer) As long

Sub TestMacros()
 startstop(1)
End Sub

// или по кнопке

Private Sub Command1_Click()
 startstop(1)
End Sub
Пример использования в VB:
Declare Function startstop Lib "VoiceControlArduino.dll" (ByVal scan As Integer) As long

Private Sub Command1_Click()
 startstop(1)
End Sub
Пример динамического подключения (Delphi 6/7/2006/2009/2010/TDL/XE5-7):
var startstop:function(p: integer): pansichar;stdcall;
    LibHandle: THandle;

function LinkProc(ProcName: string):Pointer;
begin
 result:= GetProcAddress(LibHandle, PChar(ProcName))
end;

{ инициализация }
LibHandle:= LoadLibrary('VoiceControlArduino.dll');
 if LibHandle<>0 then begin
  startstop:= LinkProc('startstop');
  startstop(1)
end
...

{ деинициализация }
if LibHandle<>0 then startstop(0)
...
 Код скетча под Буратино (нижний уровень)

/* Control pin2...13, 52, 53 + Sound
 * For my robot over Arduino Mega 2560
 * H-page: http://raxp.radioliga.com
 * Author: Badlo Sergey
 */

// загрузчик
//int ledPin0 = 0; // RX0
//int ledPin1 = 1; // TX0

// I/O

int ledPin2 = 2;
int ledPin3 = 3;
int ledPin4 = 4;
int ledPin5 = 5;
int ledPin6 = 6;
int ledPin7 = 7;
int ledPin8 = 8;
int ledPin9 = 9;
int ledPin10 = 10;
int ledPin11 = 11;
int ledPin12 = 12;
int ledPin13 = 13;
int ledPin14 = 14;
int ledPin15 = 15;
int ledPin16 = 16;
int ledPin17 = 17;

// блютуз HC-05
//int ledPin18 = 18; // TX1
//int ledPin19 = 19; // RX1

// I/O

int ledPin20 = 20;
int ledPin21 = 21;
int ledPin22 = 22;
int ledPin23 = 23;
int ledPin24 = 24;
int ledPin25 = 25;
int ledPin26 = 26;
int ledPin27 = 27;
int ledPin28 = 28;
int ledPin29 = 29;
int ledPin30 = 30;
int ledPin31 = 31;
int ledPin32 = 32;
int ledPin33 = 33;
int ledPin34 = 34;
int ledPin35 = 35;
int ledPin36 = 36;
int ledPin37 = 37;
int ledPin38 = 38;
int ledPin39 = 39;
int ledPin40 = 40;
int ledPin41 = 41;
int ledPin42 = 42;
int ledPin43 = 43;
int ledPin44 = 44;
int ledPin45 = 45;
int ledPin46 = 46;
int ledPin47 = 47;
int ledPin48 = 48;
int ledPin49 = 49;
int ledPin50 = 50;
int ledPin51 = 51;

// светодиод состояния
int led = 52;
// спикер
int speaker = 53;

String inString;

// Названия нот и соответствующие им полупериоды 
byte names[] ={ 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'}; 
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
 
int ledState = LOW;
int count = 0;

void setup() {
  pinMode(speaker,  OUTPUT);
  pinMode(led,      OUTPUT);
 
  pinMode(ledPin2,  OUTPUT);
  pinMode(ledPin3,  OUTPUT);
  pinMode(ledPin4,  OUTPUT);
  pinMode(ledPin5,  OUTPUT);
  pinMode(ledPin6,  OUTPUT);
  pinMode(ledPin7,  OUTPUT); 
  pinMode(ledPin8,  OUTPUT);
  pinMode(ledPin9,  OUTPUT);
  pinMode(ledPin10, OUTPUT);
  pinMode(ledPin11, OUTPUT);
  pinMode(ledPin12, OUTPUT);
  pinMode(ledPin13, OUTPUT); 
  pinMode(ledPin14, OUTPUT);
  pinMode(ledPin15, OUTPUT);
  pinMode(ledPin16, OUTPUT);
  pinMode(ledPin17, OUTPUT);
 
  pinMode(ledPin20, OUTPUT);
  pinMode(ledPin21, OUTPUT); 
  pinMode(ledPin22, OUTPUT);
  pinMode(ledPin23, OUTPUT);
  pinMode(ledPin24, OUTPUT);
  pinMode(ledPin25, OUTPUT);
  pinMode(ledPin26, OUTPUT);
  pinMode(ledPin27, OUTPUT);
  pinMode(ledPin28, OUTPUT);
  pinMode(ledPin29, OUTPUT);
  pinMode(ledPin30, OUTPUT);
  pinMode(ledPin31, OUTPUT);
  pinMode(ledPin32, OUTPUT);
  pinMode(ledPin33, OUTPUT); 
  pinMode(ledPin34, OUTPUT);
  pinMode(ledPin35, OUTPUT);
  pinMode(ledPin36, OUTPUT);
  pinMode(ledPin37, OUTPUT);
  pinMode(ledPin38, OUTPUT);
  pinMode(ledPin39, OUTPUT);
  pinMode(ledPin40, OUTPUT);
  pinMode(ledPin41, OUTPUT);
  pinMode(ledPin42, OUTPUT);
  pinMode(ledPin43, OUTPUT);
  pinMode(ledPin44, OUTPUT);
  pinMode(ledPin45, OUTPUT); 
  pinMode(ledPin46, OUTPUT);
  pinMode(ledPin47, OUTPUT);
  pinMode(ledPin48, OUTPUT);
  pinMode(ledPin49, OUTPUT);
  pinMode(ledPin50, OUTPUT);
  pinMode(ledPin51, OUTPUT);
 
  // задействуем Serial1, их всего 4-ре: Serial, Serial1, Serial2, Serial3
  // для платы Arduino Mega 2560

  Serial.begin(9600);
  Serial.flush();

  Serial1.begin(9600);
  Serial1.flush();
 
  inString = "";
  // гасим светодиод состояния
  digitalWrite(led, LOW); 
}

void sound(char sp) {
ledState = !ledState;         // поменять состояние светодиода
digitalWrite(led, ledState);  // послать сигнал на светодиод 
 
digitalWrite(speaker, LOW); 
// воспроизведение звука от Kurt в оригинале скетча
for (count=0; count<=8; count++) {  // найти ноту
 if (names[count] == sp) {  // ага, нашли
  for( int i=0; i<100; i++ ) {   // играть её 50 циклов
   digitalWrite(speaker, HIGH);
   delayMicroseconds(tones[count]);
   digitalWrite(speaker, LOW);
   delayMicroseconds(tones[count]);
   }
  }
 }
}


void command() {
// разбор данных вида H2...H13, L2...L13: H - включен, L - выключен
   if (inString[0] == 'H') {
     switch (inString[1])
     {
      case 2: digitalWrite(ledPin2,   HIGH); break;
      case 3: digitalWrite(ledPin3,   HIGH); break;
      case 4: digitalWrite(ledPin4,   HIGH); break;
      case 5: digitalWrite(ledPin5,   HIGH); break;
      case 6: digitalWrite(ledPin6,   HIGH); break;
      case 7: digitalWrite(ledPin7,   HIGH); break;
      case 8: digitalWrite(ledPin8,   HIGH); break;
      case 9: digitalWrite(ledPin9,   HIGH); break;
      case 10: digitalWrite(ledPin10, HIGH); break;
      case 11: digitalWrite(ledPin11, HIGH); break;
      case 12: digitalWrite(ledPin12, HIGH); break;
      case 13: digitalWrite(ledPin13, HIGH); break;
      case 14: digitalWrite(ledPin14, HIGH); break;
      case 15: digitalWrite(ledPin15, HIGH); break;
      case 16: digitalWrite(ledPin16, HIGH); break;
      case 17: digitalWrite(ledPin17, HIGH); break;
      case 20: digitalWrite(ledPin20, HIGH); break;
      case 21: digitalWrite(ledPin21, HIGH); break;
      case 22: digitalWrite(ledPin22, HIGH); break;
      case 23: digitalWrite(ledPin23, HIGH); break;
      case 24: digitalWrite(ledPin24, HIGH); break;
      case 25: digitalWrite(ledPin25, HIGH); break;
      case 26: digitalWrite(ledPin26, HIGH); break;
      case 27: digitalWrite(ledPin27, HIGH); break;
      case 28: digitalWrite(ledPin28, HIGH); break;
      case 29: digitalWrite(ledPin29, HIGH); break;
      case 30: digitalWrite(ledPin30, HIGH); break;
      case 31: digitalWrite(ledPin31, HIGH); break;
      case 32: digitalWrite(ledPin32, HIGH); break;
      case 33: digitalWrite(ledPin33, HIGH); break;
      case 34: digitalWrite(ledPin34, HIGH); break;
      case 35: digitalWrite(ledPin35, HIGH); break;
      case 36: digitalWrite(ledPin36, HIGH); break;
      case 37: digitalWrite(ledPin37, HIGH); break;
      case 38: digitalWrite(ledPin38, HIGH); break;
      case 39: digitalWrite(ledPin39, HIGH); break;
      case 40: digitalWrite(ledPin40, HIGH); break;
      case 41: digitalWrite(ledPin41, HIGH); break;
      case 42: digitalWrite(ledPin42, HIGH); break;
      case 43: digitalWrite(ledPin43, HIGH); break;
      case 44: digitalWrite(ledPin44, HIGH); break;
      case 45: digitalWrite(ledPin45, HIGH); break;
      case 46: digitalWrite(ledPin46, HIGH); break;
      case 47: digitalWrite(ledPin47, HIGH); break;
      case 48: digitalWrite(ledPin48, HIGH); break;
      case 49: digitalWrite(ledPin49, HIGH); break;
      case 50: digitalWrite(ledPin50, HIGH); break;
      case 51: digitalWrite(ledPin51, HIGH); break;
      case 52: digitalWrite(led,      HIGH); break;
      case 53: digitalWrite(speaker,  HIGH); break;     
     }
   }
  
   if (inString[0] == 'L') {
     switch (inString[1])
     {
      case 2: digitalWrite(ledPin2,   LOW); break;
      case 3: digitalWrite(ledPin3,   LOW); break;
      case 4: digitalWrite(ledPin4,   LOW); break;
      case 5: digitalWrite(ledPin5,   LOW); break;
      case 6: digitalWrite(ledPin6,   LOW); break;
      case 7: digitalWrite(ledPin7,   LOW); break;
      case 8: digitalWrite(ledPin8,   LOW); break;
      case 9: digitalWrite(ledPin9,   LOW); break;
      case 10: digitalWrite(ledPin10, LOW); break;
      case 11: digitalWrite(ledPin11, LOW); break;
      case 12: digitalWrite(ledPin12, LOW); break;
      case 13: digitalWrite(ledPin13, LOW); break;
      case 14: digitalWrite(ledPin14, LOW); break;
      case 15: digitalWrite(ledPin15, LOW); break;
      case 16: digitalWrite(ledPin16, LOW); break;
      case 17: digitalWrite(ledPin17, LOW); break;
      case 20: digitalWrite(ledPin20, LOW); break;
      case 21: digitalWrite(ledPin21, LOW); break;
      case 22: digitalWrite(ledPin22, LOW); break;
      case 23: digitalWrite(ledPin23, LOW); break;
      case 24: digitalWrite(ledPin24, LOW); break;
      case 25: digitalWrite(ledPin25, LOW); break;
      case 26: digitalWrite(ledPin26, LOW); break;
      case 27: digitalWrite(ledPin27, LOW); break;
      case 28: digitalWrite(ledPin28, LOW); break;
      case 29: digitalWrite(ledPin29, LOW); break;
      case 30: digitalWrite(ledPin30, LOW); break;
      case 31: digitalWrite(ledPin31, LOW); break;
      case 32: digitalWrite(ledPin32, LOW); break;
      case 33: digitalWrite(ledPin33, LOW); break;
      case 34: digitalWrite(ledPin34, LOW); break;
      case 35: digitalWrite(ledPin35, LOW); break;
      case 36: digitalWrite(ledPin36, LOW); break;
      case 37: digitalWrite(ledPin37, LOW); break;
      case 38: digitalWrite(ledPin38, LOW); break;
      case 39: digitalWrite(ledPin39, LOW); break;
      case 40: digitalWrite(ledPin40, LOW); break;
      case 41: digitalWrite(ledPin41, LOW); break;
      case 42: digitalWrite(ledPin42, LOW); break;
      case 43: digitalWrite(ledPin43, LOW); break;
      case 44: digitalWrite(ledPin44, LOW); break;
      case 45: digitalWrite(ledPin45, LOW); break;
      case 46: digitalWrite(ledPin46, LOW); break;
      case 47: digitalWrite(ledPin47, LOW); break;
      case 48: digitalWrite(ledPin48, LOW); break;
      case 49: digitalWrite(ledPin49, LOW); break;
      case 50: digitalWrite(ledPin50, LOW); break;
      case 51: digitalWrite(ledPin51, LOW); break;
      case 52: digitalWrite(led,      LOW); break;
      case 53: digitalWrite(speaker,  LOW); break;       
     }
   }
  
   inString = "";
}


void loop() {
 
 // работа с портом загрузки для тестов
 while (Serial.available()) {
  char inChar = Serial.read(); // читаем побайтно
  Serial.write(inChar);          // эхо

  if (inChar!= 13) {
   inString += inChar;          // накопление
   sound(inChar);
  }
  if (inChar == 13) {
   command();
   Serial.flush();
  }
 }

 // работа с прозрачным UART over BlueTooth HC-05
 while (Serial1.available()) {
  char inChar = Serial1.read(); // читаем побайтно
  Serial1.write(inChar);          // эхо

  if (inChar!= 13) {
   inString += inChar;           // накопление
   sound(inChar);
  }
  if (inChar == 13) {
   command();
   Serial1.flush();
  }
 }

}

ПОРЯДОК ИСПОЛЬЗОВАНИЯ
  1. Подключите ваш микрофон или гарнитуру/блютуз-гарнитуру (используя аудио-шлюз) и убедитесь в его/ее работоспособности.
  2. Извлеките содержимое архива (саму библиотеку 'VoiceControlArduino.dll' и рабочую папку 'VoiceControlArduino' в каталог по вашему выбору.
  3. Проведите регистрацию COM-сервера 'DynamicWrapperX' через batch-файл 'regdynwrapx.bat', если вы хотите использовать работу через VBS.
  4. Запустите скрипт 'test_VoiceControlArduino.vbs' и установите HID-гаджет в слот USB.
  5. В момент запуска скрипта рядом с библиотекой появится (автосоздание) файл настроек 'VoiceControlArduino.ini', вы можете в любой момент времени изменять следующие настройки во время работы:
 Arduino_Port_Manual=COM9 - номер в ручном режиме (при подключении по USB реализован автопоиск)
 Threshold_Level=20 - пороговый уровень срабатывания "триггера тишины" отслеживания начала фразы, %
 Delay_Off=1000 - величина задержки отключения "триггера тишины" отслеживания конца фразы, мс
 Lang=RU - язык распознавания (жестко забит русский )
 0=0 - любая фраза/слово/цифра для контроля 0-м каналом
 ...
 53=53 - любая фраза/слово/цифра для контроля 53-м каналом
 Recognition= - результат распознавания (лог плагина)
скачать

1 комментарий:

  1. В связи с нововведениями Google архив обновлен.

    ОтветитьУдалить

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Просьбы и предложения из разряда: «можно ваш Skype/Viber/телефон», «напишите мне в vk/FB», а также другие им подобные — игнорируются. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.