SSブログ
English Version

I2C通信実験 照度センサー [PIC]

 結構前に amazon で購入した照度センサモジュール(GY-302)を I2C でPIC24FJに接続し動かしてみました。
 このモジュールは BH1750FVI を使用していて、データシートを見るとコマンド数も少なく簡単に動かせそうです。

 今回は ebay 価格702円の Logic Analyzer で I2C の通信をモニタしてみました。価格から推測するに saleae社製のものではなくパチモンなのでPC側のソフトは本家の Saleae Logic ではなく、pulseview を使ってみました。
 I2Cの表示に限って言えば pulseview は波形表示の下に I2C のコマンドやデータの値を表示できるので本家のソフトより見易い面もあります。(★2018/02/18 修正 本家ソフトも波形部にも通信内容を表示できます)
 でもセーブした設定状態をロードすると変になる等、不安定な部分があります。これに対して本家のソフトはこれでもかというくらい使い易さを追求し作り込まれたようなソフトに仕上がっています(すばらしい!)。

8chロジックアナライザ


 picle言語による I2C 接続は「I2C通信実験 3軸磁気センサー」で実験済みなのですんなり接続できました。
 3軸磁気センサーの実験の時は I2C のクロックとデータの波形を見て確認したりしていましたが、今回は数百円のロジックアナライザのおかげで確認が超ラクチンです^^

 接続試験のために作成した処理の概要は下記のとおりです。
  1. 1秒ウェイト後、Power On コマンド(0x01)と One Time H-Resolution Mode コマンド(0x20)を送信
  2. 計測時間(180ms)待ち
  3. 計測データを取り込み、値を表示
  4. Power Down コマンド(0x00)を送信し、I2Cのストップシーケンスを実行
  5. 上記1に戻る

 ロジックアナライザで確認した結果は次のようになります。I2Cのスタートシーケンスとストップシーケンスがともに「|」のような表示ですが、マウスカーソルをあてると状態が表示されどちらか判別できます(スタートとストップは違う記号の方が見易いのに)
★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 connect to Light Sensor(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();
    }
}


[ 前へ ] 連載記事 [ 次へ ]

HT7733Aの入出力特性 [PIC]

 電池1個で動作する簡単なロギング装置を作成しようと思い、ステップアップDC/DCコンバータ(HT7733A)にPIC24FJ64GAを接続してみたところ、入力電圧が 2.2V を切る辺りから HT7733A の出力電圧がどんどん低下してきて電池1本で動かすことが不可能な感じでした。
 HT7733A のデータシートには次のように書かれています。
  • Low start-up voltage: 0.7V (Typ.)
  • Output current up to 200mA

 試しに HT7733A(出力:3.3V)のデータシートに記載されている下図の回路の先に PIC24FJ64GA を接続して入力電圧/出力電圧/入力電流の特性を確認してみました。インダクタは 68μH のものを使っています。

測定回路


 測定順番としては入力電圧を 2.5V から始め、入力電圧を段々下げて測定しています。入出力電圧はデジタルオシロの表示数値、電流は電源からの入力部の間にテスタを繋いで測定(HT7733Aの入力電流を測定)しています。
 HT7733A のデータシートによると入力電圧、出力電圧、出力電流の関係は下記グラフのようになります。

HT7733Aのスペック特性


 電池1個で動かすものを作りたいので 0.9V 程度までは出力が 3V 以上であることを期待していましたが、下のグラフのように入力電圧が 1.7V を下回ったあたりで急に出力電圧が下がりました。安定化電源で給電して測定していますが、1.7V → 1.2V の途中の値は出力を微調整できませんでした。
 PIC24FJ のスペックとしては 32MHz動作時の電源電圧は 2.35V 以上必要なのでこの状態では電池1個での動作はできません・・・

 出力電圧が下がるに従い、入力電流が増加しているのは 入力電圧の低下により HT7733A の変換効率が下がっているためと推測されます(PIC自体の消費電流は電圧が下がれば若干減少するはず)

特性(PIC24FJ64GA:32MHz)


 HT7733A のデータシートに 200mA まで出力できるとは書いていますがこれは入力電圧が高い場合であり、入力電圧が低い場合は出力電流との兼ね合いで供給できる電圧が変化します。
 負荷側の消費電流を下げた場合、状況が変わるものか確認するため、 PIC24FJ64GA のクロックを 1/4(8MHz)にした状態で同様な特性を確認した結果が下のグラフです。
 また、PIC24FJ は 8MHz 動作時にスペック上は電源電圧が 2V まで動作します。これであれば周辺回路の消費電流次第ですが、電池1個でも動かせそうです。

特性(PIC24FJ64GA:8MHz)


デルタ式3Dプリンタ(Kossel Reprap)の購入(その3) [3D_printer]

 前回から引き続き ABSフィラメントでの調整をしています。

 ヒートベッドへのフィラメント固定については色々試しましたが カプトンテープ+ケープで落ち着きました。
 ケープ(3Dエキストラキープ)はたまたま近所で安売りしていたものですが、容器に記載されている説明を読むとキープレベル(1~4)がケープシリーズでは最高の4のものです。商品名にも「3D」とあり、まさに今回の用途向きですw
 ヒートベッドとの接触面積が小さいものでも今のところ出力途中で剥がれることありません。

 今まで使ってきたダヴィンチのヒートベッドはヒーターにガラス板が付けてあり、スティック糊(シワなしPiT)を塗ることで出力直後は出力物が取れない状態で、ヒートベッドが冷めると「ピシッ」と音がして簡単に取れました。また、スティック糊は水分を含ませた布で拭くことで簡単に取れ、再度塗ることでリピート的に出力できました。

 今回のカプトンテープ+ケープでは出力直後でも力を入れれば出力物が取れる状態で固着力はダヴィンチの場合よりも低いですがヒートベッドが冷めなくても取り外せるというのは利点ともいえます。
 但し、ケープは濡れた布ではきれいに取れない(ゴシゴシ擦ると垢のように塊になって取れてくるけどきれいには取れない)のである程度出力を繰り返したら、カプトンテープごと張り替える必要がありそうです。
 またケープの場合、最下層が艶消しのようになり、ラフト無しでもいい感じで出力できます(ダヴィンチでは艶々になるのでケースの上面部等に好んで使いましたがケープのつや消し状態の方がいい)。


 ヒートベッドへのフィラメント固定については一応解決できたのである程度のサイズのあるものを出力したところ、ダヴィンチでは発生しなかったひび割れ問題が発生しました。
 積層間の固着が弱いのが原因の1つと考え、フィラメントの温度を上げたましたが、若干の改善はしたもののひび割れが発生する状態でした。

ひび割れ(215℃) ひび割れ(230℃)


 ABS樹脂は熱膨張率が大きいので出力時の環境温度を上げることが有効との情報があったので、まずはプリンタをビニール袋で囲って出力時の環境温度を上げてみました。因みに暖房していないところで動かしているので今までの環境温度は15℃くらいでした。
 プリンタ全体をビニール袋で囲ったところプレームに取付けたスイッチング電源が結構熱くなったので電源は囲わないようにしました。この状態で出力してみたところ、ひび割れ無しで出力できました ^^/
 温度計もいれて環境温度を確認しながら出力しましたが、環境温度は30℃程度でした。冬でなければこんなことをしなくても大丈夫かもしれません。また出力物の高さが低い(2~3cm以下)のであればヒートベッドで温められるので環境温度対策は不要です。
 ビニール袋をかぶせただけではプリンタの可動部に巻き込まれる危険があるので下図のようなビニール固定パーツを作成しました。
 この簡易的な環境温度対策をビニールハウス方式と呼ぶことにしますw

対処後(環境温度:30℃) ビニール固定用パーツ


 ダヴィンチでも使用し、調子が良かったフィラメントホルダを今回購入したデルタ式3Dプリンタ用に作りました(プリンタと配色を合わせた^^)

フィラメントホルダ


 今回自作したビニールハウス方式でのビニール固定用パーツの STL ファイルはここからダウンロードできます(商用目的以外であれば自由に使用できます)

[TOP] [ 前へ ] 連載記事 [ 次へ ]