はじめに
にて、Intel EdisonにてWebカメラを有効にし、mjpg-streamerで映像を配信してみました。
今回は、Intel Edisonを使ったデモとして、そのWebカメラにサーボモーターを2つ取り付け、Web経由でパン・チルト(水平方向と垂直方向)を制御してみました。
全体像は下図のようになります。カメラの他は、Intel Edison Breakout Board、レギュレータやレベルシフタを含む周辺回路、バッテリー(Eneloop Pro6本)が見えます。
コントローラーはPC、タブレット、スマートフォンなどのブラウザです。
動作状況の動画はこちらになります。
VIDEO
カメラ雲台の準備
カメラとサーボモータ2つを接続する方法ですが、なるべく楽をしたかったので、秋月電子通商にある
を用いました。
この組み立て方は
にあります。これを見るだけでも大変そうなのはわかりますが、実際に手元に届いてみると
ニッパ、ピンバイス、ヤスリによるパーツの加工が必須
必要なネジが全然足りない(と思う)
2つのサーボSG-90の品質が悪く、最初から正常動作しないことがある
のように、なかなか骨のあるキットです。
ちなみにサーボSG-90は秋月やamazonなどでも追加注文できますが、店によってはバージョン違いなのかサーボのケースサイズやサーボホーンの径が異なり、さらに加工が必要になったりします。なお、私の場合、SG-90を計12個入手して、正常動作したものは10個でした。
さらに、このキットに付属するWebカメラはMJPEGモードに対応していないので、「
Intel EdisonでWebカメラを有効にしmjpg-streamerで映像を配信してみた 」で紹介した方法では映像配信できません。
私は手元で余っていた
Logicool C210 を加工して取り付けました。Logicoolのものなら大抵大丈夫だと思います(今にして思えば、もっと画質の良いものにすれば良かったかも)。
回路の接続
作成したカメラ雲台を下図のようにIntel Edisonと接続します。
いくつかコメントします。
USBカメラを使うため、電源は7V~15VをJ21に入力します。バッテリーを用いたかったので、Enelooop6本を用いることにしました。容量の大きいEneloop Proにしましたが、これはお好みで。
サーボモーターは5Vで駆動するため、レギュレータ
TA4805S で5Vを作ります。これは手元にあったものをそのまま用いました。
Intel Edisonからは下記の5つの信号を引っ張りだしました。Intel Edisonを外した状態で、Breakout Boardにケーブルを直接半田づけしました。
J17-1:サーボ用PWM
J18-1:サーボ用PWM
J18-2:GPIO。プルアップされた入力として用いて、シャットダウンスイッチに利用します。
J19-2:1.8V
J19-3:GND
各ピンの情報は
Intel Edison Breakout Board Hardware Guide のPDFファイルを参考にしてください。
サーボモータ用に出力するPWM信号は1.8Vなので、サーボモータに与えるために5Vにレベル変換します。これも手元にあった「
8ビット双方向ロジックレベル変換モジュール 」を用いました。
PCとの接続は、J3のシリアルコンソールにより行います。
libmraaライブラリの準備
ここからはIntel Edison上での作業になります。あらかじめ、「
Intel EdisonでWebカメラを有効にしmjpg-streamerで映像を配信してみた 」に基づいてWebカメラの映像配信を有効にしておいてください。エントリ作成当時はポート8080を用いていましたが、ポート9000を用いるように変更しましたので、ご注意ください。
さて、スイッチサイエンスさんのページ「
Intel Edison opkgのフィードを設定する 」および「
libmraaを使ってC++で開発する 」を参考に、GPIOにアクセスするためのlibmraaライブラリをインストールします。
# vi /etc/opkg/myfeeds.conf
このファイルに下記の内容を記述して保存します。
src intel-iotdk http://iotdk.intel.com/repos/1.1/intelgalactic
src all http://iotdk.intel.com/repos/1.1/iotdk/all
src i586 http://iotdk.intel.com/repos/1.1/iotdk/i586
src x86 http://iotdk.intel.com/repos/1.1/iotdk/x86
書けたら、下記のコマンドを実行します。
# opkg update
# opkg upgrade
# opkg install libmraa0
これでlibmraaのインストールが完了しました。
node.jsで用いるモジュールの準備
node.jsによるWeb連携で用いるconnectモジュールとsocket.ioモジュールをインストールします。
# npm install connect@2.27.4
# npm install socket.io@0.9.17
使っているスクリプトの関係上、バージョンを指定して最新のものではないファイルをインストールしました。
これらのモジュールは/home/root/node_modules以下にインストールされます。
なお、libmraaライブラリに対応するmraaモジュールは/usr/lib/node_modules/mraaとしてインストールされていますが、これを/home/root/node_modulesにリンクしておかないと、自作のnodeスクリプトを/etc/rc.localから起動するときに失敗します。そのため、下記を実行しておきます。
# ln -s /usr/lib/node_modules/mraa /home/root/node_modules/mraa
ソースのダウンロード
ソースのダウンロードのために、gitをインストールします。
# opkg update
# opkg install git
次に、ソースをダウンロードし、pantiltという名前のディレクトリに保存します。
# cd
# git clone https://github.com/neuralassembly/Edison_pantilt.git pantilt
以下、いくつか解説を加えていきます。
シャットダウンスイッチ
シャットダウンスイッチを有効にするためには、下記のコマンドを実行します。
# python /home/root/pantilt/shutdown.py &
この状態で、回路上のタクトスイッチを2~3秒程度長押しすると、poweroffコマンドが実行され、シャットダウンが始まります。
中身は下記のようなPythonプログラムになっています。GPIO15はJ18-2のことであり、プルアップ抵抗つきの入力として設定しています。GPIO番号とピン番号の対応は
こちら を参照。
import mraa
import time
import subprocess
sw = mraa.Gpio(15)
sw.dir(mraa.DIR_IN)
sw.mode(mraa.MODE_PULLUP)
state = 0
while True:
if sw.read() == 0:
if state == 2:
state = 0
args = ['poweroff']
subprocess.Popen(args)
else:
state += 1
else:
state = 0
time.sleep(0.5)
このshutdown.pyスクリプトを起動時に有効にするには、mjpg-streamerの自動起動の際に作成した/etc/rc.localに上記のコマンドを追記してください。
サーバーの起動
サーバーを起動するには、下記のコマンドを実行してください。
# node /home/root/pantilt/pantiltserver.js &
その状態でブラウザで
http://(Intel EdisonのIPアドレス):8080/
にアクセスすると、操作用のアプリが開きます。使用されているポートは下記の通りです。
8080:ページの閲覧
8888:socket.ioによるソケット通信
9000:mjpg-streamerによる映像配信
JavaScriptで記述したpantiltserver.jsの中では、下記のようにJ17-1およびJ18-1ピンに対してPWM信号を出力しています。
var mraa = require('mraa');
var p0 = new mraa.Pwm(0); // J17-1
var p1 = new mraa.Pwm(14); // J18-1
p0.period_us(19500);
p0.enable(true);
p1.period_us(19500);
p1.enable(true);
// For upper servo
var duty0min = 0.03; // min
var duty0max = 0.11; // max
var duty0 = (duty0min + duty0max)/2;
// For lower servo
var duty1min = 0.031; // min
var duty1max = 0.115; // max
var duty1 = (duty1min + duty1max)/2;
p0.write(duty0);
p1.write(duty1);
サーボモータに50Hzの信号を与えるのですが、細かな周期やパルス幅はオシロスコープの波形を見たりサーボモーターの振る舞いを見ながら微調整しました。Duty比は0~1の実数で指定します。
このpantiltserver.jsをIntel Edison起動時に自動実行する場合は、やはり/etc/rc.localに上記コマンドを追記してください。
ブラウザ上のアプリ
ブラウザのアプリは下図のように映像の下と右にjQuery UIによるスライダを配置してサーボモーターへの指令をJavaScriptで送るようにしています。iOSのSafari/ChromeやAndroidのChrome/Firefoxなどで動作を確認しています。画面の回転にも対応しています。
このアプリは、主に下記のファイルで構成されています。
index.html
js/pantilt.js
js/socket.io.js:node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.jsと同じもの
js/jquery/:jQuery UI用ファイル
css/pantilt.css
js/pantilt.js内で、映像の取得と命令の送信を行っています。
展示
終わりに
Intel Edisonを用いた簡単なデモということで、カメラのパンチルトを制御してみました。
mraaモジュールを用いるとJavaScriptで直接GPIOにアクセスできるので、Web連携が容易であるという印象を持ちました。ただし、ドキュメントがあまり充実していないように思われるのが残念なところです(Pythonの入力ピンのプルアップ抵抗を有効にする方法を調べるために、mraaのソースをgrepしたりしました)。そのあたりは今後に期待でしょうか。
あとは、7V以上の電源の確保と1.8VのGPIO入出力のレベルシフトがやや面倒、というところです。
他のボードとの比較で言えば、Raspberry Piで同じことをやろうとする場合、Webカメラでは性能が出ないので、
Raspberry Pi用のカメラモジュールを用いる 必要があります。さらに、Raspberry PiではハードウェアPWMが一つしか使えないので、全く同じことをするのは少し面倒です。
BeagleBone Blackでは全く同じことを実現できるはずですが、私はBeagleBone BlackでのGPIOプログラミングは未経験なのでノーコメントです。
以上でした。