IchigoJamのI2Cインタフェースについて
IchigoJamのI2Cインタフェースに関する個人的なまとめです。
(対象はファームウェア 1.2.1です)
1)3.3V対応であること
I2Cバス電圧が5Vの利用も一応可能です。
5Vで利用すれば動作します。ただし、なるべく3.3Vでの利用を推奨します。
あります。
利用出来 ています。
2)IchigoJam BASICの I2CR、I2CWコマンド仕様で利用可能なデバイスであること
一部のI2Cデバイスの制御が出来ません(そう多くないです)。
I2Cアドレスのみを送信してデータ取得を行うような通信が出来ません。
アドレスが0x50なのでEEPROMの0x50と競合して使えないです。
4)I2Cアドレスは7ビット長
5)プルアップ抵抗は必須(ボード上の搭載・MPU内部プルアップなし)
利用ピン
図の紫色の5番ピンSDA、27番ピン SCLをデータの2ピンをデータ通信に利用します。
また必要に応じて、VCC、GNDをIchigoJamに結線します。
5番ピン、純正品のラベルはIN3のみしか書いていないのでちょっと分かりにくいですね。
接続方法
一般的な接続方法
I2Cはバスですので複数のI2Cデバイス(スレーブ)が接続出来ます。
注意点としてSDAとSCLにプルアップ抵抗(2.2kΩ~10kΩ、図では4.7kΩを利用)が必要です。
ただし、I2Cデバイスにあらかじめプルアップ抵抗が搭載されている場合があります。
この場合は、そのプルアップ抵抗を利用するため回路図の抵抗は省略出来ます。
(省略しなくても利用可能)
「プアップ抵抗って何? 何で必要なの?」、「なんで出力が競合しないん?」的な解説
(内容が間違えているかもしれません)
I2Cバスの電気的性質
(読み返すと若干、内容が怪しいかも..後で修正します)
I2CのSDAとSCLは双方向の信号ラインです。
普通に考えると、それぞれのデバイスで入出力の方向が異なる可能性があり、
なんで上手く動いているのだろう?って疑問に思います。
通常のH(ハイ 3.3V)、L(ロー 0V)の状態を持つ線を共通配線にした場合、
それぞれが出力状態かつ、出力値が異なる場合、厄介なことが発生します。
例えば、SDA接続で1つがH(3.3V)、別の1つがL(0V)を出力するとこれはもう、
ショート状態です。H→L間で大きな電流が流れICが破損する可能性もあります。
また、ショートしなくてもSDAのバス的に信号がHなのかLなのか不定です。
そこでI2CバスではワイヤードAND接続が採用されています。
この場合、SDA、SCL端子はオープンドレインという状態で利用します。
この時の出力の取り得る状態はH(1、ハイ 3.3V)、L(0、ロー 0V)ではなく、
H(Hi-Z:ハイインピータンス=絶縁状態)、L(0、ロー 0V)となります。
ハイインピータンスは高抵抗値を意味し、端子には電流が流れない状態です。
この状態であれば、バス上で各デバイスの出力状態でHとLが重なっても
問題となりません。
絶縁状態の端子に0Vの端子を接続しても電流は流れませんね。
当然、ショートも発生しません。
ただしこの場合、1つ厄介なことが発生します。
下の図は共通配線SDA、各スイッチがI2CデバイスのSDA出力を等価的に表しています。
スイッチOFF時がハイインピータンス(絶縁状態)、スイッチON(接続時)がLです。
全てのデバイスがH(ハイインピータンス=スイッチが開いている状態)、
共通配線SDAは、電圧が不定て右端のSDA出力端子からは
状態(H? L?どっち?)を読むことが出来ません。
そこで、プルアップ抵抗を入れて
SDAがH(ハイインピータンス)の場合は、プルアップ抵抗経由の電圧が出力され、
ロジックとして"1"をとるようにします。
SDAがL(0V)の場合は、そのまま0Vでロジックとして"0"と判定出来ます。
もしも、それぞれが好き勝手に出力した場合ですが、
1つでもL(0V)があればSDAの状態はLになります。
上図は全てがHですが、どれか1つスイッチを閉じるとSDAが0Vになるは明白です。
論理的にはANDをとってどれか1つでも0ならばSDAのバスは0、
全部がHなら1となります(= ワイヤードAND (論理積))。
(ちなみにI2Cでは、SDA、SCLともHの場合にバスがフリーな状態と規定しています)
IchigiJamのI2C利用コマンド
例としてRTCモジュール(DS3231搭載)を使って説明します。
RTCモジュールは時計機能を持つモジュールで時刻設定、時刻参照、アラーム設定、
アラーム通知が主な機能です。
(このデバイスはプルアップ抵抗搭載なのでIchigoJamに直結で利用出来ます)
IchigoJamにはデータ送信用とデータ受信用の2つのコマンドが用意されています。
・ データ送信
I2CW(I2Cアドレス、 コマンド、コマンド長、送信データ、データ長)
・ データ受信
I2CR(I2Cアドレス、 コマンド、コマンド長、受信データ、データ長)
引数のI2Cアドレスは利用するI2Cスレーブのアドレスを指定します。
このアドレスの指定方法は7ビット、8ビット、10ビット等がちょっと混乱しすが
IchigoJamでは7ビットアドレスを指定します。
まず、利用するI2CデバイスのI2Cアドレスを知る必要があります。
通常は添付の解説書または、商品情報HPのリンク先の資料に記載されています。
大抵は下図のような通信データのレイアウトが記載されています。
この図で<SLAVEADDRESS>がI2Cアドレスとなります。
(0と1の羅列が7個あるので7ビットだと分かります。系によっては<R/W>を含めて
8ビットで指定する場合もあります)
2進数表記 1101000 をIchigoJamでそのまま指定する場合は、
`1101000 となります(` はキーボードの[@]キーを[Shift]キーを押しながら入力)。
メモリー的&読書きにおいて無駄なので16進数に直して#68 で指定することにします。
(IchigoJam上で ?HEX$(`1101000) を実装すれば楽に求められますね)
I2CW、I2CRコマンドの引数、
コマンドはI2Cデバイスに送るコマンドの格納アドレス、コマンド長はその長さです。
IchigoJamの変数では可変長のデータを直接扱うことが出来ません。
そのため、アドレスでの指定となります。
ここで、RTCモジュールに時刻設定する場合を考えます。
設定にはI2CWコマンドを使います。
RTCモジュールの場合、引数のコマンドにはRTCモジュール内のレジスタアドレスを指定します。
次の表がレジスタアドレスに割りつけられている機能です。
引数のコマンドにはこの表のアドレスを指定し、書きこみたいアドレスを指定します。
<レジスタアドレス表>
引数の送信データには上記の表に設定する内容を指定します。
ここでは年、月、日、曜日、時、分、秒 の7つの値を1回の送信で設定したいと思います。
2016年9月13日(火) 20時30分00秒 を設定することにします。
この場合、アドレス00h~06hにだけ値を設定します。
まず、設定値は次のようになります。データ長は7バイトです。
アドレス 設定値 補足
00h: #00 秒
01h: #30 分
02h: #20 時
03h: #03 曜日(01:日、02:月、03:火 ... 06:土)
04h: #13 日
05h: #09 月
06h: #16 西暦年下2桁
16進数BCD表記ではほぼ見た目のままの数字の指定となります。
以上のコマンドと設定データの実際の送信を行うプログラムと実行結果です。
10 POKE #700,#00,#00,#30,#20,#03,#13,#09,#16
20 R=I2CW(#68,#700,1,#701,7)
30 ?R
10行のPOKEコマンドでIchigoJamのアドレス#700から#00、#00、#30..#16を
順番に格納しています。最初の#00はコマンドとして送信するデータ1バイト、
次の#00~#16が設置値7バイトです。
#700からの領域はPCG定義用の領域です。フォント定義を利用しない場合は、
自由に利用出来ます(256バイト)。
20行ではI2CWコマンドを使って実際にI2Cデバイスのデータを送信しています。
変数Rは送信結果が返されます(0で正常、1で異常)。
#68はI2Cデバイスのアドレス、#700がコマンド格納アドレス、1がコマンド長、
#701が送信データの格納アドレス、7が送信データの長さです。
実行すると次のような感じになります。
正常動作の0が表示されます。
次にI2CWコマンドを使って現在時刻を読みだしてみます。
I2CR(I2Cアドレス、 コマンド、コマンド長、受信データ、データ長)
ここでは年、月、日、曜日、時、分、秒 の7つの値を取得することです。
I2CRの引数のI2CアドレスはI2CRと同じ#68を指定します。
コマンドおよびコマンド長にはレジスタアドレス表の00hを指定します。
受信データおよびデータ長は取得したデータを格納するアドレスとして#710、長さ7を指定します。
以下が実際のプログラムと実行結果です。
10 POKE #700,0
20 R=I2CR(#68,#700,1,#710,7)
30 ?R
40 FOR I=0 TO 6
50 ?HEX$(PEEK(#710+I),2)
60 NEXT
10行はコマンドを#700に設定
20行はI2Cアドレス#68、コマンド格納アドレスとして#700、その長さとして1を指定、
受信したデータ格納アドレスとして#710、その長さとして7を指定しています。
30行がI2CRの実行結果の表示
40~60行は#710~#706に格納されている取得データを16進数2桁で表示しています。
IchigoJamのI2CW、I2CRのバグ(不具合)について
2つのコマンド、
I2CW(I2Cアドレス、 コマンド、コマンド長、送信データ、データ長)
I2CR(I2Cアドレス、 コマンド、コマンド長、受信データ、データ長)
において次のバグ(不具合)があります。
・コマンドにて送信するデータはコマンド長0を指定すると意味不明なデータが
I2Cデバイスに送信されます。この時、データ長も固定ではないようです。
・コマンドにて5バイト以上のデータを送信するとI2Cデバイスには
正しくないデータが送信されます。
(本不具合は開発者に連絡済です)
なのでコマンドは1~4バイトの範囲で利用しましょう。
2017/04/03 追記
最新のβファームでは上記不具合は対応済みです。
(facebook IchigoJam-FANにて公開 IchigoJam 1.2 beta 42)
以前試した、Wii用ヌンチャク等も利用可能になりました。
2018/04/19 追記
現時点の最新版IchigoJam 1.2b56で温湿度センサAM2320の利用の挙動が怪しいです。
パケットを調べると、 アドレス送信だけの送信を何回も繰り返し(1000回以上)ています。
温湿度センサAM2320 は、プロトコルとして、最初にウェイクアップのために
I2Cスレーブアドレスだけを送信します。
このとき、温湿度センサAM2320はNAKを返す仕様です。
どうも、IchigoJamはアドレス送信で、NAKが帰ってくるとリトライを膨大に繰り返すようです。
試しに、存在しないI2Cスレーブアドレスを送信してみると、やはりリトライを膨大に
繰り返しました。
う~ん、リトライはアプリの方でやればいいので、コマンドで勝手にやっちゃダメでしょ。
以前ぼバージョンでは、リトライは無かったので、仕様変更があったようです。本件の現象の報告は、開発者さんも目にしているはずですが、今のところ沈黙です。
2019/01/14 追記
IchigoJam 1.3系では、上記のI2Cの怪しい挙動が改善されました。
温湿度センサAM2320 も問題なく動作します。
« aitendoのこどもパソコン「ai.Jam-T」キット を組み立てました | トップページ | LEDドットマトリックスを使ったメッセージ表示デバイスを作成中 »
「IchigoJam」カテゴリの記事
- Ichigojam Rが届きました(2021.02.05)
- β版 IchigoJam Rを予約注文しました(2021.01.23)
- IchigoJamのファームウェア 1.4.1が正式に公開されました(2019.12.10)
- 「ichigoツール」をGithubにて公開しました(2019.11.09)
- ichigojamのファームウェアを1.4b13にアップデートしました(2019.11.06)
コメント
« aitendoのこどもパソコン「ai.Jam-T」キット を組み立てました | トップページ | LEDドットマトリックスを使ったメッセージ表示デバイスを作成中 »
昨日イチゴジャムのI2Cで上手くいかないで悩みまくってました。
ラズパイで出来て何でイチゴジャムで出来ないのか、、、、
> I2Cアドレスのみを送信してデータ取得を行うような通信が出来ません。
そうなんですね。 プルアップ抵抗も知りませんでした。
初めて二日目のジャムは辛かった、、、、、
投稿: 米光 | 2018年2月21日 (水) 03時55分