Raspberry Pi ロボット化計画 第1段階~ ラズベリーパイ研究室

Raspberry Pi は小さいながら、とても高性能なコンピューターです。しかも GPIO というインターフェイスがついていて、ここに LED や様々なセンサー、モーターなどを繋いで制御することができます。

Linux 系の OS を選べば、膨大な Linux の資産がほぼそのまま使え、とても簡単に様々なことができるようになります。

この「Raspberry Pi ロボット化計画」では、Raspberry Pi を使って簡単なロボットを作ることを目指してみたいと思います。出来るだけ簡単に、誰でも作れる基本的な方法をご紹介しますので、その通りに作るも自分なりにアレンジするもあなたの自由です。



おススメ!記事
Raspberry Pi 用「HAL」で、
カップラーメン・タイマーを作ってみよう!
ラズパイDIYの決定版! ソケットサーバー「HAL」をご紹介します。

※誠に申し訳ありませんがこちらの電子工作のコンテンツは弊社の実験制作例となっております。十分な安全が保障されているわけではないため、参照や実施は自己責任となってしまいますのでご注意ください。

Raspberry Pi ロボット化計画(第1回)

これから数回に渡って、Raspberry Pi でロボットを作る記事を書いてみようと思います。今回は第 1 回目として、

  • しゃべる
  • 音声の命令を受け取る
  • 蛍光灯をオン・オフする

までです。

今回の到達予想図

必要要項

  • Raspberry Pi(音声認識エンジン Julius がかなり重いため、Pi 2 以上が必要です)
  • ソケットサーバー「HAL」version 1.3(動作試験用には体験版をご利用下さい)
  • ブレッドボード 小さくても 30 ✕ 10 くらいのもの。
  • 赤外線リモコン受信モジュール - 1 個(PL-IRM2161-XD1を使用したが入手困難な模様。別のもので構いません)
  • 1.0μF セラミックコンデンサ(赤外線リモコン受光モジュールの仕様書のサンプル回路に併せて適宜)
  • 赤外線LED - 1 個(OSI5LA5113Aを使用しました。別のもので構いません)
  • NPN型トランジスタ 2SC2120Y - 1 個
  • 抵抗 10Ω - 1 個
  • 抵抗 240Ω - 2 個
  • 抵抗 10KΩ - 1 個
  • CdSセル - 1 個
  • MCP3208-CI/P - 1 個(ADコンバーター)
  • ジャンパワイヤ―各種

リンク)電子工作の味方「秋月電子通商」

リンク)電子工作の味方「千国電商オンラインショップ」

リンク)ゆりかごから墓場まで「Amazon.co.jp」

回路図

※ピン番号は Raspberry Pi のピン番号。(GPIO 番号、WiringPi 番号はそれぞれ異なるので注意)

回路図

ブレッドボード予想図

ブレッドボード

Raspberry Pi のセットアップ

Raspberry Pi 簡単セットアップマニュアル にそって、一通りのインストールを行って下さい。

音声認識エンジンとして「Julius」、日本語テキストから音声ファイルを生成するライブラリ「OpenJTalk」、そして Julius の音声認識結果を処理するためのサーバー・アプリケーション・フレームワーク「HAL」が必要です。

HAL のアップロードディレクトリ

HAL はお好きなディレクトリに展開してご利用頂けますが、本記事では、

/var/www/HAL

として展開されている事を想定して記載を行います。

赤外線リモコンの学習

赤外線リモコンの信号を学習するには

cd /var/www/HAL/infrared

に移動し、

スキャンプログラム

sudo gcc scanir.c -o scanir -lwiringPi

送信プログラム

sudo gcc sendir.c -lm -o sendir -lwiringPi

で、コンパイルして下さい。それぞれ、scanir および sendir という実行プログラムが作成されます。

お使いの赤外線リモコン信号を学習させるには、

sudo ./scanir データ名

を実行して下さい。例えば、 sudo ./scanir light_on.data のようになります。拡張子は有っても無くても構いませんし、.data でなくても構いません。

以下のように待受け状態になりますので、赤外線リモコン受光モジュールに向けてお使いのリモコンの、覚えさせたい信号を送信して下さい。(英語がおかしいのは気にしないでください)

pi@raspberrypi:/var/www/HAL/infrared $ sudo ./scanir test.data
write file: test.data
scaning pin: 7 (wiringpi)
max keep time: 40(ms)
Infrared LED scanning start.
Pressed Ctrl+C, this program will exit.

信号がスキャンされると

Scanning has been done.

と表示され、プロンプトが戻ります。指定したデータ名(例えば test.data)のファイルが作成されていることを確認して下さい。vi データ名 などのコマンドで、どんなデータが記録されているか確認してみてください。

このデータが正常に動作するかは、

sudo ./sendir データ名 送信回数

で確かめることができます。赤外線 LED をお使いの機器(例えば蛍光灯)に向けてから、上記コマンドを実行して下さい。送信回数はお使いの機器にもよりますが、3 回くらい送信するのが良いかもしれません。

上記 scanir および sendir については、「赤外線信号受信プログラム」「赤外線送信プログラム」を御覧ください。パラメターを追加することで、その挙動を変えることができます。

Julius の辞書ファイル作成

Julius での音声認識は少々重い処理のため、普通に認識させると Raspberry Pi の CPU では時間がかかり過ぎます。そこで辞書ファイルを作成し、利用できる言葉を限定することで高速な認識を行えるようにします。

具体的には .voca ファイルと .grammar ファイルを作成して Julius でコンパイルを行うことで辞書ファイルが作成されます。(詳しい導入については「Juliusによる音声認識~国産オープンソースライブラリの活用」を御覧ください)

ソケットサーバー「HAL」version 1.3 では、下記ディレクトリに、single、kaden、zatsudan という3つの定義ファイルがサンプルとして収録されています。

/var/www/HAL/julius

これらに対し、

sudo ~/julius-4.3.1/gramtools/mkdfa/mkdfa.pl /var/www/HAL/julius/single

sudo ~/julius-4.3.1/gramtools/mkdfa/mkdfa.pl /var/www/HAL/julius/kaden

sudo ~/julius-4.3.1/gramtools/mkdfa/mkdfa.pl /var/www/HAL/julius/zatsudan

で、それぞれの辞書ファイルが作成されます。

あとは、Julius について、この辞書ファイルをカンマ区切りで列挙して起動します。

sudo julius -C /home/pi/julius-kits/grammar-kit-v4.1/hmm_mono.jconf -input mic -gram /var/www/HAL/julius/single,/var/www/HAL/julius/kaden,/var/www/HAL/julius/zatsudan -nostrip -nolog -module &

(-nostrip はエラーログの出力を抑制するオプション。-nolog は Julius のログ出力を抑制するオプション。-module は、HAL で利用するためにモジュールモードで起動するためのオプション。 & はバックグラウンドで実行)

OpenJTalk を使ってしゃべらせる

ソケットサーバー「HAL」では、OpenJTalk を使った「テキスト→音声ファイル生成→生成された音声ファイルの再生」のプロセスをラップした Voice クラスが付属しています。このため、どこからでも

Voice::say($dto, $filename, $word);

とする事で、Raspberry Pi にしゃべらせる事ができます。例えば、 Voice::say($dto, "hello", "こんにちは"); のようになります。

第一引数の $dto は、ソケットサーバー「HAL」内でデータの伝達を行うコンテナオブジェクトです。第二引数の hello は何でも構いません。ここで指定した文字列で

/var/www/HAL/voice

内に、第三引数で指定した言葉を発声する音声ファイル(.wav)を生成します。つまり上記では hello.wav が生成されます。最後に、この生成した .wav ファイルを再生します。

また、同時に 第二引数.txt というテキストファイルも生成され、その中身は第三引数で指定した文字列です。

これにより、次回の Voice::say() メソッド呼び出しで 第二引数.txt ファイルの内容が第三引数の文字列と同じであれば音声ファイルの生成は行われず、既存の 第二引数.wav ファイルを再生します。

冒頭の YouTube 動画で「ちょっと疲れたよ」と言った後に少し間があったのは、新しい音声ファイルを作成していたために少し時間がかかっているのです。

Julius を使った音声認識

Julius の音声認識結果は voice_client.php を通して HAL の juliusActions.php に伝えられます。juliusActions.php の JuliusActions クラスの冒頭には現在、定数として CONVERSATION という配列が定義されています。(2016/08/13追記 version 1.3 までです。1.4 からは action 定義ファイルが YAML ファイルとして外部に分離されました)

const CONVERSATION = array(
array("type" => "\Aだ(。|、)?", "class" => "Noise", "method" => "ignore"),
array("type" => "ハルを?終了", "class" => "Kill", "method" => "exec"),
array("type" => "電気を?つけて", "class" => "Light", "method" => "light_on"),
array("type" => "電気を?消して", "class" => "Light", "method" => "light_off"),
array("type" => "豆を?つけて", "class" => "Light", "method" => "light_bulb"),
array("type" => "弱く?つけて", "class" => "Light", "method" => "light_low"),
array("type" => "(今日)?は?疲れた(よ|ね)?", "class" => "Chat", "method" => "chat_tired"),
array("type" => "(今日)?は?暑い(よ|ね)?", "class" => "Chat", "method" => "chat_hot"),
array("type" => "(今日)?は?寒い(よ|ね)?", "class" => "Chat", "method" => "chat_cold"),
array("type" => "ありがとう?", "class" => "Chat", "method" => "chat_thanx"),
array("type" => "おはよう?", "class" => "Chat", "method" => "chat_good_morning"),
array("type" => "(声|音量)を?小さく", "class" => "Volume", "method" => "volume_wisper"),
array("type" => "(声|音量)を?大きく", "class" => "Volume", "method" => "volume_loud"),
);

type は、Julius の音声認識結果のパターン定義で、正規表現になっています。class と method はパターンマッチした場合に実行されるクラスとメソッド名です。このクラスとメソッドは自由に作成し、

/var/www/HAL/actions

内に配置して下さい。なお、このディレクトリはオートロードの対象となっているため、クラスファイルを個別に require する必要はありません。クラス名と同じ名前の .php ファイルを作成して配置して下さい。既存のファイルを参考にして下さい。

以下に、簡単な正規表現の説明を行います。詳しくは「正規表現」で google 検索等を行って下さい。

\A - 行頭

\z - 行末

(a|b|c) - a または b または c。幾つでも列挙可能

? - 直前の文字が存在しないか、その文字が存在する場合マッチ。たとえば "おはよう?" は、"おはよ" と "おはよう" にはマッチするが "おはよわ" にはマッチしない。

アナログ/デジタル・コンバーターでのアナログ信号入力

MCP3208 は、アナログ信号をデジタルの信号に変換してくれます。足が 16 本あるのですが、半円形の切り欠きがある方を上にして右側 8 本が電源系統と通信(SPI通信)を行う部分で、左側 8 本が、アナログ信号を入力する部分です。

つまり、この MCP3208 だけで、最大 8 個のアナログデバイスの値を読み取れるわけです。

このセンサー部分はチャンネル 0 から始まっていて、上記回路 では一番最後のチャンネル 7 に CdS セルを繋いでいます。CdS セルは、照射される光の強さで抵抗が変わる半導体で、明るいほど抵抗値が下がるセンサーです。

ソケットサーバー「HAL」には SPI 通信を使って 12 bit の ADコンバーターの信号を読み取るための ReadADC クラスが含まれており、

ReadADC::exec($ch, $raw = false);

で、プログラムのどこからでも値を取得できます。$ch は検査するチャンネルなので、今回、CdS セルを CH7 に繋いでいますから、ここでは 7 を指定します。

/var/www/HAL/actions/Light.php

を見るとわかりますが、実際には冒頭で

const CDS_CH = 7;

のように定数としてチャンネルを定義して利用しています。

ReadADC::exec() の第二引数は boolean で指定し、false を指定すると 0~100 までの割合(%)の浮動小数点型、true を指定すると 12bit で示される 10 進数、つまり 0 ~ 4,095 までの整数型が得られます。デフォルトは false です。

Light.php では、「赤外線リモコンの学習」で学習させた赤外線リモコンデータの送信を行っていますが、同時に CdS からの明るさデータを検査し、リモコンデータを送信したにも関わらず明るさが変化していない時は失敗したと判断し、最大で Light::RETRY 回のリトライを行うようになっています。

こんなことも出来ます。

少し手を加えてみました。(version 1.3 のサンプルコードには入っていません)

こうすれば、音声で再生するジュークボックスが作れます。ただ、再生を行っている最中は音声による入力をするわけには行かないので、曲が終わるまで待たなければなりません。

ですから、タクトスイッチ等を導入して手動で止められるようにするか、WEBアプリなどからソケット経由で音声を停止するようにする必要がありそうです。

半固定抵抗の導入

(2016/08/01 追記)

半固定抵抗を導入して、Volume をコントロール出来るようにしてみました。30KΩの半固定抵抗の変化を A/D コンバーターの MCP3208-CI/P で読み取って

sudo amixer set PCM {$dto->volume}%

しているだけですが、アナログからの読み取りなのでダイヤルが止まっていても 1% 程度のブレが生じて、上記コマンドが断続的に発生してしまうため、直近のボリュームを DTO オブジェクトに保存しておいて、2% よりも大きい変化がない場合はコマンドの発行をしないようにしてあります。

曲の停止にはタクトスイッチを使っても良かったのですが、面倒なので Volume を 0 に絞ると曲が止まるようにしました。あんまりインターフェイスがたくさんあるよりは、こっちのほうがシンプルかと思います。

利用した半固定抵抗は音楽機材用と思われる大きめのもので 400 円ほどしました。それからダイヤルも同様に 400 円ほど、筐体用の金具が 200 円くらい、Vcc、GND、A/D コンバーターに繋ぐリード線も含め、これだけで 1000 円以上かかってしまっています。精度はあまりなくても全然構わないので、可能であればジャンクショップ等で揃えたほうがよさそうですね。

カップラーメンタイマー実装

(2016/08/01 追記)

冗談機能として、カップラーメンタイマーを追加してみました。間が持たないので曲を再生していますが、勿論、曲を流す必要はありません。

どん兵衛タイマーも作ってみました。

データベースと連動した温度計

(2016/08/06 追記)

気温データベースを作ってみよう!(温度の記録と確認) で記録した気温データベースを併用して、前日の同時刻と現在の温度を比較する処理を入れてみました。

天気予報

Livedoor さんの Livedoor天気予報 から任意の地域の天気予報を取得して、それを OpenJTalk で読み上げています。

(2016/08/23 追記)

NHK さんの NHKオンライン の RSS から記事を取得して OpenJTalk で読上げを行っています。

多言語対応

多言語対応への対応も行っています。Julius には英語の音響モデルが含まれていないため英語の音声認識をするには独自の音響モデルを作成する必要があります。このため、近い将来的に Google Cloud Speech API を併用できるように機能拡張する予定です。

アレンジ

まとめ

今回は Raspberry Pi ロボット化のとっかかりとして、学習した赤外線リモコンの信号を音声により送信するところまでをご紹介しました。

第二回は温度センサーや人感センサーを使って、もう少し Raspberry Pi を賢くしてみたいと思います。

最後に、今回の回路で使われている部品や回路の詳細については、こちらの本で詳しく説明されています。

何しろ、30年くらい前の中学の時に少し電子回路をいじっただけだった私でも、Raspberry Pi とブレッドボードさえ使えばそれなりに電子工作ができるようになったのはこの本のお陰ですので、これから始めてみようという人にはとてもお勧めです。

同じシリーズで、

が続々と刊行されていますが、ソケットサーバー「HAL」他のプログラム制作にかかりきりでなかなか読んでいる時間がありません。購入はしてあるので、早く余裕が欲しいです…


ご購入

もう少々お待ち下さい。

体験版

version 1.5 から、IPアドレス制限が無くなり、ライセンス制になりました。ライセンスされていない場合、起動後30時間後に自動的に HAL を終了します。

体験版のインストーラー・スクリプトをダウンロード インストーラー・スクリプト
SHA-1: dd2a390b4f0f8c15301eaee23cd92bd5e831da91
※インストール方法については ソケットサーバー「HAL」の概要 (version 2.0対応版)~導入方法 を御覧ください。

体験版パッケージ
HAL_trial_2_0.tar.gz | version 2.0 | SHA-1: ce31802a5b423a9b0d73721a3d43e0585b009a6f
試用期限 2017/1/31 まで

この記事へのコメント

※現在コメントはMarkdown記法が強制です。>>Markdown の書き方


この記事に返信

このコメントに返信