UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

ESP32でVL53L1X(レーザー測距センサー)モジュールをMicroPythonで操作

ESP32_WROOM_32EとI2Cを介してVL53L1X(測距センサー)を次のように取り付けた場合の情報です。 VL53L1X(測距センサー)は内部レジスタの初期化処理が非常に複雑なため、ドライバライブラリを通して制御するのが一般的らしいです。
VL53L1Xは電源投入直後、基板内部の多くのレジスタが不定値または最小限の待機状態になっています。
そしてSTマイクロエレクトロニクス社が提供する公式API(ULD: Ultra Lite Driver)や一般的なライブラリでは、 センサー初期化関数の中で以下で示す書き込み(Burst Write)が必要する仕様になっているそうです。
Pythonの場合であれば、Adafruit(エイダフルート)のadafruit_vl53l1xモジュールなどが使われます。
ですが、Micropythonではドライバライブラリが見つかりませんでした。(20260810)
それで、STMicroelectronicsのVL53L1X Ultra Lite Driver(STSW-IMG009)のAPIおよびレジスタ設定を参考に、 ESP32/MicroPython向けのコードをAIに生成することにしました。
以下は、ChatGPTを利用して生成したコード(vl53l1x_uld.py)です。
from machine import I2C
import time


class VL53L1X:
    """
    VL53L1X ULD(Ultra Lite Driver)-style minimal driver
    Based on STSW-IMG009 / VL53L1X ULD register operations.

    Tested target:
        ESP32-WROOM-32E
        MicroPython

    Default I2C address:
        0x29 (7-bit)
    """

    # ------------------------------------------------------------
    # I2C
    # ------------------------------------------------------------

    DEFAULT_ADDRESS = 0x29

    # ------------------------------------------------------------
    # Identification
    # ------------------------------------------------------------

    IDENTIFICATION__MODEL_ID = 0x010F
    IDENTIFICATION__MODULE_TYPE = 0x0110
    IDENTIFICATION__REVISION_ID = 0x0111
    IDENTIFICATION__MODULE_ID = 0x0112

    # ------------------------------------------------------------
    # Boot / VHV
    # ------------------------------------------------------------

    FIRMWARE__SYSTEM_STATUS = 0x00E5
    VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND = 0x0008

    # ------------------------------------------------------------
    # GPIO / interrupt
    # ------------------------------------------------------------

    GPIO_HV_MUX__CTRL = 0x0030
    GPIO__TIO_HV_STATUS = 0x0031

    SYSTEM__INTERRUPT_CONFIG_GPIO = 0x0046
    SYSTEM__INTERRUPT_CLEAR = 0x0086

    # ------------------------------------------------------------
    # Timing / distance mode
    # ------------------------------------------------------------

    PHASECAL_CONFIG__TIMEOUT_MACROP = 0x004B

    RANGE_CONFIG__TIMEOUT_MACROP_A_HI = 0x005E
    RANGE_CONFIG__TIMEOUT_MACROP_B_HI = 0x0061

    RANGE_CONFIG__VCSEL_PERIOD_A = 0x0060
    RANGE_CONFIG__VCSEL_PERIOD_B = 0x0063

    RANGE_CONFIG__SIGMA_THRESH = 0x0064
    RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS = 0x0066

    RANGE_CONFIG__VALID_PHASE_HIGH = 0x0069

    SD_CONFIG__WOI_SD0 = 0x0078
    SD_CONFIG__INITIAL_PHASE_SD0 = 0x007A

    # ------------------------------------------------------------
    # ROI
    # ------------------------------------------------------------

    ROI_CONFIG__USER_ROI_CENTRE_SPAD = 0x007F
    ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE = 0x0080

    # ------------------------------------------------------------
    # Measurement control
    # ------------------------------------------------------------

    SYSTEM__SEQUENCE_CONFIG = 0x0081
    SYSTEM__MODE_START = 0x0087

    # ------------------------------------------------------------
    # Result
    # ------------------------------------------------------------

    RESULT__RANGE_STATUS = 0x0089
    RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x008C
    RESULT__AMBIENT_COUNT_RATE_MCPS_SD = 0x0090

    RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 = 0x0096
    RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 = 0x0098

    # ------------------------------------------------------------
    # Distance modes
    # ------------------------------------------------------------

    DISTANCE_MODE_SHORT = 1
    DISTANCE_MODE_LONG = 2

    # ------------------------------------------------------------
    # ULD default configuration
    #
    # STSW-IMG009:
    #   VL53L1X_DEFAULT_CONFIGURATION[]
    #
    # Applied to registers:
    #   0x2D ... 0x87
    #
    # I2C level:
    #   0x2E = 0x00
    #   because the normal VL53L1X module uses 1.8V I2C
    #   internally.
    #
    # For the commonly used modules, this is the ST ULD default.
    # ------------------------------------------------------------

    DEFAULT_CONFIGURATION = bytes([
        0x00,  # 0x2D
        0x00,  # 0x2E
        0x00,  # 0x2F
        0x01,  # 0x30
        0x02,  # 0x31
        0x00,  # 0x32
        0x02,  # 0x33
        0x08,  # 0x34
        0x00,  # 0x35
        0x08,  # 0x36
        0x10,  # 0x37
        0x01,  # 0x38
        0x01,  # 0x39
        0x00,  # 0x3A
        0x00,  # 0x3B
        0x00,  # 0x3C
        0x00,  # 0x3D
        0xFF,  # 0x3E
        0x00,  # 0x3F
        0x0F,  # 0x40
        0x00,  # 0x41
        0x00,  # 0x42
        0x00,  # 0x43
        0x00,  # 0x44
        0x00,  # 0x45
        0x20,  # 0x46
        0x0B,  # 0x47
        0x00,  # 0x48
        0x00,  # 0x49
        0x02,  # 0x4A
        0x0A,  # 0x4B
        0x21,  # 0x4C
        0x00,  # 0x4D
        0x00,  # 0x4E
        0x05,  # 0x4F
        0x00,  # 0x50
        0x00,  # 0x51
        0x00,  # 0x52
        0x00,  # 0x53
        0xC8,  # 0x54
        0x00,  # 0x55
        0x00,  # 0x56
        0x38,  # 0x57
        0xFF,  # 0x58
        0x01,  # 0x59
        0x00,  # 0x5A
        0x08,  # 0x5B
        0x00,  # 0x5C
        0x00,  # 0x5D
        0x01,  # 0x5E
        0xCC,  # 0x5F
        0x0F,  # 0x60
        0x01,  # 0x61
        0xF1,  # 0x62
        0x0D,  # 0x63
        0x01,  # 0x64
        0x68,  # 0x65
        0x00,  # 0x66
        0x80,  # 0x67
        0x08,  # 0x68
        0xB8,  # 0x69
        0x00,  # 0x6A
        0x00,  # 0x6B
        0x00,  # 0x6C
        0x00,  # 0x6D
        0x0F,  # 0x6E
        0x89,  # 0x6F
        0x00,  # 0x70
        0x00,  # 0x71
        0x00,  # 0x72
        0x00,  # 0x73
        0x00,  # 0x74
        0x00,  # 0x75
        0x00,  # 0x76
        0x01,  # 0x77
        0x0F,  # 0x78
        0x0D,  # 0x79
        0x0E,  # 0x7A
        0x0E,  # 0x7B
        0x00,  # 0x7C
        0x00,  # 0x7D
        0x02,  # 0x7E
        0xC7,  # 0x7F
        0xFF,  # 0x80
        0x9B,  # 0x81
        0x00,  # 0x82
        0x00,  # 0x83
        0x00,  # 0x84
        0x01,  # 0x85
        0x00,  # 0x86
        0x00,  # 0x87
    ])

    # ------------------------------------------------------------
    # Timing budget tables
    #
    # ULD SetTimingBudgetInMs()
    #
    # [distance mode] :
    #     timeout A
    #     timeout B
    # ------------------------------------------------------------

    TIMING_SHORT = {
        15:  (0x001D, 0x0027),
        20:  (0x0051, 0x006E),
        33:  (0x00D6, 0x006E),
        50:  (0x01AE, 0x01E8),
        100: (0x02E1, 0x0388),
        200: (0x03E1, 0x0496),
        500: (0x0591, 0x05C1),
    }

    TIMING_LONG = {
        20:  (0x001E, 0x0022),
        33:  (0x0060, 0x006E),
        50:  (0x00AD, 0x00C6),
        100: (0x01CC, 0x01EA),
        200: (0x02D9, 0x02F8),
        500: (0x048F, 0x04A4),
    }

    # ------------------------------------------------------------

    def __init__(self, i2c, address=DEFAULT_ADDRESS, debug=False):
        self.i2c = i2c
        self.address = address
        self.debug = debug

        self.distance_mode = self.DISTANCE_MODE_LONG
        self.timing_budget_ms = 50

    # ============================================================
    # Low level I2C
    # ============================================================

    def _write8(self, reg, value):
        buf = bytes([
            (reg >> 8) & 0xFF,
            reg & 0xFF,
            value & 0xFF
        ])

        self.i2c.writeto(self.address, buf)

        if self.debug:
            print("W8  %04X <- %02X" % (reg, value))

    def _write16(self, reg, value):
        buf = bytes([
            (reg >> 8) & 0xFF,
            reg & 0xFF,
            (value >> 8) & 0xFF,
            value & 0xFF
        ])

        self.i2c.writeto(self.address, buf)

        if self.debug:
            print("W16 %04X <- %04X" % (reg, value))

    def _write32(self, reg, value):
        buf = bytes([
            (reg >> 8) & 0xFF,
            reg & 0xFF,
            (value >> 24) & 0xFF,
            (value >> 16) & 0xFF,
            (value >> 8) & 0xFF,
            value & 0xFF
        ])

        self.i2c.writeto(self.address, buf)

        if self.debug:
            print("W32 %04X <- %08X" % (reg, value))

    def _read8(self, reg):
        self.i2c.writeto(
            self.address,
            bytes([
                (reg >> 8) & 0xFF,
                reg & 0xFF
            ])
        )

        value = self.i2c.readfrom(self.address, 1)[0]

        if self.debug:
            print("R8  %04X -> %02X" % (reg, value))

        return value

    def _read16(self, reg):
        self.i2c.writeto(
            self.address,
            bytes([
                (reg >> 8) & 0xFF,
                reg & 0xFF
            ])
        )

        data = self.i2c.readfrom(self.address, 2)

        value = (data[0] << 8) | data[1]

        if self.debug:
            print("R16 %04X -> %04X" % (reg, value))

        return value

    def _read32(self, reg):
        self.i2c.writeto(
            self.address,
            bytes([
                (reg >> 8) & 0xFF,
                reg & 0xFF
            ])
        )

        data = self.i2c.readfrom(self.address, 4)

        value = (
            (data[0] << 24) |
            (data[1] << 16) |
            (data[2] << 8) |
            data[3]
        )

        if self.debug:
            print("R32 %04X -> %08X" % (reg, value))

        return value

    # ============================================================
    # Identification
    # ============================================================

    def get_model_id(self):
        return self._read8(self.IDENTIFICATION__MODEL_ID)

    def get_module_type(self):
        return self._read8(self.IDENTIFICATION__MODULE_TYPE)

    def get_revision_id(self):
        return self._read8(self.IDENTIFICATION__REVISION_ID)

    def get_module_id(self):
        return self._read16(self.IDENTIFICATION__MODULE_ID)

    def check_device(self):
        model = self.get_model_id()

        if model != 0xEA:
            raise RuntimeError(
                "VL53L1X model ID error: 0x%02X" % model
            )

        return True

    # ============================================================
    # Boot
    # ============================================================

    def boot_state(self):
        """
        ST ULD VL53L1X_BootState()

        0 = not booted
        non-zero = booted
        """

        return self._read8(
            self.FIRMWARE__SYSTEM_STATUS
        ) != 0

    def wait_booted(self, timeout_ms=1000):
        start = time.ticks_ms()

        while not self.boot_state():
            if time.ticks_diff(
                time.ticks_ms(),
                start
            ) > timeout_ms:
                raise RuntimeError(
                    "VL53L1X boot timeout"
                )

            time.sleep_ms(5)

    # ============================================================
    # SensorInit
    # ============================================================

    def sensor_init(self):
        """
        Equivalent to STSW-IMG009 VL53L1X_SensorInit().

        This is the ULD equivalent of the initialization stage.
        It is NOT the Full API DataInit()/StaticInit() split.
        """

        self.check_device()

        # --------------------------------------------------------
        # ST ULD:
        #
        # for (Addr = 0x2D; Addr <= 0x87; Addr++)
        #     WrByte(Addr, DEFAULT_CONFIGURATION[Addr - 0x2D])
        # --------------------------------------------------------

        for offset in range(len(self.DEFAULT_CONFIGURATION)):
            reg = 0x2D + offset
            value = self.DEFAULT_CONFIGURATION[offset]

            self._write8(reg, value)

        # --------------------------------------------------------
        # ULD SensorInit performs one initial ranging operation.
        # --------------------------------------------------------

        self.start_measurement()

        self.wait_data_ready(
            timeout_ms=1000
        )

        self.clear_interrupt()

        self.stop_measurement()

        # --------------------------------------------------------
        # VHV configuration after the initial measurement.
        # --------------------------------------------------------

        self._write8(
            self.VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND,
            0x09
        )

        self._write8(
            0x000B,
            0x00
        )

    # ============================================================
    # Distance mode
    # ============================================================

    def set_distance_mode(self, mode):
        """
        ST ULD:
            1 = Short
            2 = Long
        """

        if mode not in (
            self.DISTANCE_MODE_SHORT,
            self.DISTANCE_MODE_LONG
        ):
            raise ValueError(
                "distance mode must be 1 or 2"
            )

        # Save current timing budget.
        old_budget = self.timing_budget_ms

        if mode == self.DISTANCE_MODE_SHORT:

            # PHASECAL_CONFIG__TIMEOUT_MACROP
            self._write8(
                self.PHASECAL_CONFIG__TIMEOUT_MACROP,
                0x14
            )

            # VCSEL period A
            self._write8(
                self.RANGE_CONFIG__VCSEL_PERIOD_A,
                0x07
            )

            # VCSEL period B
            self._write8(
                self.RANGE_CONFIG__VCSEL_PERIOD_B,
                0x05
            )

            # Valid phase high
            self._write8(
                self.RANGE_CONFIG__VALID_PHASE_HIGH,
                0x38
            )

            # WOI SD0
            self._write16(
                self.SD_CONFIG__WOI_SD0,
                0x0705
            )

            # Initial phase SD0
            self._write16(
                self.SD_CONFIG__INITIAL_PHASE_SD0,
                0x0606
            )

        else:

            # PHASECAL_CONFIG__TIMEOUT_MACROP
            self._write8(
                self.PHASECAL_CONFIG__TIMEOUT_MACROP,
                0x0A
            )

            # VCSEL period A
            self._write8(
                self.RANGE_CONFIG__VCSEL_PERIOD_A,
                0x0F
            )

            # VCSEL period B
            self._write8(
                self.RANGE_CONFIG__VCSEL_PERIOD_B,
                0x0D
            )

            # Valid phase high
            self._write8(
                self.RANGE_CONFIG__VALID_PHASE_HIGH,
                0xB8
            )

            # WOI SD0
            self._write16(
                self.SD_CONFIG__WOI_SD0,
                0x0F0D
            )

            # Initial phase SD0
            self._write16(
                self.SD_CONFIG__INITIAL_PHASE_SD0,
                0x0E0E
            )

        self.distance_mode = mode

        # ST ULD re-applies the previous timing budget
        # after changing distance mode.
        if old_budget is not None:
            self.set_timing_budget(old_budget)

    # ============================================================
    # Timing budget
    # ============================================================

    def set_timing_budget(self, budget_ms):
        """
        STSW-IMG009 supported timing budgets:

        Short:
            15, 20, 33, 50, 100, 200, 500 ms

        Long:
            20, 33, 50, 100, 200, 500 ms
        """

        if self.distance_mode == self.DISTANCE_MODE_SHORT:
            table = self.TIMING_SHORT
        else:
            table = self.TIMING_LONG

        if budget_ms not in table:
            raise ValueError(
                "timing budget %d ms is not valid for "
                "distance mode %d"
                % (
                    budget_ms,
                    self.distance_mode
                )
            )

        timeout_a, timeout_b = table[budget_ms]

        self._write16(
            self.RANGE_CONFIG__TIMEOUT_MACROP_A_HI,
            timeout_a
        )

        self._write16(
            self.RANGE_CONFIG__TIMEOUT_MACROP_B_HI,
            timeout_b
        )

        self.timing_budget_ms = budget_ms

    # ============================================================
    # Get timing budget
    # ============================================================

    def get_timing_budget(self):
        a = self._read16(
            self.RANGE_CONFIG__TIMEOUT_MACROP_A_HI
        )

        if self.distance_mode == self.DISTANCE_MODE_SHORT:

            values = {
                0x001D: 15,
                0x0051: 20,
                0x00D6: 33,
                0x01AE: 50,
                0x02E1: 100,
                0x03E1: 200,
                0x0591: 500,
            }

        else:

            values = {
                0x001E: 20,
                0x0060: 33,
                0x00AD: 50,
                0x01CC: 100,
                0x02D9: 200,
                0x048F: 500,
            }

        return values.get(a, 0)

    # ============================================================
    # Measurement
    # ============================================================

    def start_measurement(self):
        """
        SYSTEM__MODE_START = 0x40
        """

        self._write8(
            self.SYSTEM__MODE_START,
            0x40
        )

    def stop_measurement(self):
        """
        SYSTEM__MODE_START = 0x00
        """

        self._write8(
            self.SYSTEM__MODE_START,
            0x00
        )

    # ============================================================
    # Interrupt polarity
    # ============================================================

    def get_interrupt_polarity(self):

        value = self._read8(
            self.GPIO_HV_MUX__CTRL
        )

        # ST:
        # Temp = Temp & 0x10
        # polarity = !(Temp >> 4)

        return 0 if (value & 0x10) else 1

    def set_interrupt_polarity(self, polarity):

        value = self._read8(
            self.GPIO_HV_MUX__CTRL
        )

        value &= 0xEF

        value |= (
            0x00 if (polarity & 1)
            else 0x10
        )

        self._write8(
            self.GPIO_HV_MUX__CTRL,
            value
        )

    # ============================================================
    # Data ready
    # ============================================================

    def data_ready(self):

        polarity = self.get_interrupt_polarity()

        status = self._read8(
            self.GPIO__TIO_HV_STATUS
        )

        return (status & 0x01) == polarity

    def wait_data_ready(self, timeout_ms=1000):

        start = time.ticks_ms()

        while not self.data_ready():

            if time.ticks_diff(
                time.ticks_ms(),
                start
            ) > timeout_ms:
                raise RuntimeError(
                    "VL53L1X data-ready timeout"
                )

            time.sleep_ms(1)

    # ============================================================
    # Clear interrupt
    # ============================================================

    def clear_interrupt(self):

        self._write8(
            self.SYSTEM__INTERRUPT_CLEAR,
            0x01
        )

    # ============================================================
    # Ranging result
    # ============================================================

    def get_ranging_measurement_data(self):

        status = self._read8(
            self.RESULT__RANGE_STATUS
        )

        distance_mm = self._read16(
            self.RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0
        )

        ambient = self._read16(
            self.RESULT__AMBIENT_COUNT_RATE_MCPS_SD
        )

        signal = self._read16(
            self.RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0
        )

        spads = self._read16(
            self.RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0
        )

        return {
            "status": status,
            "distance_mm": distance_mm,
            "ambient": ambient,
            "signal": signal,
            "spads": spads,
        }

    # ============================================================
    # One-shot convenience function
    # ============================================================

    def read(self):

        self.wait_data_ready()

        result = self.get_ranging_measurement_data()

        self.clear_interrupt()

        return result

    # ============================================================
    # Initialize everything
    # ============================================================

    def init(
        self,
        distance_mode=DISTANCE_MODE_LONG,
        timing_budget_ms=50
    ):

        # Wait until the embedded firmware is booted.
        self.wait_booted()

        # STSW-IMG009 SensorInit().
        self.sensor_init()

        # Configure distance mode.
        self.set_distance_mode(
            distance_mode
        )

        # Configure timing budget.
        self.set_timing_budget(
            timing_budget_ms
        )

        # Start continuous ranging.
        self.start_measurement()

    # ============================================================
    # Continuous measurement generator
    # ============================================================

    def measurements(self):

        while True:

            self.wait_data_ready()

            result = (
                self.get_ranging_measurement_data()
            )

            self.clear_interrupt()

            yield result
    

上記ドライバの利用例(AI生成コード)
from machine import Pin, I2C
import time

from vl53l1x_uld import VL53L1X


# ------------------------------------------------------------
# I2C
# ------------------------------------------------------------

i2c = I2C(
    0,
    scl=Pin(22),
    sda=Pin(21),
    freq=400000
)

print("I2C scan:", [
    hex(x) for x in i2c.scan()
])


# ------------------------------------------------------------
# VL53L1X
# ------------------------------------------------------------

tof = VL53L1X(
    i2c,
    address=0x29,
    debug=False
)


print("Model ID    :", hex(tof.get_model_id()))
print("Module Type :", hex(tof.get_module_type()))
print("Revision    :", hex(tof.get_revision_id()))
print("Module ID   :", hex(tof.get_module_id()))


# ------------------------------------------------------------
# Initialize
#
# Long mode
# 50 ms timing budget
# ------------------------------------------------------------

tof.init(
    distance_mode=VL53L1X.DISTANCE_MODE_LONG,
    timing_budget_ms=50
)

print("VL53L1X initialized")
print(
    "Distance mode:",
    tof.distance_mode
)
print(
    "Timing budget:",
    tof.get_timing_budget(),
    "ms"
)


# ------------------------------------------------------------
# Continuous ranging
# ------------------------------------------------------------

for _ in range(20):

    result = tof.read()

    print(
        "distance=%4d mm  "
        "status=%d  "
        "ambient=%d  "
        "signal=%d  "
        "spads=%d"
        % (
            result["distance_mm"],
            result["status"],
            result["ambient"],
            result["signal"],
            result["spads"]
        )
    )

    time.sleep_ms(10)



上記の実行例
R:\drone>mpremote connect COM3 run vl53l1x_uld_test.py
I2C scan: ['0x29']
Model ID    : 0xea
Module Type : 0xcc
Revision    : 0x10
Module ID   : 0xfffe
VL53L1X initialized
Distance mode: 2
Timing budget: 50 ms
distance= 821 mm  status=9  ambient=28  signal=1492  spads=52200
distance= 820 mm  status=9  ambient=28  signal=1477  spads=52200
	・・・・・省略・・・・・
distance= 825 mm  status=9  ambient=30  signal=1508  spads=52200

R:\drone>

補足

VL53L1Xの初期化時にレジスタアドレス 0x002D から 0x0087 へ連続書き込みされるデフォルト設定値(ST公式Ultra Lite Driver仕様)のコメントです。
DEFAULT_CONFIGURATION = bytes([
    0x00,  # 0x2D: VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND (VHVキャリブレーション タイムアウト制御)
    0x00,  # 0x2E: VHV_CONFIG__COUNT_THRESH (VHVカウント閾値)
    0x00,  # 0x2F: ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS (クロストーク補正オフセット [MSB])
    0x01,  # 0x30: ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS (クロストーク補正オフセット [LSB])
    0x02,  # 0x31: ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS (クロストークX方向勾配 [MSB])
    0x00,  # 0x32: ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS (クロストークX方向勾配 [LSB])
    0x02,  # 0x33: ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS (クロストークY方向勾配 [MSB])
    0x08,  # 0x34: ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS (クロストークY方向勾配 [LSB])
    0x00,  # 0x35: ALGO__PAUSE_SOLID_ARRAY_CHECK (ソリッドアレイ検証の一時停止フラグ)
    0x08,  # 0x36: ALGO__PART_TO_PART_RANGE_OFFSET_MM (個体差距離補正オフセット(mm) [MSB])
    0x10,  # 0x37: ALGO__PART_TO_PART_RANGE_OFFSET_MM (個体差距離補正オフセット(mm) [LSB])
    0x01,  # 0x38: MM_CONFIG__INNER_OFFSET_MM (内部測定領域オフセット(mm) [MSB])
    0x01,  # 0x39: MM_CONFIG__INNER_OFFSET_MM (内部測定領域オフセット(mm) [LSB])
    0x00,  # 0x3A: MM_CONFIG__OUTER_OFFSET_MM (外部測定領域オフセット(mm) [MSB])
    0x00,  # 0x3B: MM_CONFIG__OUTER_OFFSET_MM (外部測定領域オフセット(mm) [LSB])
    0x00,  # 0x3C: DSS_CONFIG__TARGET_TOTAL_RATE_MCPS (DSS目標トータルリターンレート(Mcps) [MSB])
    0x00,  # 0x3D: DSS_CONFIG__TARGET_TOTAL_RATE_MCPS (DSS目標トータルリターンレート(Mcps) [LSB])
    0xFF,  # 0x3E: DEBUG__CTRL (内部デバッグ制御)
    0x00,  # 0x3F: TEST_MODE__CTRL (テストモード制御)
    0x0F,  # 0x40: CLK__CONFIG (内部メインクロック設定)
    0x00,  # 0x41: SYSTEM__START (システムトリガー/開始制御)
    0x00,  # 0x42: SYSTEM__HISTORY_CTRL (履歴バッファ制御)
    0x00,  # 0x43: SYSTEM__STREAM_COUNT_CTRL (ストリームカウント制御)
    0x00,  # 0x44: SYSTEM__SEQUENCE_CONFIG (測定シーケンス有効化設定)
    0x00,  # 0x45: SYSTEM__GROUPED_PARAMETER_HOLD_0 (パラメータ一括適用保持 0)
    0x20,  # 0x46: VHV_CONFIG__INIT (VHV初期化制御)
    0x0B,  # 0x47: VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND (VHVループ制限値)
    0x00,  # 0x48: MYCRO_TUNE (内部アナログチューニング 1)
    0x00,  # 0x49: MYCRO_TUNE (内部アナログチューニング 2)
    0x02,  # 0x4A: GLOBAL_CONFIG__SPAD_ENABLES_REF_0 (参照SPAD有効化マップ 0)
    0x0A,  # 0x4B: GLOBAL_CONFIG__SPAD_ENABLES_REF_1 (参照SPAD有効化マップ 1)
    0x21,  # 0x4C: GLOBAL_CONFIG__SPAD_ENABLES_REF_2 (参照SPAD有効化マップ 2)
    0x00,  # 0x4D: GLOBAL_CONFIG__SPAD_ENABLES_REF_3 (参照SPAD有効化マップ 3)
    0x00,  # 0x4E: GLOBAL_CONFIG__SPAD_ENABLES_REF_4 (参照SPAD有効化マップ 4)
    0x05,  # 0x4F: GLOBAL_CONFIG__SPAD_ENABLES_REF_5 (参照SPAD有効化マップ 5)
    0x00,  # 0x50: GLOBAL_CONFIG__REF_EN_START_SELECT (参照SPAD開始選択)
    0x00,  # 0x51: REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS (要求参照SPAD数)
    0x00,  # 0x52: REF_SPAD_MAN__REF_LOCATION (参照SPAD配置場所)
    0x00,  # 0x53: ALGO__CONSISTENCY_CHECK__REFERENCE_SIGNAL_NON_KIN_INTRINSIC (参照信号整合性チェック)
    0xC8,  # 0x54: ALGO__CONSISTENCY_CHECK__EVENT_CONSISTENCY (イベント整合性閾値 0)
    0x00,  # 0x55: ALGO__CONSISTENCY_CHECK__EVENT_CONSISTENCY (イベント整合性閾値 1)
    0x00,  # 0x56: ALGO__CONSISTENCY_CHECK__EVENT_CONSISTENCY (イベント整合性閾値 2)
    0x38,  # 0x57: ALGO__CONSISTENCY_CHECK__EVENT_CONSISTENCY (イベント整合性閾値 3)
    0xFF,  # 0x58: ALGO__RANGE_IGNORE_THRESHOLD_MCPS (無視するノイズ距離閾値 [MSB])
    0x01,  # 0x59: ALGO__RANGE_IGNORE_THRESHOLD_MCPS (無視するノイズ距離閾値 [LSB])
    0x00,  # 0x5A: ALGO__RANGE_MIN_CLIP (最小クリッピング範囲)
    0x08,  # 0x5B: ALGO__CONSISTENCY_CHECK__TOTAL_RATE_PER_SPAD_MCPS (SPADあたりレート整合性 [MSB])
    0x00,  # 0x5C: ALGO__CONSISTENCY_CHECK__TOTAL_RATE_PER_SPAD_MCPS (SPADあたりレート整合性 [LSB])
    0x00,  # 0x5D: SD_CONFIG__WOI_CONFIG (受光タイミングウィンドウWOI設定 0)
    0x01,  # 0x5E: SD_CONFIG__WOI_CONFIG (受光タイミングウィンドウWOI設定 1)
    0xCC,  # 0x5F: SD_CONFIG__INITIAL_PHASE_CONFIG (初期位相設定 0)
    0x0F,  # 0x60: SD_CONFIG__INITIAL_PHASE_CONFIG (初期位相設定 1)
    0x01,  # 0x61: SYSTEM__GROUPED_PARAMETER_HOLD_0 (パラメータ更新の保留設定)
    0xF1,  # 0x62: SYSTEM__THRESH_HIGH (距離割り込み上限閾値 [MSB])
    0x0D,  # 0x63: SYSTEM__THRESH_HIGH (距離割り込み上限閾値 [LSB])
    0x01,  # 0x64: SYSTEM__THRESH_LOW (距離割り込み下限閾値 [MSB])
    0x68,  # 0x65: SYSTEM__THRESH_LOW (距離割り込み下限閾値 [LSB])
    0x00,  # 0x66: SYSTEM__ENABLE_CONFIG_0 (システム機能有効化フラグ 0)
    0x80,  # 0x67: SYSTEM__ENABLE_CONFIG_1 (システム機能有効化フラグ 1)
    0x08,  # 0x68: SYSTEM__SEQUENCE_CONFIG (シーケンサ動作制御)
    0xB8,  # 0x69: SYSTEM__HISTOGRAM_BIN (ヒストグラムBin初期構成)
    0x00,  # 0x6A: ROI_CONFIG__USER_ROI_CENTRE_SPAD (ユーザー設定ROIの中心SPAD番号)
    0x00,  # 0x6B: ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE (ユーザー設定ROIのXYサイズ)
    0x00,  # 0x6C: SYSTEM__CONFIG_VALID_HEADER (設定ヘッダー有効検証)
    0x00,  # 0x6D: SYSTEM__SEQUENCE_CONFIG (内部シーケンス追加制御)
    0x0F,  # 0x6E: SYSTEM__GROUPED_PARAMETER_HOLD_1 (一括パラメータ保持 1)
    0x89,  # 0x6F: SYSTEM__GROUPED_PARAMETER_HOLD (一括パラメータ保持トリガー)
    0x00,  # 0x70: SD_CONFIG__QUANTIFIER_CONFIG (シグナル検出クオンティファイア設定)
    0x00,  # 0x71: ROI_CONFIG__ROI_CONTROL (関心領域ROI動的制御)
    0x00,  # 0x72: FIRMWARE__SYSTEM_STATUS (ファームウェアステータス初期化)
    0x00,  # 0x73: INTERRUPT_CONFIG (割り込み信号出力設定)
    0x00,  # 0x74: INTERRUPT_CLEAR (割り込みクリアフラグ)
    0x00,  # 0x75: INTERRUPT_MODE (割り込み検出モード)
    0x00,  # 0x76: GPIO_HV_PAD__CTRL (GPIO高電圧パッド制御)
    0x01,  # 0x77: GPIO_HV_MUX__CTRL (GPIOマルチプレクサ機能選択)
    0x0F,  # 0x78: GPIO__TIO_HV_STATUS (GPIOピン入出力ステータス)
    0x0D,  # 0x79: SYSTEM__INTERRUPT_CLEAR (システム割り込み解除)
    0x0E,  # 0x7A: SYSTEM__MODE_START (測距モード開始/レンジング有効化)
    0x0E,  # 0x7B: PAD_I2C_HV__CONFIG (I2C通信パッド設定)
    0x00,  # 0x7C: ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS (トリミング用補正値 0x7C)
    0x00,  # 0x7D: ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS (トリミング用補正値 0x7D)
    0x02,  # 0x7E: ALGO__PAUSE_SOLID_ARRAY_CHECK (アレイ制御内部トリミング)
    0xC7,  # 0x7F: ALGO__PART_TO_PART_RANGE_OFFSET_MM (内部距離トリミングレジスタ)
    0xFF,  # 0x80: ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS (内部補正トリミングレジスタ)
    0x9B,  # 0x81: GLOBAL_CONFIG__SPAD_ENABLES_REF (内部SPAD調整トリミング)
    0x00,  # 0x82: SD_CONFIG (シグナル検出内部パラメータ 0x82)
    0x00,  # 0x83: SD_CONFIG (シグナル検出内部パラメータ 0x83)
    0x00,  # 0x84: SD_CONFIG (シグナル検出内部パラメータ 0x84)
    0x01,  # 0x85: SD_CONFIG (シグナル検出内部パラメータ 0x85)
    0x00,  # 0x86: SYSTEM__START (システム起動最終確定フラグ)
    0x00,  # 0x87: SYSTEM__GROUPED_PARAMETER_HOLD (一括設定バッファクリア)
])
1.役割:センサーの動作モードと内部パラメータを一括定義する:ST公式ドライバ(Ultra Lite Driver)準拠。 DEFAULT_CONFIGURATION(レジスタ 0x002D ? 0x0087)は、VL53L1Xをリセット状態から正しく動作させるための推奨初期設定値のバイナリ配列です。
  1. クロック・アナログ部の安定化: 内部オシレータやVCSEL(赤外線レーザー)の駆動タイミング調整
  2. SPAD(受光素子)アレイの有効化: レーザーを受光するための素子配置(16x16)の初期化
  3. 補正アルゴリズムの設定: カバーガラス等の影響を抑えるクロストーク補正や距離オフセットの初期パラメータ投入
  4. 割り込み・GPIO制御: 測距完了を通知するGPIOピンや通信パッドの設定