サーマルカメラ(サーモ AI デバイス TiD) Python VL53L0X編

Pololu Time-of-Flight 距離センサモジュール VL53L0Xの距離データを、I2C通信で取得します。

***
1. [紹介編](https://qiita.com/MH-SS/items/c3d12abe871bfd62d1df)
2. [センサ編](https://qiita.com/MH-SS/items/61021e58b3a5a7f81b3d)
3. [センサケース編](https://qiita.com/MH-SS/items/ab142942c702eb6e545f)
4. [Raspberry Pi編](https://qiita.com/MH-SS/items/73f09db1ad1890c90987)
5. Python編  
    5.1 [Form編](https://qiita.com/MH-SS/items/035682853d18dc2074f2)  
    5.2 [オムロン 非接触温度センサ D6T-44L-06編](https://qiita.com/MH-SS/items/f9301bde143de482a17a)  
    5.3 [Pololu 測距センサ VL53L0X編](https://qiita.com/MH-SS/items/df3c33a6256a533d4eb5)  
    5.4 [BOSCH 温湿度・気圧センサ BME280](https://qiita.com/MH-SS/items/aff10e7b4d84c1b03714)  
    5.5 [シャットダウン・再起動スイッチ編](https://qiita.com/MH-SS/items/82db17524553e56d7605)  
    5.6 [OpenCV編](https://qiita.com/MH-SS/items/bcc9092bb9b6977014a1)  
    5.7 [高速化編](https://qiita.com/MH-SS/items/154dd994d73b4c93854f)  

***

![vl53l0x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569469/685b511c-2bd7-9a17-7e73-6ea695ba0e07.jpeg)
Raspberry Pi上のPythonでVL53L0Xからデータを取得する為に、adafruit-circuitpython-vl53l0xモジュールを使用します。
adafruit-circuitpython-vl53l0xモジュールがインストールされていない場合、下記コマンドでインストールしてください。

```
sudo pip3 install adafruit-circuitpython-vl53l0x
```

vl53l0x.pyはパッケージとしてimportして使用しますが、テスト用に単体で距離データを取得できます。
<a href="https://mhss.server-on.net/a656d/index/tid3/development/python/vl53l0x/vl53l0x.zip" target="_blank">vl53l0x.py (ZIPで圧縮済)</a>

```
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
MH VL53L0X script.
==================
"""
import threading
import time

i2c_enable = False
try:
    import adafruit_vl53l0x
    import board
    import busio
    i2c_enable = True
except:
    i2c_enable = False
import numpy as np
import random


class VL53L0X():
    def __init__(self, *args, **kwargs):
        """
        mesure length: 30 - 2000[mm]
        Optionally adjust the measurement timing budget to change speed and accuracy.
        See the example here for more details:
          https://github.com/pololu/vl53l0x-arduino/blob/master/examples/Single/Single.ino
        For example a higher speed but less accurate timing budget of 20ms:
        vl53.measurement_timing_budget = 20000
            Or a slower but more accurate timing budget of 200ms:
        vl53.measurement_timing_budget = 200000
        The default timing budget is 33ms, a good compromise of speed and accuracy.
        ***
        avg: Average counts.
        range: Default is (30, 2000).
        in_range: If distance is inth range then True.
        """
        self.i2c_enable = i2c_enable

        self._distance = 0
        self._history = []
        self._shutdowning = False
        self._in_range = False

        self._avg = 1
        self.avg = kwargs.get('avg', self._avg)

        self._range = (30, 2000)
        self.range = kwargs.get('range', self._range)

        self.vl53 = None
        if self.i2c_enable:
            i2c = busio.I2C(board.SCL, board.SDA)
            try:
                self.vl53 = adafruit_vl53l0x.VL53L0X(i2c)
            except:
                self.i2c_enable = False

        self._processing()

    def __call__(self, *args, **kwargs):
        return self.distance

    @property
    def avg(self):
        return self._avg
    @avg.setter
    def avg(self, value):
        self._avg = value
        self._history = [0]
        for _ in range(self.avg - 1):
            self._history.append(0)

    def __del__(self):
        self._shutdowning = True

    @property
    def distance(self):
        return self._distance

    @property
    def in_range(self):
        return self._in_range

    def _processing(self):
        if self._shutdowning:
            return

        tmp = 0
        if self.i2c_enable:
            # For I2C error at pushed power switch.
            try:
                tmp = self.vl53.range
            except:
                pass
        else:
            # This value is for D6T-44L-06.
            tmp = random.randint(500, 550)

        if tmp <= 2000:
            self._history[1: self.avg] = self._history[0: self.avg - 1]
            self._history[0] = tmp

        self._distance = np.average(self._history)

        if (self._distance >= self._range[0]) \
                & (self._distance <= self._range[1]):
            self._in_range = True
        else:
            self._in_range = False

        time.sleep(0.1)

        thread = threading.Thread(
            name='VL53L0X_Measuring',
            target=self._processing,
        )
        thread.daeom = True
        thread.start()

    @property
    def range(self):
        return self._range
    @range.setter
    def range(self, value):
        self._range = value

    def stop(self):
        self._shutdowning = True


if __name__ == '__main__':
    vl = VL53L0X(avg=10)
    while True:
        print(f'Range: {vl()}[mm] {vl.in_range}')
        time.sleep(0.1)
    pass
```

***
[YouTube: サーマルカメラ(サーモ AI デバイス TiD) Python編](https://www.youtube.com/watch?v=fgwBsISDtXo)
[web: サーモ AI デバイス TiD Python D6T編](https://mhss.server-on.net/?f401c=Index&ae504=tid3/development/python/vl53l0x) (URLが変更されました)