LoginSignup
3
3

More than 3 years have passed since last update.

音声入力(Voiceflow)で自作LEGOカーを制御する

Last updated at Posted at 2019-12-28

概要

 一時流行ったスマートスピーカー。今では家の片隅や押し入れに封印されている方が多いのではないでしょうか。(個人的意見)少なくとも私はその一人です。このまま封印されたままになると思っていましたが、第二回技術書同人博覧会で「スマートスピーカーでおうちハック / 温泉BBA」を購入したのをきっかけに封印を解くことができました!

 こちらの書籍でスマートスピーカーのスキルがビジュアルプログラミングできるVoiceflowというツールが紹介されており、スマートスピーカー初心者の私にはぴったりでした。

 基本的な操作を理解できたので、音声入力にで実世界の物を動かしてみたいと思い自作のLEGOカーを制御してみました。

デモ

 音声で「前進」「後退」「停止」を入力すると、それに応じてLEGOカーが動作します。

【実際の動き】

構成

 Voiceflowで音声入力を受け付け、「前進」「後退」といった入力を定型のURLに変換し、obnizへWebhookを投げています。obnizではWehookで受け取ったコマンドに応じてモータを制御しています。次のような構成となっています。
 image.png

以降はもう少し詳しく解説していきます。

Voiceflow

 定型のコマンドを入力するとWebhookをobnizに投げます。次のURLからサンプルプロジェクトを動かすことができます。
https://creator.voiceflow.com/demo/2897161440721865

入力部のフロー
image.png
 最初のSpeekブロックではスキルが開始したことを知らせています。サンプルプロジェクトでは次の部分です。
image.png
 最初のSpeekブロックは次のように設定しています。
image.png
 次にChoiceブロックで入力された音声による分岐を行っています。条件は”前進”、”後退”、”停止”、”その他”です。
image.png
 Choiceブロックの設定は次のようになっています。これが後退と停止まであります。
image.png
 分岐したとのSpeekブロックでは何のコマンドを受け付けたか分かるような応答をしています。このブロックの設定は次のようになっています。
image.png
 その後のSetブロックでは変数にコマンドをセットしています。前進の場合は次のように変数”cmd”に”front”コマンドをセットしています。・
image.png
 Voiceflowで変数を扱うには予め定義が必要です。次のように画面左のブロック一覧タブから変数タブに切り替え、変数名を入力して定義します。
image.png

 最後にIntegrationブロックです。このブロックでWebhookを投げています。
 image.png
 URLは次のようにしています。このフォーマットにすることでobnizにWebhookを投げることができます。URLの「0000-0000」部分はobnizのIDです。「data={cmd}」に各コマンドごとの文字列が入ります。

https://obniz.io/obniz/0000-0000/message?data={cmd}

obniz

 obnizではWebhookで受け取ったコマンドに応じてモータを制御しています。

 Webhook受け取りにはobnizのMessaging機能で実現しています。特定フォーマットのURLにWebhookを投げると、obnizのソースコード内でペイロードのデータを扱うことができます。Messagingについてはこちら

受け取ったデータをプログラム内で使うには次のようにします。

obniz.onmessage = function(message, from) {
    if (message === "front") {   // コマンド判定
      // コマンドごとの処理を記述
    }
  };

プログラム

 今回のプログラムではMeesagingによる制御と、obnizのWeb画面操作による制御の2系統を用意しています。

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="/css/starter-sample.css">
    <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@2.5.0/obniz.js" crossorigin="anonymous"></script>
  </head>
  <body>

    <div id="obniz-debug"></div>

    <div class="wrap">
      <div class="print">
        <h3 class="text-center">Print words on obniz</h3>
        <div>
          <input type="text" id="text" value="Hello World" placeholder="Input in freely">
          <button class="btn btn-primary" id="showtime">Print on obniz</button>
        </div>
      </div>

      <div class="switch">
        <h3 class="text-center"> Swtich </h3>
        <span id="print">undefined</span>
      </div>

      <div class="led">
        <h3 class="text-center">Control</h3>
        <button class="btn btn-primary" id="front">Front</button>
        <button class="btn btn-outline-primary" id="back">Back</button>
        <button class="btn btn-outline-primary" id="stop">stop</button>
      </div>
    </div>

    <script>
      var obniz = new Obniz("OBNIZ_ID");
      obniz.onconnect = async function () {
        obniz.display.clear();
        obniz.display.print("Hello World");

        // Javascript Example
        var R_motor = obniz.wired("DCMotor",  {forward:0, back:1});
        var L_motor = obniz.wired("DCMotor",  {forward:10, back:11});

        obniz.onmessage = function(message, from) {
          console.log(message);
          if (message === "front") {
            R_motor.reverse();
            L_motor.forward();
          }
          if (message === "back") {
            L_motor.reverse();
            R_motor.forward();
          }
          if (message === "stop") {
            R_motor.stop();
            L_motor.stop();  
          }
        };

        $('#front').click(function () {
          R_motor.reverse();
          L_motor.forward();
          obniz.display.clear();
          obniz.display.print("Front");
        });

        $('#back').click(function () {
          L_motor.reverse();
          R_motor.forward();
          obniz.display.clear();
          obniz.display.print("Back");
        });
        $('#stop').click(function () {
          R_motor.stop();
          L_motor.stop();
          obniz.display.clear();
          obniz.display.print("stop");
        });
      };
    </script>
  </body>
</html>

おわりに

今回は車の制御デモで、実際に車を動かすと考えるとレスポンスや認証などの問題が出てきます。ここを突破できれば面白いものが作れそうですね。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3