I2C通信実験 照度センサー [PIC]
結構前に amazon で購入した照度センサモジュール(GY-302)を I2C でPIC24FJに接続し動かしてみました。
このモジュールは BH1750FVI を使用していて、データシートを見るとコマンド数も少なく簡単に動かせそうです。
今回は ebay 価格702円の Logic Analyzer で I2C の通信をモニタしてみました。価格から推測するに saleae社製のものではなくパチモンなのでPC側のソフトは本家の Saleae Logic ではなく、pulseview を使ってみました。
I2Cの表示に限って言えば pulseview は波形表示の下に I2C のコマンドやデータの値を表示できるので本家のソフトより見易い面もあります。(★2018/02/18 修正 本家ソフトも波形部にも通信内容を表示できます)
でもセーブした設定状態をロードすると変になる等、不安定な部分があります。これに対して本家のソフトはこれでもかというくらい使い易さを追求し作り込まれたようなソフトに仕上がっています(すばらしい!)。
picle言語による I2C 接続は「I2C通信実験 3軸磁気センサー」で実験済みなのですんなり接続できました。
3軸磁気センサーの実験の時は I2C のクロックとデータの波形を見て確認したりしていましたが、今回は数百円のロジックアナライザのおかげで確認が超ラクチンです^^
接続試験のために作成した処理の概要は下記のとおりです。
ロジックアナライザで確認した結果は次のようになります。I2Cのスタートシーケンスとストップシーケンスがともに「|」のような表示ですが、マウスカーソルをあてると状態が表示されどちらか判別できます(スタートとストップは違う記号の方が見易いのに)
★2017/02/25 追記
I2C のスタートシーケンスとストップシーケンスが判別可能な記号で表示されるようになりましたので画像を差し替えました。いじっていると表示されたりされなかったりします・・^^;
実行結果のサンプルが下記です。データシートによると読込んだ値を 1.2 で割ったものが ルックス ということですが、今回は接続確認ということで読込んだ値の 1/12 の値を表示しています。途中で値が変化しているのはライトで照らしているからですw
実行結果
picle言語で記述したソースは次のとおりです。
I2C connect to Light Sensor(picle)
[ 前へ ] 連載記事 [ 次へ ]
このモジュールは BH1750FVI を使用していて、データシートを見るとコマンド数も少なく簡単に動かせそうです。
今回は ebay 価格702円の Logic Analyzer で I2C の通信をモニタしてみました。価格から推測するに saleae社製のものではなくパチモンなのでPC側のソフトは本家の Saleae Logic ではなく、pulseview を使ってみました。
I2Cの表示に限って言えば pulseview は波形表示の下に I2C のコマンドやデータの値を表示できる
でもセーブした設定状態をロードすると変になる等、不安定な部分があります。これに対して本家のソフトはこれでもかというくらい使い易さを追求し作り込まれたようなソフトに仕上がっています(すばらしい!)。
8chロジックアナライザ |
|
picle言語による I2C 接続は「I2C通信実験 3軸磁気センサー」で実験済みなのですんなり接続できました。
3軸磁気センサーの実験の時は I2C のクロックとデータの波形を見て確認したりしていましたが、今回は数百円のロジックアナライザのおかげで確認が超ラクチンです^^
接続試験のために作成した処理の概要は下記のとおりです。
- 1秒ウェイト後、Power On コマンド(0x01)と One Time H-Resolution Mode コマンド(0x20)を送信
- 計測時間(180ms)待ち
- 計測データを取り込み、値を表示
- Power Down コマンド(0x00)を送信し、I2Cのストップシーケンスを実行
- 上記1に戻る
ロジックアナライザで確認した結果は次のようになります。
★2017/02/25 追記
I2C のスタートシーケンスとストップシーケンスが判別可能な記号で表示されるようになりましたので画像を差し替えました。いじっていると表示されたりされなかったりします・・^^;
上記1の波形 |
|
上記3の波形 |
|
上記4の波形 |
|
実行結果のサンプルが下記です。データシートによると読込んだ値を 1.2 で割ったものが ルックス ということですが、今回は接続確認ということで読込んだ値の 1/12 の値を表示しています。途中で値が変化しているのはライトで照らしているからですw
:run 0 : 8 [x10 lx] 1 : 8 [x10 lx] 2 : 8 [x10 lx] 3 : 8 [x10 lx] 4 : 8 [x10 lx] 5 : 156 [x10 lx] 6 : 890 [x10 lx] 7 : 423 [x10 lx] 8 : 1002 [x10 lx] 9 : 1026 [x10 lx] 10 : 222 [x10 lx] 11 : 97 [x10 lx] 12 : 2684 [x10 lx] 13 : 2895 [x10 lx] 14 : 4296 [x10 lx] 15 : 4712 [x10 lx] 16 : 4746 [x10 lx] 17 : 4755 [x10 lx] 18 : 4453 [x10 lx] 19 : 3704 [x10 lx] 20 : 2192 [x10 lx] 21 : 1031 [x10 lx] 22 : 794 [x10 lx] 23 : 675 [x10 lx] 24 : 614 [x10 lx] 25 : 607 [x10 lx] 26 : 581 [x10 lx] |
picle言語で記述したソースは次のとおりです。
# I2C test Light Sensor(BH1750) # written with picle language by skyriver # 2017/02/24 ver 0.01 var RegRcv,RegTrn,RegBrg; var RegCon,RegStat; var I2CRcv; # send data to slave # data <- send data # return -> 0:no error func I2CSnd( data ) { while ( RegCon[0] & $1f ) {} RegTrn[0] = data; while ( RegStat[0] & $4000 ) {} return = RegStat[0] & $8000; # check nack } # receive data form slave # ack <- 0:nak, else:ack # I2CRcv -> receive data # return -> 0:no error func I2CRcv( ack ) { while ( RegCon[0] & $1f ) {} RegCon[0] = RegCon[0] | $0008; # enable receive while ( RegCon[0] & $0008 ) {} if ( ack ) { RegCon[0] = RegCon[0] & ~$0020; # set ack } else { RegCon[0] = RegCon[0] | $0020; # set nack } RegCon[0] = RegCon[0] | $0010; # send ack/nack while ( RegCon[0] & $0010 ) {} I2CRcv = RegRcv[0]; return = RegStat[0] & $0040; # check overflow } # start seqence and send salave adrs # adr_cmd <- slave_adrs << 1 | RD:1 # return -> 0:no error func I2CAdr( adr_cmd ) { RegCon[0] = RegCon[0] | 3; # repeated start return = I2CSnd( adr_cmd ); } # stop I2C sequence proc I2CStop() { RegCon[0] = RegCon[0] | $0004; # set PEN(stop) while ( RegCon[0] & $0004 ) {} } proc Init( base ) { var Ad1pcfg; Ad1pcfg = $032c; Ad1pcfg[0] = $ffff; # set digital mode RegRcv = base; RegTrn = base + 2; RegBrg = base + 4; RegCon = base + 6; RegStat = base + 8; RegBrg[0] = 39; # Fcy:4MHz -> I2C 100kHz RegCon[0] = $8000; # enable I2C } proc main() { var CmdPowerdown, CmdPowerOn, CmdHiResoRead; var TimerSave; var adr, err, i, RdVal; Init( $0210 ); # I2C 2ch:$0210 adr = $23 * 2; # BH1750's address CmdPowerdown = 0; CmdPowerOn = 1; CmdHiResoRead = $20; I2CStop(); err = I2CAdr( adr ); err = err | I2CSnd( CmdPowerdown ); # set Power down if ( err ) { PrnStr_( "error !" ); exit(); } for ( i=0; i<600; i=i+1 ) { while ( Timer_ ) {} Timer_ = 100; # set timer 1sec if ( I2CAdr( adr ) ) { PrnStr_( "adr err " ); } else if ( I2CSnd( CmdPowerOn ) ) { # Power on PrnStr_( "err " ); } else { if ( I2CAdr( adr ) ) { PrnStr_( "read cmd err " ); } else { err = I2CSnd( CmdHiResoRead ); TimerSave = Timer_ - 18; while ( TimerSave <= Timer_) {} # wait 180ms until complete err = err | I2CAdr( adr | 1 ); # read command err = err | I2CRcv( 1 ); # read high byte RdVal = I2CRcv * 128; err = err | I2CRcv( 0 ); # read low byte PrnDecF_( i, 5 ); PrnStr_( " : " ); if ( err = 0 ) { RdVal = RdVal + I2CRcv / 2; RdVal = RdVal / 6; # calc [10 lx] PrnDecF_( RdVal, 5 ); PrnStr_( " [x10 lx]\n" ); } else { PrnStr_( "err\n" ); } } } if ( I2CAdr( adr ) = 0 ) { err = I2CSnd( CmdPowerdown ); } I2CStop(); } } |
[ 前へ ] 連載記事 [ 次へ ]