VL53L1X (Time-of-Flight, 長距離測距センサー) を動かしてみる

[adafruit](https://www.adafruit.com/) で VL53L1X と言うセンサーを買ってみたのでそのメモです。

https://www.adafruit.com/product/3967

VL53L1X はレーザで測距を測定するセンサーで  Digi-Key に [日本語での説明説明](https://www.digikey.jp/ja/product-highlight/s/stmicroelectronics/vl53l1x-tof-long-distance-ranging-sensor) があります。

距離を測定するセンサーと言えば音波を使った [HC-SR04](https://www.adafruit.com/product/4007) の方が [300 円](https://akizukidenshi.com/catalog/g/gM-11009/) 程度と安価であり [近い距離ならかなり優秀](https://ambidata.io/samples/m5stack/ranging/) という話もあります。またプログラムもかなり単純でライブラリも GPIO のみで書けたりします。

一方、VL53L1X は [1500円](https://www.adafruit.com/product/3967) くらいしますが個人的には 1 秒間に図れる距離が最大 50 回と高速な読み取りができるのが一番大きな利点と思います。また VL53L1X の方が外部環境の影響を受けにくいと言った特徴もあるようです。プログラム自体はやや複雑になり  I2C 経由でシヨするため Raspberry Pi に直に指す場合は GPIO 2 と GPIO 3 を使用します。

VL53L1X と Raspberry Pi との配線は [ここ](https://learn.adafruit.com/assets/105865)

![adafruit_products_VL53L1X_RasPi_STEMMA_bb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360970/dcb5e38f-7f0e-7499-beb3-15e175f5d6bb.jpeg)

や [ここ](https://learn.adafruit.com/assets/105866)

![adafruit_products_VL53L1X_RasPi_breadboard_bb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360970/3eb04ee5-e3c1-465e-46aa-2ad86850e030.jpeg)

のようになります。Adafruit で同じものを買う場合は [QT To Female Headers](
https://www.adafruit.com/product/4397) や [QT to Male Headers](https://www.adafruit.com/product/4209) を買っておくとはんだ付け不要で配線ができるため便利そうです。

Adafruit のライブラリをインストールして以下のようなプログラムを書くと距離の値を読み込むことができます。注意点としては VL53L1X には保護フィルムがはられているので [使用前に剥がす](https://learn.adafruit.com/adafruit-vl53l1x/overview) のを忘れないでください。

```
# pip3 install adafruit-circuitpython-vl53l1x
# cat VL53L1X.py
import time, datetime, board

import adafruit_vl53l1x

i2c = board.I2C()
vl53 = adafruit_vl53l1x.VL53L1X(i2c)

# SHORT mode
vl53.distance_mode = 1

# Ranging duration in milliseconds: 15 (short mode only), 20, 33, 50, 100, 200, 500
vl53.timing_budget = 20

vl53.start_ranging()

while True:
    try:
        if vl53.data_ready:
            print("{} - Distance: {} cm".format(datetime.datetime.today(), vl53.distance))
            vl53.clear_interrupt()
    except KeyboardInterrupt:
        break
```

動作はこんな感じになります。

```
$ python3 ./VL53L1X.py
2022-01-07 10:07:52.907338 - Distance: 8.3 cm
2022-01-07 10:07:53.009449 - Distance: 10.0 cm
2022-01-07 10:07:53.109584 - Distance: 13.9 cm
2022-01-07 10:07:53.209908 - Distance: 19.1 cm
2022-01-07 10:07:53.310239 - Distance: 25.8 cm
2022-01-07 10:07:53.412281 - Distance: 31.8 cm
2022-01-07 10:07:53.512457 - Distance: 37.4 cm
2022-01-07 10:07:53.612652 - Distance: 41.8 cm
2022-01-07 10:07:53.713085 - Distance: 45.7 cm
2022-01-07 10:07:53.815121 - Distance: 49.2 cm
2022-01-07 10:07:53.915243 - Distance: 49.4 cm
2022-01-07 10:07:54.015543 - Distance: 48.0 cm
```

うーん、1 秒間に 10 回程度しか距離を読めてませんがこれがなんでなのかは不明です。。

当然 [公式のサンプル](https://github.com/adafruit/Adafruit_CircuitPython_VL53L1X/blob/main/examples/vl53l1x_simpletest.py) でも動作の確認はできます。vl53.timing_budget の意味などは [ソースのコメント](https://github.com/adafruit/Adafruit_CircuitPython_VL53L1X/blob/main/adafruit_vl53l1x.py) を参照するのが良さそうです。

```
    def timing_budget(self):
        """Ranging duration in milliseconds. Increasing the timing budget
        increases the maximum distance the device can range and improves
        the repeatability error. However, average power consumption augments
        accordingly. ms = 15 (short mode only), 20, 33, 50, 100, 200, 500."""
        return self._timing_budget

```

余談ですが i2cdetect では 29 として認識されるようです。

```
$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```