Голосовое управление Arduino средствами Processing и Google Speech API

Идея: Пришла как-то идея сделать голосовое управление Arduino, но одного Arduino мало, т.к. для системы умного дома нужно еще и общение с компьютером и его системами.Поиск решения: BitVoicer Натыкался на разного рода статьи с применением BitVoicer в связке с Arduino, но вся проблема в том, что BitVoicer работает только на Windows, а это не позволяет использовать систему на простых устройствах типа Rasberry Pi под управлением Unix.Arduino Voice Recognition Так же Arduino можно управлять голосом благодаря модулю распознавания голоса, но пока у меня нет срадств на его приобретение и есть ряд неудобств при использовании этого модуля: ограниченное количество команд, нудное обучение, для новых команд требуется перепрошивка модуля, что уже является минусом, если система отлажена и установлена.Решение Начал искать кросплатформенное решение, которое позволяло бы работать системе на множестве операционных систем. Нашлось такое: Speech to Text Library for Java/Processing. Комплекс реализован на базе языка Processing (Java) и Google Speach API о котом тут уже ранее писали. Данное решение позволяет отслеживать голос в реальном времени enableAutoRecord (), указывать лимит громкости enableAutoThreshold (), подключать внешние микрофоны getLineIn (), указывать язык распознавания setLanguage (String). Полный перечень возможностей и специфика есть на сайте разработчика: http://stt.getflourish.com. Для работы нам понадобиться Google Speech API Key. Как его получить описано тут: www.chromium.org/developers/how-tos/api-keys. Единственный негативный момент в том, что Google Speech позволяет обрабатывать лишь 50 запросов в сутки, но на практике проходят больше 500 запросов.image

Для того, чтобы в дальнейшем было проще ориентироваться по тексту, я прикладываю все исходники, в которых уже прописаны голосовые команды, подключение к плате Arduino, скетч для платы Arduino, голосовое подтверждение фраз и все остальное, что сейчас уже есть и работает: исходники. После скачивание папку GoogleTTS помещаем в библиотеки Processing’a. Скетч для Arduino лежит в папке GoogleTTS/ArduinoSerial. Все писалось на Processing 3.0a4, доступный в пре-релизе на официальном сайте.

Реализация («Слушай мою команду!»): С распознаванием определились. Теперь нужно отлавливать нужные нам команды и по ним принимать решения. За это отвечает секция: void commands () { if (result.equals («arduino»)) { // Ищем соответствие // Выполняющая команда при получении соответсвия } else if (result.equals («сколько время»)) { // Выполняющая команда при получении соответсвия }

} Голосовой ответ Теперь нам нужен инструмент, который будет нам отвечать человеческим голосом в случае найденного соответствия. В качестве инструмента реализации был выбран Google Translate, а вернее модуль, который конвертирует текст в голос. Текст оправляется запросом на сервер Google, преобразуется в звуковой файл и отправляется нам обратно в формате mp3. За это отвечает секция: void googleTTS (String txt, String language) { // преобразование текста в звук происходит командой googleTTS («текст», «язык») String u = «http://translate.google.com/translate_tts? tl=»; u = u + language + »&q=» + txt; u = u.replace (» »,»%20»); try { URL url = new URL (u); try { URLConnection connection = url.openConnection (); connection.setRequestProperty («User-Agent», «Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 1.2.30703)»); connection.connect (); InputStream is = connection.getInputStream (); File f = new File (sketchPath + »/» + txt + ».mp3»); OutputStream out = new FileOutputStream (f); byte buf[] = new byte[1024]; int len; while ((len = is.read (buf)) > 0) { out.write (buf, 0, len); } out.close (); is.close (); println («File created:» + txt + ».mp3»); } catch (IOException e) { e.printStackTrace (); } } catch (MalformedURLException e) { e.printStackTrace (); } } За обработку непосредственно текстовых фраз отвечает секция:

void voicer (String s) { // Выполняется командой voicer («текст») println (s); // применяется для мониторинга текста File f = new File (sketchPath + »/» + s + ».mp3»); // Проверка файла // Если файл уже есть — проигрывть файл if (f.exists ()){ println («Файл уже есть! Проигрываю Файл!»); player = minim.loadFile (s + ».mp3»); player.play (); } // Если файла еще нет — создаем его else { println («Файла еще нет! Создаю!»); googleTTS (s, «ru»); player = minim.loadFile (s + ».mp3»); player.play (); } } Пример реализации распознавания и голосового подтверждения:

void commands () { if (result.equals («компьютер»)) { // Ищем соответствие voicer («Слушаю»); // Получаем голосовое подтверждение // Выполняющая команда при получении соответсвия } } He is alive! Processing + Arduino Ну вот вроде и заработало, но чего-то не хватает. Теперь «подружим» это все с Arduino.Инициализируем serial подключение в Processing для отправки данных на Arduino (для пользователей Mac и Unix): String portName = Serial.list ()[0]; myPort = new Serial (this, portName, 9600); myPort.bufferUntil ('\n'); Для Windows пользователей:

String myPort = new Serial (this, «Ваш COM-порт», 9600); myPort.bufferUntil ('\n'); И отправим туда команду при найденном голосовом соответствии:

void commands () { if (result.equals («включи свет»)) { // Если голосовая фраза распозналась как «включи свет», то выполняем запрос myPort.write («High»); // Отправляет команду High в Serial подключение voicer («Включаю свет»); // Голосовое подтверждение о выполнении команды } else if (result.equals («выключи свет»)) { myPort.write («Low»); // Отправляет команду Low в Serial подключение voicer («Выключаю свет»); // Подтверждение // Выполняющая команда при получении соответсвия } } Теперь займемся платой Arduino. Нам нужно слушать Serial порт и при нахождении команды из списка, выполнять требуемое действие согласно команде. Скетч очень прост:

int led = 13; // Пин светодиода на плате

void setup () { Serial.begin (9600); // Инициализируем серийное подключение pinMode (led, OUTPUT); // Пин светодиода передает данные }

void loop () { int i=0; // переменная для загона строки в буффер char buffer[100]; // массив буфера для загона в него строки if (Serial.available ()){ // Ппроверяем серийный порт на наличие данных delay (100); //загоняем прочитанное в буфер while (Serial.available () && i< 99) { buffer[i++] = Serial.read(); } //закрываем массив buffer[i++]='\0'; String val = buffer; if (val == "High") { // Если получили значение High Serial.println("Led is On"); // Отправляем в Serial подтверждение получения digitalWrite(led, HIGH); // Включаем светодиод } if (val == "Low") { // Если получили значение Low Serial.println("Led is Off"); // Отправляем в Serial подтверждение получения digitalWrite(led, LOW); // Выключаем светодиод } } } Все. Проверяем.Проблемы и планы: Т.к. я не занимался программирование до этого времени, я не до конца понимаю некоторые вещи в процессе отладки. Буду признателен, если кто-нибудь подскажет как решить проблемы из перечня ниже:— Самая основная проблема — голосовая фраза не проговаривается целиком. Пропадают последние буквы. Хотя звуковой файл приходит с сервера Google в нормальном виде. Как я понимаю ситуацию: проблема аудио-плеера, но где именно пока не ясно.— Уже писал, что у Google Speech API есть ограничение на 50 запросов в сутки, но по факту получается больше. В любом случае этого мало. Планирую прописать локальное распознавание главной команды и только после ее распознавания, остальной текст отправлять на обработку Google'у. Ищу решение.— Думаю не помешает отправка команд на Ethernet-шилд Arduino, т.к. некоторые системы могут находиться на приличном расстоянии от главного компьютера и Serial подключение тут уже не подойдет. Займусь этим решение на днях, т.к. нет у меня в наличии роутера для подключения к нему Arduino с Ethernet-шилдом.

На этом собственно все! Прошу строго не судить за строки кода! Я только начал изучать этот плацдарм и буду крайне признателен, если вы меня ткнете носом в то, как делать не нужно и покажете как нужно. Так же буду рад, если к этому проекту подключатся другие заинтересованные лица — всегда открыт к общению!

© Habrahabr.ru