Голосовое управление 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-шилдом.

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

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 13

      0
      del
        +2
        мне больше с CMUSphinx нравиться рбаотать
          0
          Спасибо за наводку! Обязательно ознакомлюсь! Только начал изучать программирование и искал простое решение проблемы. Думал будет полезно тем, кто так же только начинает двигаться в этом направлении. Лично для меня этот проект оказался очень полезным для понимания принципов работы с голосом.
          • НЛО прилетело и опубликовало эту надпись здесь
              0
              Поддерживаю! Нашел библиотеку Vose (пакет включающий в себя CMUSphinx, FreeTTS) для Processing, но так и не понял как прикрутить к нему русский словарь.
            +1
            На OS X для воспроизведения голоса не нужно использовать сторонние приложения — с этим хорошо справляется «голос системы», на данный момент есть 3 русскоговорящих голоса, использовать очень просто:
            say "Моя фраза"
            

            ну и концы слов не пропадают, попробуйте.
            Выбрать голос можно в:
            Системные настройки — Диктовка и речь — Преобразование текста в речь, там подгрузить нужные голоса и языки.
              0
              Спасибо! Не знал! Буду пробовать!
                0
                Только в дальнейшем планирую использовать распознавание на Rasberry Pi. Именно по этой причине и использовалась «говорилка» от Google.
                +2
                Демонстрацию бы увидеть.
                  0
                  Думаю на днях сделаю небольшую презентацию работы! Отпишусь в этой ветке комментариев по результату.
                  0
                  Yandex.SpeechKit — 10000 запросов в сутки.
                    0
                    К сожалению Яндекс отказывается выдавать API-ключ к Yandex.SpeechKit.
                    Изначально планировал собирать на нем.
                    –1
                    Вспоминается старый анекдот:… и сказал в розетку: «Товарищ майор, две бутылки водки в 310 номер»

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое