Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Arduino を PHP で制御する
@oasynnoum
PHPカンファレンス関西2014
自己紹介
● @oasynnoum
● PHP が好きです
● 物を動かせるものに惹かれます
● シリアルポートを制御するモジュール
– http://sandbox.n-3.so/Gorilla/
● USB制御するモジュール(libusbラ...
まとめ
firmata プロトコルを実装した PHP ライブラリ、
PHPMakeFirmataを使えば
ArduinoとWebを連携させたアプリが
簡単にPHPで作れる!
Arduino を PHP で制御する
ご清聴ありがとうございました
m(_ _)m
終
お話したいこと
● firmataとは
これの次に述べる PHPMakeFirmata API の根底を理解して
もらう目的で firmata プロトコルを少し細かく説明
– PHPのカンファレンスで話す内容としては不適切かもしれ
ません。PH...
firmata プロトコル概要
● firmata はPCのようなホストマシンから Arduino の
ようなデバイスを制御するためのプロトコル
● firmata はシリアル通信の上のアプリケーションプ
ロトコル
firmata プロトコル概要
● ホストからデバイスにリクエストを出し、
デバイスはそれに応じ動作し、必要に応じて
レスポンスを返す
– 必ずしも「リクエスト対レスポンス」ではない
● デバイスが断続的にピンの状態を通知したり
● ホストから...
firmata プロトコル概要
● 最大0xF個のデジタルポートをサポート
– 一つのポートは8個のデジタルピンを持つ
– つまり最大128個のデジタルピンをサポート
● 最大0xF個のアナログ入力ピンをサポート
firmata プロトコル概要
● 用途(メリット)
– もっとお手軽プロトタイピング(スクリプティング)
● ホスト側でプログラムを書ければ言語は何でもいい
● あるデバイスが firmata を実装しているとわかれば、その
デバイス専用のプ...
StandardFirmata 概要
● Firmata のデータ形式は大雑把に
– シンプルな固定長のコマンド
– 可変長データを内包するコマンド(SysEx)
● #define START_SYSEX 0xF0
● #define END...
StandardFirmata 概要
● リセット時、デバイスから特定のメッセージが送られる
● デバイス初期化実装例
https://github.com/firmata/arduino/blob/45c67d3c18351d23eb979b...
ファームウェア情報の取得
● REPORT_FIRMWARE
– #define REPORT_FIRMWARE 0x79
– pack('C3',
START_SYSEX,
REPORT_FIRMWARE,
END_SYSEX);
● ファー...
ピンの機能を調べる
● デバイスに存在するピン一つ一つについて、
それが持つ機能を返す
● つまり、ピンの総数とピンそれぞれの機能がこのコ
マンドでわかる
● CAPABILITY_QUERY
– #define CAPABILITY_QUER...
ピンの機能を調べる
● 定義されている Capability は次の通り
– digital input
– digital output
– analog read
– PWM
– servo
– I2C
● このコマンドはGUIアプリケーシ...
デジタル出力
● 3バイトのコマンド
● 先頭バイトは DIGITAL_MESSAGE|ポート番号
– 下位4bitはポート番号
– #define DIGITAL_MESSAGE 0x90
– $n番目のピンがあるポート番号は floor($...
デジタル出力
● 1バイト目例:0x90|1
– ポート1に対するデジタル出力
● 2バイト目例:01011011
– 最上位ビットは 0 固定
– 最下位ビットから順にポート中のピン番号 0 ~ 6 の状態を示す
● 3バイト目例:00000...
デジタル入力
● ポートの状態を監視し、変化があれば通知する
– 読み出さないとバッファにどんどんデータが溜まっていく
– 入力を受け取るアプリの場合、
この理由でポーリングが必要になる
● REPORT_DIGITAL
– #define R...
デジタル入力
● 2バイトのコマンドで監視、または監視をやめるポートを指定
● 1バイト目は REPORT_DIGITAL|ポート番号
– 下位8bitはポート番号
– 特定のピンの状態だけ教えてくれればいいよという訳にはいかない
– 5ピンは...
デジタル入力
● 指定したポート中のピンに状態変化があった場合
3バイトのデータを受け取る
● データの形式はデジタル出力のコマンドと同じ
アナログ入力
● デバイスがアナログピンの状態を監視し、変化があれば
通知する
● 監視要請のコマンドの形式は
デジタル入力のそれとほぼ同じ
● #define REPORT_ANALOG 0xC0
● pack('C2', REPORT_AN...
アナログ入力
● 指定したアナログピンに状態変化があった場合
3バイトのデータを受け取る
● 1バイト目は監視要請のコマンドと同じ
– REPORT_ANALOG|ピン番号
● 2バイト目はピンの状態(値)の下位7bit
● 3バイト目はピンの...
その他主要コマンド
● PWM(アナログ出力)
– 単位時間あたりのピンがHIGHとなる時間を調整し、
デジタル(二値的)なピンにアナログ(多値的)な振舞をさ
せる
● Servo
– 特別な場合の PWM コマンド
● I2C
– 他のデバイ...
PHPMakeFirmataについて
● Firmataのホスト側実装
● 先に述べたプロトコルの詳細を隠蔽
– PHPMakeFirmataDevice が対象のデバイスを表現
● コンストラクタは Capability チェックなど、まず必...
PHPMakeFirmataについて
● WebSocket の機能(余計なお世話)
– Ratchet との連携により WebSocket サーバーの機能
も提供
– フレームワークユーザーがピン監視のポーリングと
Ratchet が提供する...
PHPMakeFirmataについて
● ホスト側実装のキモは parser だと思う
– バッファはデジタルピン、アナログピンの状態通知など
色々なデータが混じる
● 例えば REPORT_FIRMWARE のクエリを投げた
直後に受け取るバ...
導入
● Composer で簡単に firmata プロジェクト作れる!
しかし、依存の PHPMakeSerialPort は拡張モジュール
なのでこれを先に手動でインストールする必要がある
– ちなみに、先に上げた carica-firm...
LEDを点滅させよう(Lチカ)
● 要約:
– Device のインスタンスを作って、 digitalWrite() をコール
– http://qiita.com/oasynnoum@github/items/91aed309bd9de8af...
デジタル入力を読む
● コードは少し長いので省きました
– http://qiita.com/oasynnoum@github/items/cd9f90cfec8c0
18a47c6
を参照してください
● $dev->setPinMode(1...
デジタル入力を読む
● デバイスから送られる通知を取得するため、
なるべく短い時間間隔でバッファを確認する必要がある
(ポーリング)
– このポーリングの事をデバイスループと呼んでます
– デバイスループに入るには Device の
run()...
デジタル入力を読む
● LoopDelegate
– デバイスループ以降何も出来なくなることを回避するため用
意されたインターフェース
– このインスタンスを run() の引数に渡す
– LoopDelegate の tick() メソッドは...
アナログ入力を読む
● デジタル入力とほぼ同じです
● ただし、 PinObserver のインスタンスは
addAnalogPinObserver() メソッドで Device に渡
します
● $dev->setPinMode(13, PH...
PWM(アナログ出力)
● $dev->setPinMode(13, PHPMakeFirmata::PWM);
● Device の analogWrite() をコールします
● 第一引数はピン、第二引数は値
● 第二引数の値のとり得る範囲...
デモ1
● firmata-websocket-taste
– https://github.com/PHPMake/firmata-websocket-taste
– Taste は test のタイポ。
面白いと思ったのでそのままにしていま...
デモ2
● firmata-space-travel
– https://github.com/PHPMake/firmata-space-travel
● Arduino でしょぼい宇宙船制御コンソール
● phoria.js でなんちゃって...
PHPMakeFirmata の課題
● firmata のメリットはそのままにデメリットを減じたい
– デメリット
● ホストとデバイスはケーブルで繋がる必要がある
● ホストが無いと何も出来ない
– 普通に Wiring 使えば?というのは...
参考資料
● firmata.org
– http://firmata.org/wiki/Main_Page
● firmata/arduino
– https://github.com/firmata/arduino
● Arduino Un...
Upcoming SlideShare
Loading in …5
×

Arduino を PHP で制御する

4,835 views

Published on

Firmata はシリアル通信を介してPC等のホストマシンから Arduino やその他マイコンボード等のデバイスを制御するためのプロトコルです。
\PHPMake\Firmata は Firmata の PHP ライブラリです。

Published in: Technology
  • Be the first to comment

Arduino を PHP で制御する

  1. 1. Arduino を PHP で制御する @oasynnoum PHPカンファレンス関西2014
  2. 2. 自己紹介 ● @oasynnoum ● PHP が好きです ● 物を動かせるものに惹かれます ● シリアルポートを制御するモジュール – http://sandbox.n-3.so/Gorilla/ ● USB制御するモジュール(libusbラッパー) – http://oasynnoum.hatenablog.com/entry/2013/03/22/013251 ● CD,DVDドライブを(☝ ՞ ՞)☝ ™ウイーンਊ するモジュール – https://github.com/oasynnoum/php-eject – http://eject.kokuda.org/ ● 工作の腕はお察し下さい
  3. 3. まとめ firmata プロトコルを実装した PHP ライブラリ、 PHPMakeFirmataを使えば ArduinoとWebを連携させたアプリが 簡単にPHPで作れる!
  4. 4. Arduino を PHP で制御する ご清聴ありがとうございました m(_ _)m 終
  5. 5. お話したいこと ● firmataとは これの次に述べる PHPMakeFirmata API の根底を理解して もらう目的で firmata プロトコルを少し細かく説明 – PHPのカンファレンスで話す内容としては不適切かもしれ ません。PHP関係なさすぎて ● PHPMakeFirmata について – 導入方法 – API – デモ
  6. 6. firmata プロトコル概要 ● firmata はPCのようなホストマシンから Arduino の ようなデバイスを制御するためのプロトコル ● firmata はシリアル通信の上のアプリケーションプ ロトコル
  7. 7. firmata プロトコル概要 ● ホストからデバイスにリクエストを出し、 デバイスはそれに応じ動作し、必要に応じて レスポンスを返す – 必ずしも「リクエスト対レスポンス」ではない ● デバイスが断続的にピンの状態を通知したり ● ホストから一方的にピンの状態を変化させたり ● 通信データの形式は MIDI メッセージ形式 ● 色々なデバイス側の実装がある – https://github.com/firmata
  8. 8. firmata プロトコル概要 ● 最大0xF個のデジタルポートをサポート – 一つのポートは8個のデジタルピンを持つ – つまり最大128個のデジタルピンをサポート ● 最大0xF個のアナログ入力ピンをサポート
  9. 9. firmata プロトコル概要 ● 用途(メリット) – もっとお手軽プロトタイピング(スクリプティング) ● ホスト側でプログラムを書ければ言語は何でもいい ● あるデバイスが firmata を実装しているとわかれば、その デバイス専用のプログラマ(ライター)・IDE等が無くてもいい – ホストとデバイスが協調動作するようなアプリ開発 – 場合によってはホストから電源が供給される ● デメリット – ホストとデバイスはケーブルで繋がる必要がある ● firmata over XBeeとかアイディアはあるらしい・・・ – ホストが無いと何も出来ない ● 単にデバイスだけを動かせばいいようなアプリの場合、 ホストの計算資源を要求するため無駄が多い
  10. 10. StandardFirmata 概要 ● Firmata のデータ形式は大雑把に – シンプルな固定長のコマンド – 可変長データを内包するコマンド(SysEx) ● #define START_SYSEX 0xF0 ● #define END_SYSEX 0xF7 に分けられる ● ホストからの接続時にデバイスの状態がリセットされ る
  11. 11. StandardFirmata 概要 ● リセット時、デバイスから特定のメッセージが送られる ● デバイス初期化実装例 https://github.com/firmata/arduino/blob/45c67d3c18351d23eb979bc2 ff32537dac180560/Firmata.cpp#L66 void FirmataClass::begin(long speed) { Serial.begin(speed); FirmataSerial = &Serial; blinkVersion(); printVersion(); printFirmwareVersion(); }
  12. 12. ファームウェア情報の取得 ● REPORT_FIRMWARE – #define REPORT_FIRMWARE 0x79 – pack('C3', START_SYSEX, REPORT_FIRMWARE, END_SYSEX); ● ファームウェア名(StandardFirmata.ino)と、 バージョン番号がレスポンスとして返ってくる ● ただし、この情報は前述したリセット時の特定のデータに 含まれるため、このクエリを発行する場面は稀
  13. 13. ピンの機能を調べる ● デバイスに存在するピン一つ一つについて、 それが持つ機能を返す ● つまり、ピンの総数とピンそれぞれの機能がこのコ マンドでわかる ● CAPABILITY_QUERY – #define CAPABILITY_QUERY 0x6B – pack('C3', START_SYSEX, CAPABILITY_QUERY, END_SYSEX);
  14. 14. ピンの機能を調べる ● 定義されている Capability は次の通り – digital input – digital output – analog read – PWM – servo – I2C ● このコマンドはGUIアプリケーションの初期化時に有用 – ピンの数、機能に応じたコントロールを配置する
  15. 15. デジタル出力 ● 3バイトのコマンド ● 先頭バイトは DIGITAL_MESSAGE|ポート番号 – 下位4bitはポート番号 – #define DIGITAL_MESSAGE 0x90 – $n番目のピンがあるポート番号は floor($n/8) ● ピン番号を8で割り、端数を切り捨て ● つまりピンは8毎にグループ化される ● 6番目のピンはポート0に、13ピンはポート1にある ● 2バイト目、3バイト目はポート中のピン状態を示す
  16. 16. デジタル出力 ● 1バイト目例:0x90|1 – ポート1に対するデジタル出力 ● 2バイト目例:01011011 – 最上位ビットは 0 固定 – 最下位ビットから順にポート中のピン番号 0 ~ 6 の状態を示す ● 3バイト目例:00000001 – 最上位ビットから2ビット目まで 0 固定 – 最下位ビットはポート中のピン番号 7 の状態を示す ● ポート 0 に対し偶数ピンをHIGHにするコマンド ● pack('C3', 0x90|0, 0b00101010, 0b00000001);
  17. 17. デジタル入力 ● ポートの状態を監視し、変化があれば通知する – 読み出さないとバッファにどんどんデータが溜まっていく – 入力を受け取るアプリの場合、 この理由でポーリングが必要になる ● REPORT_DIGITAL – #define REPORT_DIGITAL 0xD0
  18. 18. デジタル入力 ● 2バイトのコマンドで監視、または監視をやめるポートを指定 ● 1バイト目は REPORT_DIGITAL|ポート番号 – 下位8bitはポート番号 – 特定のピンの状態だけ教えてくれればいいよという訳にはいかない – 5ピンはポート0に属するので、5ピンの状態が欲しい場合、そのポートの他 のピンの状態変化の通知も受け取ることになる ● 2バイト目は真偽値、0もしくは1 – 1で状態通知お願いします – 0で状態通知、もう結構です ● pack('C2', REPORT_DIGITAL|0, 1); – ポート0に属するピンの状態を通知
  19. 19. デジタル入力 ● 指定したポート中のピンに状態変化があった場合 3バイトのデータを受け取る ● データの形式はデジタル出力のコマンドと同じ
  20. 20. アナログ入力 ● デバイスがアナログピンの状態を監視し、変化があれば 通知する ● 監視要請のコマンドの形式は デジタル入力のそれとほぼ同じ ● #define REPORT_ANALOG 0xC0 ● pack('C2', REPORT_ANALOG|1, 1); アナログピン1の状態を監視させる ● デジタル入力同様、読み出さないとバッファにデータが 蓄積されていく
  21. 21. アナログ入力 ● 指定したアナログピンに状態変化があった場合 3バイトのデータを受け取る ● 1バイト目は監視要請のコマンドと同じ – REPORT_ANALOG|ピン番号 ● 2バイト目はピンの状態(値)の下位7bit ● 3バイト目はピンの状態(値)の上位7bit ● $pinState = (($first << 7) | $second) & 0xFF
  22. 22. その他主要コマンド ● PWM(アナログ出力) – 単位時間あたりのピンがHIGHとなる時間を調整し、 デジタル(二値的)なピンにアナログ(多値的)な振舞をさ せる ● Servo – 特別な場合の PWM コマンド ● I2C – 他のデバイス、マイコン等とシリアル通信を行う
  23. 23. PHPMakeFirmataについて ● Firmataのホスト側実装 ● 先に述べたプロトコルの詳細を隠蔽 – PHPMakeFirmataDevice が対象のデバイスを表現 ● コンストラクタは Capability チェックなど、まず必要となりそうなやりとりをデ バイスと行う – digitalWrite(), analogWrite(), ピンを監視する仕組み などをフレームワークとして提供する ● PHP による firmata のホスト側実装は他に https://github.com/ThomasWeinert/carica-firmataがある – 両者の API の違いはピン監視のAPIにおいて interface を用いるの か callable を用いるのか程度 – callable 多用するのが嫌いな人は PHPMakeFirmata を使うといい と思う
  24. 24. PHPMakeFirmataについて ● WebSocket の機能(余計なお世話) – Ratchet との連携により WebSocket サーバーの機能 も提供 – フレームワークユーザーがピン監視のポーリングと Ratchet が提供するイベント駆動の API を組み合わせ て整合性を取りつつ WebSocket アプリを作るのは多 分めんどくさいだろうと思ったので – しかし、 Ratchet の API は少し調べただけなので、 恐らく今のところあまりいい実装ではない
  25. 25. PHPMakeFirmataについて ● ホスト側実装のキモは parser だと思う – バッファはデジタルピン、アナログピンの状態通知など 色々なデータが混じる ● 例えば REPORT_FIRMWARE のクエリを投げた 直後に受け取るバッファ先頭のデータは必ずしも START_SYSEX, REPORT_FIRMWARE, END_SYSEX ではない – 動かない下手くそなパーサーを何度も書いては捨てた – 今のところパーサーは動くが、依然下手くそ
  26. 26. 導入 ● Composer で簡単に firmata プロジェクト作れる! しかし、依存の PHPMakeSerialPort は拡張モジュール なのでこれを先に手動でインストールする必要がある – ちなみに、先に上げた carica-firmata もシリアル通信部分に PHPMakeSerialPort がインストールされていれば使うように なっています ● PHPMakeFirmata のインストールについては http://sandbox.n-3.so/Gorilla/download/ を参照してください ● ArduinoにStandardFirmataを書き込む必要があります http://qiita.com/oasynnoum@github/items/91aed30 9bd9de8af8d0a を参照してください
  27. 27. LEDを点滅させよう(Lチカ) ● 要約: – Device のインスタンスを作って、 digitalWrite() をコール – http://qiita.com/oasynnoum@github/items/91aed309bd9de8af8d0a <?php require dirname(__FILE__) . '/vendor/autoload.php'; /* initialize the device */ $device = new PHPMakeFirmataDevice('/dev/ttyACM0'); /* for Windows */ // $device = new PHPMakeFirmataDevice('COM3'); $pin = 13; for ($i = 0; $i < 3; ++$i) { $device->digitalWrite($pin, PHPMakeFirmata::HIGH); // light sleep(1); $device->digitalWrite($pin, PHPMakeFirmata::LOW); // unlight sleep(1); }
  28. 28. デジタル入力を読む ● コードは少し長いので省きました – http://qiita.com/oasynnoum@github/items/cd9f90cfec8c0 18a47c6 を参照してください ● $dev->setPinMode(13, PHPMakeFirmata::INPUT); ● 監視したいピンを reportDigitalPin() で指定する – 前述のとおり、プロトコル自体はポート単位で監視・通知を行 うがフレームワークがそこを隠蔽しピン単位での監視・通知を 行う ● PinObserver を実装し、そのインスタンスを Device に addDigitalPinObserver() で渡す – ピン変化通知を notify() で受け取る
  29. 29. デジタル入力を読む ● デバイスから送られる通知を取得するため、 なるべく短い時間間隔でバッファを確認する必要がある (ポーリング) – このポーリングの事をデバイスループと呼んでます – デバイスループに入るには Device の run() メソッドをコールします ● 引数については後述 ● デバイスループに入ると処理はそこでブロックされる – run() 呼び出しの後に続くコードブロックが実行されるのはデ バイスループが終了したあと – このままだとフレームワークユーザーは何も出来ない
  30. 30. デジタル入力を読む ● LoopDelegate – デバイスループ以降何も出来なくなることを回避するため用 意されたインターフェース – このインスタンスを run() の引数に渡す – LoopDelegate の tick() メソッドはそのループの間隔ごとに コールされます – getInterval() メソッドはループの間隔を定義します ● デバイスループが実行される最初にだけ Device 内部でコールさ れます ● デバイスループを止めるには Device の stop() をコー ルします – 典型的には tick() 内から stop() とか
  31. 31. アナログ入力を読む ● デジタル入力とほぼ同じです ● ただし、 PinObserver のインスタンスは addAnalogPinObserver() メソッドで Device に渡 します ● $dev->setPinMode(13, PHPMakeFirmata::ANALOG);
  32. 32. PWM(アナログ出力) ● $dev->setPinMode(13, PHPMakeFirmata::PWM); ● Device の analogWrite() をコールします ● 第一引数はピン、第二引数は値 ● 第二引数の値のとり得る範囲は 0~上限値 ● 上限はデバイス、ピンにより異なる ● Capability により定義されている – $capability = $dev->getPin(13)->getCapability(); $pwmResolution = $capability->getResolutionPWM();
  33. 33. デモ1 ● firmata-websocket-taste – https://github.com/PHPMake/firmata-websocket-taste – Taste は test のタイポ。 面白いと思ったのでそのままにしています。 ● firmata.org が提供しているテストGUIアプリがUbuntuで動かな かったため作った ● バグっぽいです ● Onsenui で作った – http://onsenui.io/ ● Onsenui は素晴らしい。 このデモがバグっぽいのは実装者のせい ● ピンモードを変えられるようにと思ってセグメントコントロールをつ けましたが、今のところ実装していません
  34. 34. デモ2 ● firmata-space-travel – https://github.com/PHPMake/firmata-space-travel ● Arduino でしょぼい宇宙船制御コンソール ● phoria.js でなんちゃって太陽系 – http://www.kevs3d.co.uk/dev/phoria/ – phoria.js は悪くない。悪いのは実装者の腕
  35. 35. PHPMakeFirmata の課題 ● firmata のメリットはそのままにデメリットを減じたい – デメリット ● ホストとデバイスはケーブルで繋がる必要がある ● ホストが無いと何も出来ない – 普通に Wiring 使えば?というのは無し ● 俺はぺちぱーだ! ● Wiring(Arduinoの開発言語というかフレームワーク) ● ドキュメントが無い – 申し訳程度の Janglish で書かれた phpdoc オンリー
  36. 36. 参考資料 ● firmata.org – http://firmata.org/wiki/Main_Page ● firmata/arduino – https://github.com/firmata/arduino ● Arduino Uno/Leonardo で始める電子工作 – http://www.amazon.co.jp/dp/4877832963

×