VL53L0X ToF Sensor

Feb. 6th,2108 updated

1.ハードウェア準備

秋月電子通商で、VL53L0Xのチップが入手できます。
http://akizukidenshi.com/catalog/g/gI-11449/
これを下記のような回路に組み付けました。
/media/uploads/kenjiArai/vl53l0x_circuit.png
モジュールは、驚くほど小さいですが、拡大鏡を使えば何とかはんだ付け出来る大きさです。
/media/uploads/kenjiArai/board0.png/media/uploads/kenjiArai/board2.png
左側がセンサーの表で、右が裏面です。基板に穴を開けて実装しました。
基板製作後に、秋月からセンサーを実装したモジュールが発売されました。
http://akizukidenshi.com/catalog/g/gM-12590/
こちらを購入すれば、配線は楽になるでしょう。
スイッチサイエンス、ストロベリーリナックスなどでもモジュールが販売されていますので、同様に使えると思いますが、今回は手元にありませんので、実験していません。
注意すべき点としては、販売されているモジュールは、Arduinoなどへの接続を意識して、内部で2.8V電源を内蔵してI2Cラインには、レベル変換を実施しています。
しかしXSHUT端子は、2.8Vにプルアップされているだけで、そのまま端子に接続されているので、オープンドレイン駆動しないと3.3Vや5Vが端子に印加される可能性があります。
その点では、上記の回路は全てが3.3Vで動作しますので、Mbedには一番相性が良いと思います。
VL53L0Xが、2.8Vで動作させないといけないと書かれているWeb情報もありますが、3.3Vは推奨電圧範囲内ですので問題ありません。

2.ソフトウェアのポイント

当初、STマイクロが提供しているX-NUCLEO-53L0A1ボードの紹介ページから、使えそうなプログラムを探しました。
/components/X-NUCLEO-53L0A1/
下記を使おうとしたのですが、あまりにもボードに特化して単独のセンサーとして使用するには使い勝手が悪すぎます。
/teams/ST/code/X_NUCLEO_53L0A1/file/99c367e8a402/Components/VL53L0X.lib/
更に、VL53L0Xのレジスター情報が公開されていないように思えます(私が探し切れないだけでしょうか?)。
Feb.6th,'18 ->
この件は、 4.余計な話に情報追加しました。
<-Feb.6th,'18
そこで、上記ライブラリーを一部修正してクラス関数を簡素化してみました。
しかし、オリジナルのVL53L0X.hが2798ライン、VL53L0X.cppが5513ラインであり、その他のファイルを含めると膨大なライブラリーですので、理解するのは難しく、修正には多くの時間がかかりました。

ところで、本当にこんな膨大なライブラリーを用意しないと制御できないほど難しいセンサーなのでしょうか?
私は、Arduinoのライブラリーに関して知識が無いのですが、Mbedで50KB(mbed-os5だと70KB以上)にもなるライブラリーの作り方に頭が下がる以上に、疑問を持ちました。
それもセンサーを販売しているSTマイクロのプロ作成のライブラリーとして公開されています。
何か、"このセンサーは難しいぞ!素人は使うな!”としか受け取れません。

当初は、プログラムサイズを削減し、32KBROMサイズのMbedでも使えるように機能削減を始めたのですが、断念してインターフェイスのクラス呼び出し関数の簡略化だけに集中してしまいました(残念)。
手持ちのボードでの動作確認は実施しましたが、割り込み信号(GPIO1端子の利用)を用いた制御に関しては何の動作テストも行っていません。
割り込みの使用には注意願います。

Import libraryVL53L0X_simple

Fork of X-NUCLEO-53L0A1 Library and deleted the board related files. Just use a VL53L0X chip as a ToF sensor.


ライブラリーのチェック用に下記プログラムを作成しました。

Import programCheck_VL53L0X_simple_ToF_Sensor

check program for VL53L0X_simple library


Feb.6th,'18->
XSHUT端子をNCにせずにちゃんと制御する場合には、いくつものVL53L0Xを制御できます。
これは、VL53L0XにはI2Cアドレスを動的に変える機能があるために可能になります。
XSHUT端子をLoにして、ひとつだけアクティブにしてアドレスを変更するため、初期化ルーチンを分離しました。
当然のことながら、XSHUTをHiのまま放置した場合には、複数接続は出来ません。
ライブラリーの変更に伴い、上記プログラムも修正しました。

Import programCheck_VL53L0X_simple_with_three_ToF

Control three VL53L0X sensors

<-Feb.6th,'18

3.動作結果

動作チェックの様子です。
/media/uploads/kenjiArai/setup0.png
使用したプログラムでは、暗黙的に、
OperatingMode=range_single_shot_polling
となっています。
更に機能追加で、
range_long_distance_33ms_200cm
range_hi_accurate_200ms_120cm
range_hi_speed_20ms_120cm
の3つのモード選択が出来るように変更してみました(処理時間の33ms、200mS、20msは概ね可能です)。
データをExcelで処理した結果が、下記のようになりました。
/media/uploads/kenjiArai/result.png
650mmを目標に(但し、その測定精度は?)遮蔽物を置いて2万回以上のデータを260mS程度のループ周期で連続測定した結果です。
データ測定には200mS程度かかり、その他にLCD表示やPCへの出力に時間を費やしています。
平均値で652.2mmの測定値で、最大値と最小値で1.6cmほどのばらつきが出ています。
実際には、
sensor.set_mode(range_long_distance_33ms_200cm);
の設定が、処理時間が短いしより長い距離を測定できるので、最適と思われます。
仕様書(DM00279086 -> DocID029104 Rev 1 May 2016, p28 5.3.2 Range profile examples)には、+/-3%の精度(@1200mm)と書かれているので、それなりには動作していると思われます。
尚、測定はちっちゃなNucleo-F303K8で測定していますが、Nucleo-F031K6ではROMサイズの関係で動作させることが出来ませんでした。
TY51822r3では動作していますので、BLEで測定データを送ることは可能だと思います。

range_long_distance_33ms_200cmの状態で測定すると下記のようなデータとなります。
Total loop timeがデータにありますが、wait_ms()で実際には100mSに制御されています。
/media/uploads/kenjiArai/result1.png


4.余計な話

其の一
XSHUTが2.8Vでプルアップされている市販のVL53L0Xモジュールでは、Mbed側からの出力でシャットダウン制御(アクティブLow)する時には注意が必要です。
STマイクロのX-NUCLEO-53L0A1ボードでは、XSHUTもレベル変換して端子に印加しているので問題ありません。
そこで、今回の改造したライブラリーでは、MbedのコンストラクターDigitalOutは使用せずに、DigitalInOutをこのピンへの接続に使用しています。
原理は簡単で、いつもはMbed側端子を入力とし、プルアップ抵抗でHiレベル(2.8V) を保ち、アクティブLoとする時だけ、ゼロを出しながら出力モードに設定します。
このように制御すれば、XSHUT端子は、2.8V か0Vのどちらかのレベルで制御できます。
Arduinoでは、5V系で動作させているものは、5Vが印加されているのでしょうか?

其の二
更に、STマイクロのオリジナルのライブラリーでは、

#define USE_I2C_2V8

が定義されていれば、VL53L0X.cpp内の
VL53L0X_Error VL53L0X::VL53L0X_data_init(VL53L0X_DEV dev);
関数内で、2.8Vでの動作をさせることが出来ます。設定なしでは、1.8Vでの動作を想定している模様です。

#ifdef USE_I2C_2V8
#if ORIGINAL
    Status = VL53L0X_UpdateByte(Dev,
                                VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
                                0xFE,
                                0x01);
#else
    status = VL53L0X_update_byte(dev,
                                VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
                                0xFE,
                                0x01);
#endif
#endif

この定義を有効にするとORIGINAL部分が、生きてきますが、呼んでいる関数は存在しません!!
ということは、現在のSTマイクロのラブラリーでは電源電圧を2.8Vに設定しているのに、1.8V動作をさせていることになります。
ICが壊れるのではなく、多分精度の問題だとは思いますが、レジスター内容が情報不足で入手できないので、影響はわかりません。

其の三
I2Cの制御に関しては、STマイクロオリジナルライブラリーで、DevI2Cとして別クラスを作って制御しています。
それ自体に文句は無いのですが、追加でI2Cへ接続するコンストラクターを宣言するとエラーが出てしまいます。
実は、最初に何も変更しないでオリジナルライブラリーをうまく使おうと思ったのですが、I2CタイプのLCDを接続しようとすると先のエラーで、対応の仕方が見つかりませんでした。
今回のライブラリー改造は、この点が一番のポイントでした。
何故、ライブラリー作成時に、必要最小限のライブラリーが単独で使用できるように設計して、その機能を拡張するような設計ができなかったのでしょうか?
しかし私自身で最初から作成して、70KBのライブラリーとして公開する能力はありませんので、使わせていただいたことには感謝しています。
Feb.6th,'18->
実は、STマイクロ提供のオリジナルプログラムを修正する過程で、一箇所気になる点を発見してそこをコメントアウトしたところI2CタイプのLCDを一緒に使えるようになりました。
下記を修正するだけでした。
/HelloWorld_53L0A1_with_I2C_device/X_NUCLEO_53L0A1/ Components/VL53L0X/VL53L0X_i2c_platform.h <<code  VL53L0X_i2c_platform.h>>

  1. ifndef bool_t typedef unsigned char bool_t;
  2. endif
  1. define I2C 0x01
  2. define SPI 0x00
  1. define COMMS_BUFFER_SIZE 64 MUST be the same size as the SV task buffer <</code>>

上記のI2CとSPIの定義をコメントアウトするだけです。
そこで、ST製ライブラリーでI2CタイプのLCDと一緒に制御してみました。

Import programHelloWorld_53L0A1_with_I2C_device

added I2C control function (Original program cannot handle I2C constructor)


ちゃんと、制御できました。
私の改造ライブラリーの作成意図が大分薄れてしまいました。
<-Feb.6th,'18

其の四
Feb.6th,'18->
レジスターの内容が開示されていない理由が判明しました。
ここに質問が出されており、それに対して回答者がST Supportからメール返信されたものを紹介しています。
https://community.st.com/thread/7504
ちょっと驚きで、
VL53L0X is a complex device. Registers description is not possible for this device due to complexity.
と、不可能だと言って提供しない理由を述べています。
仕様書が記述できないのに、シリコンチップが出来るのはすごいことです。
STマイクロのソフトウェアエンジニアは、何を根拠に制御ソフトを作成したのでしょうか?
<-Feb.6th,'18

安価で面白いセンサーであることには、間違いありません。


Please log in to post comments.