masato-ka's diary

日々思ったこととか、やったことの備忘録。

RN4020でI2Cの値を読み取る

この記事について

この記事ではRN4020のI2Cを利用する方法について紹介します。RN4020にはI2Cポートが付いています。EEPROMなどを接続しデータを一時的にためておくために利用できます。もちろん他のマイコンと同じようにI2Cポートをもったセンサを接続することができます。そこで、RN4020のI2Cポートに温湿度センサを取り付けて動作させてみました。

RN4020のI2C仕様について

 RN4020は21Pinと22PinがI2Cのポートとなっています。データシート上では21PinがSDA, 22PinがSCAになっていますが、実際には22PinがSDA, 21PinがSCAと逆になっています。(2017/10/16現在)秋月電子のボードも他のブレークアウトボードもデータシートにならって軒並み逆に記載されています。そのため基板の印字と回路図を比較する必要があります。おそらく逆につければ大丈夫です。I2Cバスのプルアップ抵抗はRN4020についていないません。そのため、センサモジュールについていなければ別途つける必要があります。ロジックレベルは3.3Vです。  また、RN4020のI2Cはファームウェアのバージョンが1.20以降で利用できます。現在販売されているものは1.23が多いようです。(最新はバージョン1.3)念のため、シリアルからVコマンドを使ってバージョンを確認しておきましょう。  RN4020はI2Cのマスタとして動作します。スレーブ動作は設定できません。また、EEPROM の読み書きを実行するコマンドがありますが、それ以外は指定データをシリアルバスにそのまま流す低レベルなAPIしかありません。

I2Cのコマンド

RN4020でI2Cを利用するためには以下の5つのコマンドを覚えれば大丈夫です。以下の5つのコマンドの組み合わせでI2Cのスレーブにアクセスします。

コマンド 用途
]A I2Cポートの初期化
]C I2Cのイベント制御
]Z I2Cポートの開放
]W データの書き込み
]R データの取得

I2Cコマンド利用方法

 今回はHDC1000と呼ばれるI2Cインタフェースの温湿度センサから温度の値を読み取る方法を例にとり、コマンドの使い方を説明します。 このセンサは前まで秋月電子通商で手に入りましたが最近は廃盤になったようです。センサのアドレスは7bitアドレスで1000000を持っています。上記のコマンドを使ってHDC1000から温度データを取得するには以下のように実行します。

]A,1,2 //(1)
]C,0 //(2)
]W,80020000 // (3)
]W,8000 //(4)
]C,1 //(5)
]W,81//(6)
]R,02 //(7)
6541 //16進数表記
  • (1) I2Cの初期化

最初の引数1はI2Cのクロックスピードです。100kHzを指定します。4を指定すると400kHzになります。また2番目の引数はGPIOを1,2,3,4,7で指定します。指定したGPIOは出力モードとなり、I2Cのスタート時にHighになります。スレーブの電源として利用することで、普段は電源を切っておくことができます。今回はGPIOを使わずに実験のため3.3Vの電源に直接接続しています。

  • (2) I2Cのスタート

]Cの引数に0コマンドをつけ、I2Cのスタートビットをバスに流します。この時、I2Cの初期化で指定したGPIOがHighになります。

  • (3) HDC1000の初期化

HDC1000はデータの取得方法など個別に細かく設定することができます。起動時に0x02のレジスタに値を書き込みます。今回は0x0000を書き込みます。詳細は以下のデータシートを参考にしてください。

]Wコマンドは指定されたバイト列をMSB側からバスに出力するコマンドです。データにバスを流すためのコマンドですので必ずしもスレーブへのWrite要求を出すコマンドではありません。そのため、I2Cの先頭バイトには7bitのスレーズ指定のアドレスと1byteのRead(1)/Wrie(0)を指定する必要があります。今回、HDC1000は2進数7bit表記で1000000がアドレスになります。最後にWriteを表す0をつけることで書き込みを表します。その後、書き込み先レジスタアドレス0x02と書き込みデータ0x0000を付与します。  実際にこの時の出力をロジックアナライザで確認すると以下の図のようになっています。

f:id:masato-ka:20171017075459p:plain

もしデバイスアドレスが8bit表記であれば左へ1bitシフトしたものにRead/Writeのbitを付け足します。(MSB側は必ず0になっているはず。。。)

引き続き]Wコマンドでレジスタ0x00へアクセスします。HDC1000ではこのジレスタにアクセスすることで、センサないのA/Dが温度の値を変換することになっています。Write要求ですが特にデータは書き込まず問題ありません。同じようにいかに信号の状態を出力しておきます。

  • (5) I2Cリセット

温度を読み取るまでのRN4020側の書き込みは完了したため、一度I2Cのバスを解放します。

(4)から(5)までのロジックアナライザ上での動作になります。

f:id:masato-ka:20171017075506p:plain

  • (6) リード要求

RN4020からリード要求を出します。この場合もバスに信号を流すため]Wコマンドを利用します。0x81はアドレス1000000のLSB側にRead要求の1を足したものになります。 I2CバスにREAD要求のコマンドが出力されます。

  • (7) データの読み取り

I2Cのデータの読み取りはリードコマンド]Rを使います。引数は受信するバイト数でここでは2バイトを表します。HDC1000の場合結果は4桁の16進数で帰ってきます。これを指定された式で計算して温度値を読み取ります。

(5)から(7)までのロジックアナライザ上での動きは以下の通りです。前述の説明と照らし合わせてみてください。

f:id:masato-ka:20171017075453p:plain

以上でRN4020のI2Cの値の読み取りになります。]Wと]Rの使い方に気をつければ他のデバイスやアクセス方法でも問題なく利用できると思います。ロジックアナライザの出力とコマンドを照らし合わせると出力がどうなるか理解できるかと思います。

I2Cスクリプトサンプル

I2Cはもちろんスクリプトモードからも利用できます。上記の例を参考に温度データを一定間隔でNotifyするスクリプトです。キャラクタリスティックには2byteでRead Notifyが指定されています。スクリプトとプライベートサービスの詳細は過去記事を御覧ください。

masato-ka.hatenablog.com

@PW_ON
A

@CONN
]A,1,2
]C,0
]W,80020000
]W,8000
]C,1 
SM,1,00002710

@TMR1
]W,81
$VAR1=]R,02
SHW,000B,$VAR1
SM,2,00002710

@TMR2
]W,8000
]C,1
SM,1,00002710

@DISCON
]Z
A

上記例では温度の変換命令''']W,8000```と読み取り命令を別のタイマーイベントとし、相互に繰り返すようになっています。(お互いのタイマーイベントを指定している。)これはHDC1000の温度変換の結果がくるのを少し待たないといけないためです。(ハードウェア割り込みもありますが今回は不使用です。)

まとめ

今回はRN4020でI2Cを利用してみました。I2Cもスタンドアローンで利用できるので、I2Cのセンサをつないでお手軽に利用することができます。簡単なセンサーデバイスはすぐに作れそうです。注意点としてはデータシート状のI2CのピンSDAとSCLが逆になっている点、]W,]Rのそれぞれの使い方です。ここさえ押さえればすぐに利用できます。データシートは何年もほったらかしのようですが、いつか修正されるのでしょうか。。。