Raspberry PiはそれほどはI/Oが充実していませんしね〜。
以下は回路図のピンヘッダのところ。

回路図にありますように、SPI、I2Cが出てるので、ポートエキスパンダを接続するという手は使えます。
ポートエキスパンダは、例えばこんなのとか。
http://akizukidenshi.com/catalog/g/gI-03708/
とはいえPWMやりたい、とかAD値を取りたいとか、なんてことを手軽な工作で実現するには手間がかかりそうです。
本記事では、上記を解決するアプローチの1つとして、firmataのスケッチを書き込んだArduinoマイコンボードをRaspberry PiのUSBポートに接続し、Raspberry Pi側からArduinoを手足のように使って制御を行なってみる内容になっています。
そんなわけで、ArduinoシールドもRaspberry Piから制御できるようになります。いろいろお持ちの方は資産活用できるかもしれませんね
firmataは、元々PC用のJavaベースの開発環境Processingで、PCに接続したArduinoマイコンボードを制御してフィジカルコンピューティングするものです(と理解してます)。
そこで、firmataのプロトコル http://firmata.org/wiki/Protocol をRaspberryPi側に喋らせる事で、Raspberry Piで手軽にArduinoマイコンボードを制御できるようにする準備をしていきたいと思います。
今回、Raspberry Pi側で使用する言語はRubyにしました。これでRaspberry Pi上のスクリプト言語で、お手軽にスケッチ相当のコードを書いて、フィジカルコンピューティング出来ますね!(たぶん)

さて、今回はArduinoマイコンボードとして最もスタンダードなものの1つである、Arduino Unoを使用しました。
最近スイッチサイエンスさんではこのボード、永久保証されてるようで話題になりました。
Arduinoマイコンボード側の準備
では、これに、Standard Firmataのスケッチを焼きこんでおきましょう。サンプルに用意されています。

Raspberry Pi側の準備
Raspberry Pi側のディストリビューションはRaspbian Wheezyを使用します。その他のLinuxディストリビューションでも多分実施可能かとは思います。Arduno Unoを認識させる為には、USB CDC ACMデバイスを認識できるようにする必要がありますが、Raspbian Wheezyでは標準で認識するようになってます。
●Rubyのセットアップ
今回はRubyとRubyでシリアルポートを制御するruby-serialportを使用します。また、ruby-serialportをセットアップするのにRubygemを使用しますので、以下のようにセットアップするとOKです。
$ sudo apt-get install ruby
$ sudo apt-get install ruby-dev
$ sudo apt-get install rubygems
$ sudo gem install ruby-serialport
ruby-devは、gemでモジュールをインストールする際に必要になる関係でセットアップしています。
では、ライブラリを準備します。
patcoll氏のruby-firmataをベースに、現在のfirmataで使用できるように改造し、改変や機能追加したものを私のgithubで公開しています。
当初そのまま使えるかなと思ってたのですが、ruby-firmataの開発が2年ほど止まっているようで、その間のfirmataの拡張などもあったためでしょうか、そのままでは動作させられませんでした。
改変版は以下にあります。
https://github.com/yishii/ruby-firmata
これを取得します。
下記のようにgitで取得出来ますし、gitを使わない場合、「

git clone https://github.com/yishii/ruby-firmataそれではサンプルコードを用意します。以下のコードは、上述のリポジトリ内にあります、test.rbとなってます。
runメソッドにクラスを渡すとsetupとloopを呼び出すArduino IDEライクなスタイルです。直接Arduinoクラスメソッド呼び出しでの制御もできますので、お好みで。
digital_readやanalog_readメソッドの値は、firmataではレポートが定期的(または変化があった時)にArduino側から送られてきますので、それをパースした結果を返します。本ライブラリでいえば、Arduino::parseを呼び出した内部でArduinoからのレポートを解釈し、内部で記録します。
コードを見ていただくとおわかりになるかと思いますが、内容としては、デジタルピン2番をリードしてデジタルピン13番のHigh/Lowを制御するのと、アナログピン0番をリードしてデジタルピン9番に接続したサーボモーターを制御させています。
require './lib/arduino' class Test def initialize(arduino) @arduino = arduino end def setup @arduino.set_report_interval(100) # アナログ値のレポート間隔 = 100[ms] 短かくし過ぎた場合通信量が大きくなるので注意 @arduino.pin_mode(Arduino::DIGITAL2 , Arduino::INPUT) @arduino.pin_mode(Arduino::DIGITAL3 , Arduino::INPUT) @arduino.pin_mode(Arduino::DIGITAL13, Arduino::OUTPUT) @arduino.pin_mode(Arduino::DIGITAL9 , Arduino::SERVO) @arduino.pin_mode(Arduino::ANALOG0 , Arduino::ANALOG) @arduino.report # デジタル・アナログのレポート開始 end def loop @arduino.parse # レポートを受信して解釈する # デジタルピン2番のLOW/HIGHでデジタルピン13番を制御 if (@arduino.digital_read(Arduino::DIGITAL2) == 0) @arduino.digital_write(Arduino::DIGITAL13,0) else @arduino.digital_write(Arduino::DIGITAL13,1) end # アナログピン0番の入力値を用いてデジタルピン9番のサーボを回転させる val = @arduino.analog_read(Arduino::ANALOG0) @arduino.servo_write(Arduino::DIGITAL9,val >> 2) end end arduino = Arduino.new("/dev/ttyACM0") arduino.run(Test)
/dev/ttyACM0は、Arduino Unoのシリアルポートのデバイススペシャルファイルです。これを介してRaspberry PiからArduino Unoにアクセスします。
テストに使用したのは、ジョイスティックシールド+サーボモーター+LEDです。


使用してるところの動画撮りましたのでどーぞ!
firmataを使用すれば、手軽にRaspberry PiでI/O制御の拡張と、既存Arduinoシールド資産が活用できるので、よかったら是非どうぞー!
ちなみに、今回使用したライブラリはArduino::parseメソッドを呼び出して1バイトずつデータを解釈させるのですが、できれば受信は別スレッドで行わせたほうが扱いやすいように思います。その内また更新して本ブログに掲載させていただこうかなーと思います。
Raspberry Piユーザーガイド
posted with amazlet at 13.04.28
Eben Upton Gareth Halfacree
インプレスジャパン
売り上げランキング: 1,952
インプレスジャパン
売り上げランキング: 1,952
Interface (インターフェース) 増刊 お手軽ARMコンピュータ ラズベリーパイでI/O 2013年 04月号 [雑誌]
posted with amazlet at 13.04.28
CQ出版 (2013-03-29)
Raspberry Pi Type B 512MB
posted with amazlet at 13.04.28
RS Components Ltd
売り上げランキング: 1,915
売り上げランキング: 1,915