Голосовое управление Arduino средствами Processing и Google Speech API. Делаем управление светодиодом голосом с помощью Arduino

Пришла как-то идея сделать голосовое управление 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 запросов.

Для того, чтобы в дальнейшем было проще ориентироваться по тексту, я прикладываю все исходники, в которых уже прописаны голосовые команды, подключение к плате 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; 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(); 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; // массив буфера для загона в него строки if(Serial.available()){ // Ппроверяем серийный порт на наличие данных delay(100); //загоняем прочитанное в буфер while(Serial.available() && i< 99) { buffer = Serial.read(); } //закрываем массив buffer="\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-шилдом.

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

В данном проекте я совместил детектор распознавания лиц (face detection) и следящую (tracking system) систему.

Вкратце суть проекта: вебкамера, установленная на поворотном механизме подключена к компьютеру под управлением операционной системы Windows и с установленным программным обеспечением OpenCV . Если программа обнаруживает в поле зрения вебкамеры лицо, то вычисляется центр лица. Координаты X и Y передаются в контроллер Arduino, который подключен к компьютеру по USB. В свою очередь, контроллер Arduino по принятым командам управляет двумя сервомоторами: по координате X и по координате Y, т.о. обеспечивается следящая система.

Библиотеку OpenCV (Open Source Computer Vision Library) можно скачать . Библиотека мультиплатформенная, в настоящее время существует под следующие ОС: Windows, Linux, Android, Mac OS и даже iOS. Библиотека обеспечивает обработку изображений в режиме реального времени. Написана на С/С++.

Т.о. данный проект представляет собой смесь soft и hard решений. Обработка изображения ведется на компьютере, а управление серво осуществляется при помощи контроллера.

Итак, что я использовал для проекта:

Программное обеспечение:
Arduino IDE 1.0 for Windows

Microsoft Visual C++ 2010 Express SP1
Serial C++ Library for Win32 (от Thierry Schneider)

Железо:
компьютер с ОС Windows 7 SP1
Arduino Uno или совместимый + БП
2 сервопривода
USB вебкамера

Итак, поехали.

Шаг 1. Установка программного обеспечения

1) Если у вас ОС Windows, то скачайте файл OpenCV-2.3.1-win-superpack.exe (или более позднюю версию) и установите библиотеку.

2) Скачайте и установите Microsoft Visual C++ 2010 Express. Если у вас 64-битная версия Windows, то также необходимо будет скачать Windows SDK (но для 64 версии могут быть проблемы, я так и не смог заставить работать OpenCV под Windows 7 x64).

Процесс настройку OpenCV для Visual C++ читайте на официальном сайте.

Шаг 2. Крепление камеры и сервомоторов

Я не стал делать конструкцию "долговечной", потому как после достижения конечной цели я все разбираю для следующего проекта.
Вебкамеру я прикрепил к сервомотору оси Х, а его, в свою очередь закрепил на сервомоторе оси Y. И всю эту конструкцию закрепил в струбцине от "третьих рук".

Шаг 3. Подключение

Подключение сервомоторов:
Желтый вывод от серво оси Х подключается к выводу 9 контроллера Arduino
Желтый вывод от серво оси Y подключается к выводу 10 контроллера Arduino
Красный вывод Vcc от серво подключается к выводу 5V
Черный вывод GND от серво подключается к выводу GND контроллера Arduino

Подключение вебкамеры:
Вебкамера подключается к компьютеру по USB интерфейсу. Программа C++ идентифицирует вебкамеру по номеру USB-порта. Возможно, потребуется указать порт в программе.

Подключение контроллера Arduino UNO:
Контроллер также подключается к компьютеру через USB-интерфейс. В системе появляется виртуальный COM-порт, который необходимо внести в код программы на C++.

А помните, как несколько лет назад (а может быть и сейчас) была популярна идея управления светом в комнате при помощи хлопков в ладоши? А, ведь, это очень удобно, лежишь в постели, лень встать и хлопком в ладоши выключается свет или заходим домой, темно, нащупать выключатель долго, а тут с самого порога хлопок или два и свет уже горит. Мне кажется, что эта концепция актуальна до сих пор, но к ней можно применить уже более высокие технологии по сравнению с теми, что были 5 лет, 10 лет назад. Теперь за сравнительно небольшую сумму можно купить несколько деталей и запрограммировать конструкцию на подобные функции, о чем пойдет речь ниже.

Сегодня рассмотрим модуль, предназначенный для распознавания голосовых команд (в том числе и просто голоса в рамках записанной голосовой команды) – Voice recognition module V3.1 (V3) или часто встречающуюся кодировку название FZ0475 .

В комплект поставки входит сам модуль (печатная плата очень хорошего качества), микрофон на гибкой ножке с разъемом 3,5 мм jack и угловые PLS контакты с шагом 2,56 мм для платы модуля (их можно не использовать, если подключаться к контактам модуля другим способом).

На сегодняшний день существует несколько видов модулей с аналогичным функционалом разных производителей и разработчиков или исполнений. Данный модуль распознавания голоса, на мой взгляд, имеет некий баланс между стоимостью, функционалом, удобством. Более мощным и существенно более дорогим будет модуль EasyVR. Более дешевыми и неудобными будут модули на базе LD3320 (неудобные как минимум потому, что нормальное описания на них найти не просто, а в остальном это уже субъективно).

Характеристики модуля Voice recognition module V3.1 (V3):

  • Напряжение питания – 5 вольт
  • Потребляемый ток – до 40 мА
  • Интерфейсы – UART, GPIO
  • Точность распознавания – 99% (в идеальных условиях)
  • Дальность действия – зависит от используемого микрофона, для штатного микрофона из комплекта дальность составляет 0,5 – 1 метр максимального расстояния при достаточно громком голосе, если же голос тихий, то придется подносить микрофон поближе ко рту

Модуль представляет собой небольшую аккуратную плату, на которой расположены главный микроконтроллер (черная клякса), разъем jack 3,5 мм для подключения микрофона, микросхема flash памяти, контакты GPIO, UART и питания, пара светодиодов и остальной необходимый обвес, необходимый для работы схемы – резисторы, конденсаторы, кварц. Компактный размер платы позволит без особых трудностей встраивать модуль в собственные разработки. Для увеличения дальности работы голосовых команд предположительно необходимо использовать микрофон с усилителем. При достижении приемлемой дальности модуль пригоден для использования в системах умного дома. Без доработок по улучшению дальности работы модуль можно использовать в настольных системах управления, а также в системах охраны (контроля и ограничения доступа). Со штатным микрофоном из-за небольшой дальности надежнее всего использовать модуль распознавания голоса как гарнитуру и беспроводным способом передавать команды контроллеру, который чем-то управляет, используя аккумулятор и беспроводные модули (например, HC-05 или HC-12 или подходящие любые другие). Модуль способен работать без внешнего микроконтроллера, так как производителем заложена функциональная самостоятельность, необходимо лишь однократно записать голосовые команды и задать настройки для самостоятельной работы при помощи внешнего устройства (ПК или МК).

Итак, чтобы начать работу с модулем распознавания голоса нам необходимо подключить его или к компьютеру (нужен USB-UART переходник), или к микроконтроллеру (необходимо разрабатывать программный код для управления модулем).

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

Перед началом работы разберемся с платой. С торцов платы справа гнездо для подключения микрофона, с другого четыре контакта UART интерфейса. Снизу расположены восемь контактов, использующихся для вывода сигналов, вызываемых распознаванием голосовых команд. Сверху четыре контакта, настроенных как вход сигнала, используются для переключения между группами (по семь голосовых команд в каждой) команд, если такая функция используется. И остальные шесть контактов сверху, вероятно, используются для подключения к памяти модуля.

Для функционирования и конфигурации модуля используется система команд. Общий вид кадра выглядит следующим образом:

Первые четыре команды 00, 01, 02, 03 используются для проверки состояния модуля и его настроек. Следующие шесть команд 10, 11, 12, 13, 14, 15 используются для изменения настроек модуля, среди которых управление портами вывода и настройки автостарта (auto load). Далее три команды 20,21, 22 используются для записи голосовых команд. Следующие три команды 30,31,32 используются для управления распознаванием голосовых команд. Команды 0A, 0D, FF используются только при возвращении данных самим модулем. Команд на самом деле не много и все это не так страшно, как кажется на первый взгляд в документации на модуль. Рассмотрим команды, необходимые для работы с модулем распознавания голоса. Не все из существующих команд несут практический характер.

Примечательно то, что модуль может работать без внешнего управляющего микроконтроллера, а также самостоятельно управлять чем-нибудь своими портами вывода. Для этого необходимо их настроить (команды 12, 13, 14).

Команда 12 – настроить порты вывода. Этой командой настраивается режим работы портов вывода модуля распознавания голоса.

Формат: | AA | 03 | 12 | MODE | 0A |

Где MODE может принимать четыре значения: 0 – импульсный режим (при срабатывании голосовой команды соответствующий команде вывод изменит свое состояние на время, устанавливаемое командой 13), 1 – режим переключателя (toggle или flip) (при каждом срабатывании голосовой команды вывод, соответствующий голосовой команде инвертируется), 2 – режим включения (при срабатывании голосовой команды вывод перейдет в состояние логической единицы и больше не перейдет в состояние логического нуля, сброс осуществляется командой 14), 3 – режим выключения (аналогично режиму включения только, наоборот, при срабатывании голосовой команды вывод переходит в состояние логического нуля).

Наиболее практичным является режим переключателя, не требующий лишних команд. Импульсный режим был бы хорош, но логика этого режима такова, что при срабатывании голосовой команды он однократно выдает логическую единицу, на время от 10 мс до 1 с. Это мало. Хотя, смотря какие требования к этому режиму, может быть полезно. Режимы включения и выключения реализованы неудобно, так как требуют исполнение дополнительных команд.

Команда 13 – задание длительности импульса соответствующего режима.

Формат: | AA | 03 | 13 | LEVEL | 0A |

Где LEVEL принимает значение от 00 до 0F (соответствует длительности от 10 мс до 1 с).

LEVEL длительность
0x00 10 мс
0x01 15 мс
0x02 20 мс
0x03 25 мс
0x04 30 мс
0x05 35 мс
0x06 40 мс
0x07 45 мс
0x08 50 мс
0x09 75 мс
0x0A 100 мс
0x0B 200 мс
0x0C 300 мс
0x0D 400 мс
0x0E 500 мс
0x0F 1 с

Команда 14 – сброс портов вывод до состояния заданного режимами включения или выключения.

Формат: | AA| 03 | 14 | FF | 0A | - сброс всех портов вывода

| AA| 03+n | 14 | IO0 | ... | IOn | 0A | - сброс выбранных портов вывода

Где n – количество выводов, которые сбрасываются выборочно, IO0…IOn – перечисление этих выводов в кадре отправки данных.

Далее чтобы голосовые команды выполнялись их необходимо записать в модуль (обучить модуль). Здесь есть ограничение. Одновременно распознаваться могут только семь команд, хотя записать их можно значительно больше. Для того чтобы расширить диапазон голосовых команд, которые будут распознаваться используется система группировки (команда 32), которая управляется портами ввода модуля. Устанавливая конфигурацию сигналов на этих контактах, осуществляется выбор группы команд, которая будет распознаваться. Это обусловлено ограниченностью производительности используемого голосового контроллера модуля.

Команда 20 - запись одной или нескольких голосовых команд.

Формат: | AA| 03+n | 20 | R0 | ... | Rn | 0A |

Где n - это количество записываемых голосовых команд (если записывается одна команда n=0, две команды n=1 и так далее в соответствии с общим форматом передачи команд Lenght - длина), R0...Rn номера голосовых команд (AA 03 20 03 0A - команда для записи третьей голосовой команды).

Команда 21 - запись одной голосовой команды и установка для нее подписи.

Формат: | AA| 03+SIGLEN | 21 | RECORD | SIG | 0A |

Где RECORD - номер голосовой команды, SIG - подпись (может состоять из нескольких байт, таким образом, что каждый байт может соответствовать кодировке символа алфавита при необходимости), SIGLEN - количество байт, из которых состоит подпись.

Команда 22 - добавление или удаление подписи для выбранной голосовой команды.

Формат: | AA | 03+SIGLEN | 22 | RECORD | SIG | 0A | - добавление подписи

| AA | 03 | 22 | RECORD | 0A | - удаление подписи

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

После того, как в модуле записаны голосовые команды ничего происходить не будет до тех пор, пока эти команды не поместить в "распознаватель" (Recognizer) модуля. Для этого необходимо воспользоваться командой 30. После выполнения этой команды модуль начнет ожидать совпадения голосовой команды с сохраненными образцами. Одновременно распознавать можно лишь сем команд. При этом будет медленно моргать желтый (оранжевый) светодиод на плате модуля.

Команда 30 - загрузить записи в "распознаватель" (Recognizer) модуля.

Формат: | AA| 2+n | 30 | R0 | ... | Rn | 0A |

Формат ответа следующий: | AA | 07 | 0D | 00 | GRPM | R | RI | SIGLEN | SIG | 0A |

Где GRPM - информация о группе, к которой относится команда (если используется), R - распознанная голосовая команда (по этим данным можно различать команда между собой если не используются подписи), RI - индекс команды в распознавателе, SIGLEN - длина подписи в байтах, SIG - подпись (если используется).

Ну и наконец, если модуль должен работать самостоятельно, то необходимо воспользоваться командой 15 для автоматического запуска по преднастройкам распознавателя. В этом случае модуль распознавания голоса будет работать самостоятельно без необходимости инициализации после включения.

Команда 15 - установка автозапуска распознавателя при включении.

Формат: | AA| 03 | 15 | 00 | 0A | - отключение функции автозапуска

| AA| 03+n | 15 | BITMAP | R0 | ... | Rn | 0A | - установка функции автозапуска

Для контроля верности выполнения команд каждой из них соответствует свой ответ. В случае такой необходимости все данные можно найти в документации на модуль распознавания голоса, приложенной в конце статьи. Не стоит забывать, что все числовые значения представлены в шестнадцатеричной форме.

Таким образом, при помощи системы команд можно достаточно гибко настраивать модуль распознавания голоса для использования в различных целях. Если же простого управления портами вывода модуля недостаточно, то модуль распознавания голоса можно подключать к другим устройствам посредством UART или GPIO. Для беспроводного подключения можно использовать ранее рассмотренные модули .

При помощи беспроводных модулей можно подключать модуль распознавания голоса к любым устройствам, где это необходимо. Например, подключим его к микроконтроллеру, который относительно получаемых данные о распознавании голосовых команд будет управлять светодиодами. Беспроводные модули позволяют передавать данные в двух направлениях, поэтому при необходимости для микроконтроллера можно написать код инициализации голосового модуля и записи голосовых команд. В нашем случае под управлением ПК в модуле уже записано несколько голосовых команд и настроен автозапуск распознавания при включении питания, поэтому для микроконтроллера пропишем только прием данных и управление светодиодами относительно этих данных. Микроконтроллер STM32F103C8T6 использует USART1 для приема данных и контакты PB10...PB15, настроенные на выход, которыми управляет светодиодами. Исходный код расположен в приложения в конце статьи.

Немного о результатах

Распознавание голоса идет не совсем точное. Это зависит от выбранных команд и голоса пользователя. При тестировании мною было обнаружено несколько отрицательных моментов. При обучении командам модуля были выбраны голосовые команды «раз» и «два». Команда «два» проходила всегда четко, а вот команда «раз» достаточно часто определялась как команда «два» и соответственно выполнялся код второй команды. Далее при попытке отдавать голосовые команды по-английски (а они не записывались в голосовой модуль) практически всегда команда «one» определялась как «два». Возможно, все дело в произношении, интонации и прочих аспектах человеческого голоса, заложенных в алгоритм кодировки голосового модуля произносимых команд. Однако эти секреты производители в открытом доступе не дают. Кроме этого на качество распознавания влияют внешние шумовые условия – гул с улицы, шум вентилятора, случайные звуки и прочее. Производитель заостряет внимание на то, что высокий уровень точности распознавания имеет место в идеальных условиях. Идея использования микрофона с усилителем, конечно, увеличит дальность работы устройства, но так же увеличит вероятность и ошибки, так как усиление голоса будет происходить и с усилением шумов.

В итоге , если у вас невысокие требования к распознаванию голоса и выполнению голосовых команд, то этот модуль честно отработает, потраченные на него, деньги.

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
IC1 МК STM32

STM32F103C8

1 В блокнот
VR1 Линейный регулятор

AMS1117-3.3

1 В блокнот
MOD1, MOD3 Модуль беспроводной связи HC-12 2 В блокнот
MOD2 Модуль распознавания голоса VR3.1 1 В блокнот
Z1 Кварц 8 МГц 1

В данном проекте я совместил детектор распознавания лиц (face detection) и следящую (tracking system) систему.

Вкратце суть проекта: вебкамера, установленная на поворотном механизме подключена к компьютеру под управлением операционной системы Windows и с установленным программным обеспечением OpenCV . Если программа обнаруживает в поле зрения вебкамеры лицо, то вычисляется центр лица. Координаты X и Y передаются в контроллер Arduino, который подключен к компьютеру по USB. В свою очередь, контроллер Arduino по принятым командам управляет двумя сервомоторами: по координате X и по координате Y, т.о. обеспечивается следящая система.

Библиотеку OpenCV (Open Source Computer Vision Library) можно скачать . Библиотека мультиплатформенная, в настоящее время существует под следующие ОС: Windows, Linux, Android, Mac OS и даже iOS. Библиотека обеспечивает обработку изображений в режиме реального времени. Написана на С/С++.

Т.о. данный проект представляет собой смесь soft и hard решений. Обработка изображения ведется на компьютере, а управление серво осуществляется при помощи контроллера.

Итак, что я использовал для проекта:

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

Железо:

компьютер с ОС Windows 7 SP1

Arduino Uno или совместимый + БП

2 сервопривода

USB вебкамера

Итак, поехали.

Шаг 1. Установка программного обеспечения

1) Если у вас ОС Windows, то скачайте файл OpenCV-2.3.1-win-superpack.exe (или более позднюю версию) и установите библиотеку.

2) Скачайте и установите Microsoft Visual C++ 2010 Express. Если у вас 64-битная версия Windows, то также необходимо будет скачать Windows SDK (но для 64 версии могут быть проблемы, я так и не смог заставить работать OpenCV под Windows 7 x64).

Процесс настройку OpenCV для Visual C++ читайте на официальном сайте.

Шаг 2. Крепление камеры и сервомоторов

Я не стал делать конструкцию "долговечной", потому как после достижения конечной цели я все разбираю для следующего проекта.

Вебкамеру я прикрепил к сервомотору оси Х, а его, в свою очередь закрепил на сервомоторе оси Y. И всю эту конструкцию закрепил в струбцине от "третьих рук".

Шаг 3. Подключение

Подключение сервомоторов:

Желтый вывод от серво оси Х подключается к выводу 9 контроллера Arduino

Желтый вывод от серво оси Y подключается к выводу 10 контроллера Arduino

Красный вывод Vcc от серво подключается к выводу 5V

Черный вывод GND от серво подключается к выводу GND контроллера Arduino

Подключение вебкамеры:

Вебкамера подключается к компьютеру по USB интерфейсу. Программа C++ идентифицирует вебкамеру по номеру USB-порта. Возможно, потребуется указать порт в программе.

Подключение контроллера Arduino UNO:

Контроллер также подключается к компьютеру через USB-интерфейс. В системе появляется виртуальный COM-порт, который необходимо внести в код программы на C++.

Скачать файлы проекта

Оригинал статьи на английском языке (перевод Колтыков А.В. для сайта cxem.net)

  • Processing ,
  • Разработка веб-сайтов
  • Идея:

    Пришла как-то идея сделать голосовое управление 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 запросов.

    Для того, чтобы в дальнейшем было проще ориентироваться по тексту, я прикладываю все исходники, в которых уже прописаны голосовые команды, подключение к плате 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; 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(); 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; // массив буфера для загона в него строки if(Serial.available()){ // Ппроверяем серийный порт на наличие данных delay(100); //загоняем прочитанное в буфер while(Serial.available() && i< 99) { buffer = Serial.read(); } //закрываем массив buffer="\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-шилдом.

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



    Понравилась статья? Поделиться с друзьями: