0

arduino_firmata gemでサーボモーター動かせるようになった

Arduino Firmata on Ruby

前:RubyからArduinoを操作できるようにFirmataプロトコルを移植した



動くようになった。
PWMが出せるDigital 11ピンに接続したサーボをランダムに1秒おきに動かす例

#usr/bin/env ruby
require 'rubygems'
require 'arduino_firmata'

arduino = ArduinoFirmata.connect

loop do
angle = rand 180
puts "servo angle #{angle}"
arduino.servo_write 11, angle
sleep 1
end

Arduino#servo_write(pin, angle)が使えるようになった。
Arduino#analog_write(pin, value)を使えば動かせたんだけど、FirmataがServo.hを読み込んでてArduino本体と同じく角度指定で動かせるAPIをだしていたので、そっちを使うようにした。


analog_writeととservo_writeの違い

FirmataとServo.hのコードを読んでみると、Firmataプロトコルでanalog_write 0~180を送って、そのピンがPWMモードではなくSERVOモードだった場合は0~180をPWM出力値ではなく角度指定値として扱うようになってた。
通信だけ見ると0~180までのanalog_write指令を送っているのに、Arduino側でモードに合わせて0~255にマッピングして動くという面白い仕様だった。

servo_writeは最終的にArduinoのServo.hのServo.write()を呼ぶようになってる。

0

RubyからArduinoを操作できるようにFirmataプロトコルを移植した

Javaから移植した
Arduino Firmata on Ruby

インストール

gem install arduino_firmata
Ruby 1.8.7と1.9.2で動作確認してる。serialport gemを使ってるのでJRubyでは動かない。


できること・使い方

RubyからArduinoのデジタル・アナログの入出力が使える。

例えばTwの内部APIと温度センサLM35DZと組み合わせると、9行で温度をtweetできたりして便利。
#usr/bin/env ruby
require 'rubygems'
require 'arduino_firmata'
require 'tw'

arduino = ArduinoFirmata.connect "/dev/tty.usbmodem621"
puts temp = arduino.analog_read(1)*100*5/1024 # 摂氏1度毎に10mV出力なので計算する
client = Tw::Client.new
client.auth "shokai"
client.tweet "現在の温度 #{temp}度"


あとはSinatraと組み合わせて20行ぐらいでブラウザからArduino動かしたりとかもできる



Firmataとは


http://firmata.org
Firmata(ふぁるまーた)はProcessingからArduinoを制御するために5年ぐらい前に作られたプロトコルだ。

Arduinoに Firmataファームウェア を書き込むと、USBシリアル通信経由でパソコンとやりとりしてIOを操作したり色々やってくれる。
プログラムを書く側はArduinoのコードを書いたりパソコンとの通信を意識したりする必要が無くなり、
手元のRubyやProcessingだけを書けば済むのでとても楽になる。
ただし、通信する分だけ遅くなるので超細かくモーターを制御する等には向いていない。


Processing以外にもMax/MSPやopenFrameworksなど色々なプログラミング言語からArduinoを制御する時に使われるようになったり、
また逆に、Arduino以外のボード(Funnel IOなど)をProcessingから制御するのにも使われてたりしている。

いろんな言語とボードを接続するのに便利なプロトコルなのだが、
PhidgetsがあるんだからArduinoはスタンドアロンで使うべきじゃないの?という印象だった。2週間前までは。

八王子の山奥のopenFrameworksセミナーで使ったGrove Systemが拡張パーツの多さ・入手の容易さ・自分で拡張しやすいという点でPhidgetsを食ってしまっていたので、Rubyでも使いたくなった。
つまり Ruby+Firmata+Arduino+GroveSystem 最強なのでは。全部オープンソースだし。

実装はそんなに難しくなくて昨日お風呂にはいる時間を削って作ってみたらすぐ動いたのでgemにした。
Arduino playground – Processing にあったJavaのFirmataライブラリをまるごとRubyで書きなおした。


Rubyっぽい書き方


せっかくRubyで書いてるので使いやすいAPIにしたい。

デバイス名を省略してconnectしても適当に探して接続したりとか、
ADコンバータにcallback登録できるようにしてみた。
arduino = ArduinoFirmata.connect

arduino.on_analog_changed 0 do |value|
puts "analog pin 0 changed #{value}"
arduino.analog_write 11, value
end

ブロックを使うと、arduino.analog_readをanalog_readだけに省略できたりとか
ArduinoFirmata.connect do
puts "firmata version #{version}"

30.times do
an = analog_read 0
analog_write 11, an
sleep 0.01
end
end


簡単なチュートリアルも Arduino Firmata on Ruby に書いたし、
今後も機能追加するので(未実装のon_digital_changed等)見ると良いと思います。