小林です
ハイレベルの前にローレベルなお話からですみません。
FirmataでのI2Cなのですが、今の所特にプロポーザルがでていないようですので、この機会に提案してみようかと思っています。とりあえず、たたき台として次のようなものを考えてみましたが、いかがでしょうか?既にこの辺りは試されたところだと思いますので、ご意見など是非お聞かせください。
読み取りに関して、↓の案では一度writeでdata
addressを指定してから読み取りを指定、という普通にI2Cで操作する時の方法に従ったものにしています。これを1個ですませた方が簡便ではあるのですが、最終的にライブラリでラップしてしまうのであれば、できるだけローレベルに近いものにした方が、後々の自由度があっていいかな、とは思っております。
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 read/write (0 => write, 1 => read)
* 3 slave address (7bit)
* 4 data 0 (LSB)
* 5 data 0 (MSB)
* 6 data 1 (LSB)
* 7 data 1 (MSB)
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
example read a sensor value of a slave device
Host => Arduino (1/2)
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 0 (write)
* 3 0x13 (slave address)
* 4 data address to read (LSB)
* 5 data address to read (MSB)
* 6 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
Host => Arduino (2/2)
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 1 (read)
* 3 0x13 (slave address)
* 4 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
Ardino => Host
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 0 (write)
* 3 0x13 (slave address)
* 5 data 0 LSB
* 6 data 0 MSB
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
遠藤孝則
2008/10/19 22:06 Shigeru Kobayashi <koto...@gmail.com>:
--
endo takanori
小林です
了解です。とりあえず、先ほどの案でArduinoのdev
listに投げておきました。SysExですので、独自にインプリして使うというのでも問題ないといえばないのですが、できれば早い段階で標準化された方がいろいろな意味で良いかなぁと思いますので…。
また何か展開があればこちらでもお知らせします。
2008/10/19 takanori endo <sweeta...@gmail.com>:
遠藤孝則
2008/10/19 22:34 Shigeru Kobayashi <koto...@gmail.com>:
--
endo takanori
> Host => Arduino (1/2)
> /* IC2 read/write
> * -------------------------------
> * 0 START_SYSEX (0xF0) (MIDI System Exclusive)
> * 1 I2C (0x76)
> * 2 0 (write)
> * 3 0x13 (slave address)
> * 4 data address to read (LSB)
> * 5 data address to read (MSB)
> * 6 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
> */
これは、I2Cのレジスタに書き込むときのパケットですよね?
書き込む先のアドレスは、4,5に指定しますが、書き込むデータの指定が必要に
なるのではないでしょうか?
4 data address to write (LSB)
5 data address to write (MSB)
6 data 0 (LSB)
7 data 0 (MSB)
8 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
となりますか?
> Host => Arduino (2/2)
> /* IC2 read/write
> * -------------------------------
> * 0 START_SYSEX (0xF0) (MIDI System Exclusive)
> * 1 I2C (0x76)
> * 2 1 (read)
> * 3 0x13 (slave address)
> * 4 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
> */
同様に読み出す先のアドレスが必要で、
4 data address to read (LSB)
5 data address to read (MSB)
6 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
> Ardino => Host
> /* IC2 read/write
> * -------------------------------
> * 0 START_SYSEX (0xF0) (MIDI System Exclusive)
> * 1 I2C (0x76)
> * 2 0 (write)
> * 3 0x13 (slave address)
> * 5 data 0 LSB
> * 6 data 0 MSB
> * ...
> * n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
> */
これは、Arduinoからの返事で、読み込んだ結果を返す時は、
1 I2C (0x76)
2 1 (read)
3 0x13 (slave address)
5 data 0 LSB
6 data 0 MSB
7 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
となるのでしょうか?
ちなみに戻りが2byteの場合は、
7 data 1 LSB
8 data 2 MSB
9 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
という感じになるのでしょうか?
基本的なI2Cの考え方がまちがってたらすいません。
遠藤孝則
--
endo takanori
このサンプルですが、
1. I2Cで読み出したいアドレスを指定(write)
2. I2Cで読み出しを実行
3. 1で指定したアドレスのデータが読み出される
という流れを想定していました。参考にしたのはこちらのページですが、私が勘違いしているかもしれません。
http://wiki.livedoor.jp/yamamaya_com/d/I2C%A5%D0%A5%B9%A4%F2%BB%C8%A4%C3%A4%C6%A4%DF%A4%E8%A4%A6
こちらのサンプルなどの方法だと
http://www.makingthingstalk.com/chapter8/20/
・レジスタのセット
・読み出し
の2つに分かれているのですが、これに加えて書き込みを用意するよりは
・アドレスとレジスタを指定した書き込み
・アドレスとレジスタとバイト数を指定した読み出し
のように用意してしまった方がシンプルでいいでしょうか(恐らく遠藤さんが想定されているのはこれですよね)?デメリットとしては、毎回レジスタを設定するために転送量が増える、ということかなとは思いますが…。整理すると、以下のような感じになるでしょうか?
/* I2C read
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 1 (read)
* 3 slave address
* 4 register to read (LSB)
* 5 register to read (MSB)
* 6 bytes to read
* 7 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
/* I2C read (reply)
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 1 (read)
* 3 slave address
* 4 register (LSB)
* 5 register (MSB)
* 6 data 0 (LSB)
* 7 data 0 (MSB)
* 8 data 1 (LSB)
* 9 data 1 (MSB)
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
/* I2C write
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 0 (write)
* 3 slave address
* 4 register to write (LSB)
* 5 register to write (MSB)
* 6 data 0 (LSB)
* 7 data 0 (MSB)
* 8 data 1 (LSB)
* 9 data 1 (MSB)
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
2008/10/20 takanori endo <sweeta...@gmail.com>:
僕が思っていたのは、
レジスタ読み出し
レジスタ書き込み
という処理でプロトコルを決めるということで、
実際は、レジスタ読み出しにも
> 1. I2Cで読み出したいアドレスを指定(write)
> 2. I2Cで読み出しを実行
> 3. 1で指定したアドレスのデータが読み出される
こういう処理になっていますね。
I2Cに慣れている人はこちらでも問題ない気がします。
確かに毎回レジスタを設定するために転送量が増えるというデメリットがありそうなので、
昨日までの、小林さんの案で、進めたいと思います。
なにか疑問があったらまた聞きますね。
よろしくお願いします
遠藤孝則
、
2008/10/20 22:49 Shigeru Kobayashi <koto...@gmail.com>:
--
endo takanori
小林です
> I2Cに慣れている人はこちらでも問題ない気がします。
> 確かに毎回レジスタを設定するために転送量が増えるというデメリットがありそうなので、
> 昨日までの、小林さんの案で、進めたいと思います。
ここが実際のところどうなのか、というのは自信がないところではあります。コンパス1個のように常に同じレジスタの値を読み出すのであれば転送量は減らせますが、複数のとびとびのレジスタの値を読む、とかだと逆に増えてしまいますよね…。
とりあえず、昨日の案でテストしてみていただけますでしょうか。なお、昨日のものではリードの際のバイト数を指定し忘れていましたので、そこを修正しました。
#define I2C 0x76 // I2C read/write message
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 read/write (0 => write, 1 => read)
* 3 slave address (7bit)
* 4 data 0 (LSB)
* 5 data 0 (MSB)
* 6 data 1 (LSB)
* 7 data 1 (MSB)
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
example: read a value of a slave device
1. Host => Arduino (1/2)
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 0 (write)
* 3 slave address
* 4 register to read (LSB)
* 5 register to read (MSB)
* 6 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
2. Host => Arduino (2/2)
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 1 (read)
* 3 slave address
* 4 bytes to read
* 5 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
3. Ardino => Host
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 0 (write)
* 3 slave address
* 5 data 0 LSB
* 6 data 0 MSB
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
2008/10/20 takanori endo <sweeta...@gmail.com>:
しかし、とってきたデータをどうやって持っていればいいのかをちょっと悩んでいます。
単純に
Arduinoクラスに、
byte[] I2Cdata
をつくって持っているのが、簡単そうですが問題ありそうでしょうか?
遠藤孝則
2008/10/20 23:11 Shigeru Kobayashi <koto...@gmail.com>:
--
endo takanori
小林です
おお、すばらしいですね。
> しかし、とってきたデータをどうやって持っていればいいのかをちょっと悩んでいます。
>
> 単純に
> Arduinoクラスに、
> byte[] I2Cdata
> をつくって持っているのが、簡単そうですが問題ありそうでしょうか?
他の方法とすると、I2C系のイベント用のイベントリスナを登録できるようにして、イベントが届いた時にコールバックされるような形でしょうか。このあたり、実装の都合としてはいかがでしょうか。
あと、この機能自体は同じFirmataを使うFIOでも同様に利用できると思いますので、digitalPinなどと同様にIOModuleクラスに実装してしまうのがいいかなと思います。
・・・
現状ではあくまでテスト用の実装ということで
/sysex
のみですませているのですが
/sysex/string
/sysex/i2c
のようにもう1階層設けた方が受信側がシンプルになるかなと思いますが、いかがでしょうか。
・・・
あれこれ同時で恐縮ですが、アナログピンやデジタルピンと同様に、I2Cデバイスのアドレス、レジスタ、バイト数をセットすると以降自動的にレポートしてくれる、というようにファーム側に実装した方が良いかなとも思っているのですが、この点はいかがでしょうか。コール&レスポンスですと、複数のレジスタを読み出すようなことになった場合、パフォーマンスがちょっと心配かなと思うのと、無線になった時に最適にパケット化するのが難しいかなと思いまして…。
五月雨式で申し訳ありませんが、ご意見お待ちしております。:)
2008/10/22 takanori endo <sweeta...@gmail.com>:
小林です
ちょっと遅くなってしまいましたが、変更後のI2CコマンドプロポーザルをArduinoの開発者向けMLにポストしてみました。StarndardFirmataにこれを組込んだものは明日用意してみようと思います。
http://arduino.cc/pipermail/developers_arduino.cc/2008-October/000163.html
ちょっと面倒な点があるとすれば、連続読み取りで、しかも複数デバイス&レジスタをサポートしようとするとリクエストされたもののリストをArduino側で保持しておく必要がある、ということでしょうか。とりあえず、固定長のリストで実装しようと思っています。
2008/10/22 Shigeru Kobayashi <koto...@gmail.com>:
小林です
大変遅くなってしまいましたが、先ほどコミットしたr505~r507でFunnel
Serverで対応しつつ、テスト用にhardware/arduino/SimpleI2CFirmataを追加しています。まだ、read
continuouslyには対応できていないのですが、SparkFunのコンパスモジュールに関しては、以下のような感じで読み取れることを確認しています。
aio.send_sysex 0x76, [0, 0x21, 0x47, 0x74, 0x51] #write, 'G'
aio.send_sysex 0x76, [0, 0x21, 0x41] #write, 'A'
10.times do
aio.send_sysex 0x76, [1, 0x21, 0x7F, 0x02] #read
sleep 0.5
end
以下が最新の仕様です。何かお気づきの点などありましたらお知らせください。
#define I2C 0x76 // I2C read/write message
/* IC2 read/write
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 read/write
0 => write
1 => read once
2 => read continuously
3 => stop reading
* 3 slave address (7bit)
* 4 data 0 (LSB)
* 5 data 0 (MSB)
* 6 data 1 (LSB)
* 7 data 1 (MSB)
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
example: read a value of a slave device
1. Host => Arduino
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 1 (read)
* 3 slave address
* 4 register to read (LSB)
* 5 register to read (MSB)
* 6 bytes to read (LSB)
* 7 bytes to read (MSB)
* 8 END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
2. Ardino => Host
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 I2C (0x76)
* 2 slave address (LSB)
* 3 slave address (MSB)
* 4 register (LSB)
* 5 register (MSB)
* 6 data 0 LSB
* 7 data 0 MSB
* ...
* n END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
2008/10/26 Shigeru Kobayashi <koto...@gmail.com>: