ESP32S3 TOFレーザー距離センサの動作テスト

2026.7.6 2026.5.9 Coskx Lab  

1 はじめに

Xiao ESP32S3にTOFレーザー距離センサVL53L1X(STMicroelectronics)を接続して周囲の対象物までの距離を測定します。

VL53L1Xは,赤外線レーザにより4m程度までの距離を測定することができ,ESP32S3にはI2Cでデータを転送します。
VL53L1Xを基板上に取り付けた製品は多数ありますが,ここでは秋月電子で販売されているAE-VL53L1Xを使用します。

付録Aとして,二つのI2Cデバイス(異なるI2Cアドレスを持つ)をマイコンのI2Cピン(D4,D5)に接続した例を載せます。
付録 A  ≫
付録Bとして,マイコンのI2Cピン(D4,D5)以外のピンをI2C用のピンとして使用して,二つ目のI2Cデバイス(異なるI2Cアドレスを持つ)を接続した例を載せます。
付録 B  ≫


2 使用環境

3 接続

マニュアルのピンアサインを見てそのままつなげるだけです。
XSHUTとGPIOはAE-VL53L1X内部でプルアップされているので何もつながないことにします。

名称機能配線色M5Stack配線先
V+3.3~5V 入力3.3V
GNDGNDGND
SDAデータ線SDA (21)
SCLクロック線SCL (22)
XSHUTシャットダウン入力端子接続しない
GPIOGPIO(2.8Vレベル)接続しない



注意1 モータなどのノイズ発生機源と同時にレーザ距離センサを使う場合,使用していないXSHUT(青)とGPIO(紫)の2本もケーブルは,コネクタから外してください。
ノイズの影響でレーザ距離センサが誤動作する場合があります。

注意2 AE-VL53L1XのV+には「3.3~5V 入力」と書いてありますが,これは3.3Vのシステムでも5Vのシステムでも使えますということを表しています。
AE-VL53L1Xはよくできていて,AE-VL53L1Xの電源に3.3Vを与えると3.3VでI2C通信し,5Vを与えると5VでI2C通信します。
ESP32S3で使うとき,ESP32S3の信号レベルは3.3Vであるため,3.3Vで通信したいのでAE-VL53L1Xの電源には3.3Vを与えます。
信号レベルが5Vのマイコンにつなげるときは,5Vで通信したいので5Vを与えます。

4 準備

VL53L1XはI2CでCPUとデータをやり取りしますが,そのためのライブラリが必要です。
Arduino IDEにて,「ツール」メニューから,「ライブラリを管理」を選び,「ライブラリマネージャ」を開きます。
上部にある「タイプ すべて」,「トピック すべて」の右側の長いボックスが検索欄なので,
そこに「VL53L1X」と書き込むと検索されます。複数の「VL53L1X」が見つかりますが,
「by PoLolu」と書いてあるものを選んでインストールします。

5 テストプログラム

https://github.com/pololu/vl53l1x-arduino
を参考にさせていただきました。

  動作テスト用プログラム本体(センサは常時稼働)

//VL53l1x_JustTest.ino
//library: vl53l1x-arduino by Pololu

#include <Wire.h>
#include <VL53L1X.h>

VL53L1X vl53l1x;

void setup() {
  Serial.begin();
  delay(500);
  Wire.begin(SDA,SCL);
  Wire.setClock(400000); // use 400 kHz I2C
  vl53l1x.setTimeout(500); //[msec]
  if (!vl53l1x.init())
  {
    Serial.println("Failed to detect and initialize vl53l1x!");
    while (1);
  }
  vl53l1x.setDistanceMode(VL53L1X::Long);
  //Long (長距離): 最大4mまでの測定。
  vl53l1x.setMeasurementTimingBudget(50000);
  //測定タイミングバジェット(1回の距離測定)に許容される時間[micros]
  //50ms(50,000us): 長距離モードで使われることが多い安全値。
  vl53l1x.startContinuous(50);
  //連続測定モードの測定間隔[msec] 0を指定すると可能な限り最速になる
  //推奨値50ms
}

void loop() {
  static int num = 0;
  Serial.printf("distance[mm]:    %5d  \n", vl53l1x.read());

  if (num == 9){
    Serial.printf("statNum:       %5d ",
      vl53l1x.ranging_data.range_status);
    Serial.printf("status: %s\n",
      VL53L1X::rangeStatusToString(vl53l1x.ranging_data.range_status));
    Serial.printf("range:         %5d  ",
      vl53l1x.ranging_data.range_mm);
    Serial.printf("peak Signal: %8.3f  ",
      vl53l1x.ranging_data.peak_signal_count_rate_MCPS);
    Serial.printf("ambient:    %8.3f\n",
      vl53l1x.ranging_data.ambient_count_rate_MCPS);
  }
  num++;
  if (num == 10) num = 0;
  delay(50);
}

初期設定に関する補足
Wire.begin(SDA,SCL);
  使用しているSDA,SCLのGPIO番号を指示する必要がある
  ここではデフォルトで定義されているSDA=5,SCL=6を与えていることになる
  (GPIO 5 は D4ピン,GPIO 6 は D5ピンなので紛らわしいので注意)
I2Cアドレス(何も設定しなくてもライブラリが設定してくれる)
  0x29 (7bit)
vl53l1x.setDistanceMode(VL53L1X::Long);
  測定距離の設定
  Short (短距離): 約1.3mまでの高精度測定。太陽光の影響を受けにくい。
  Long (長距離): 最大4mまでの測定。
vl53l1x.setMeasurementTimingBudget(50000);
  測定タイミングバジェット(1回の距離測定)に許容される時間[micros]
  20ms(20,000us): 最短の測定時間。短距離モードでのみ推奨。
  33ms(33,000us): 長距離モードでの一般的な設定。
  50ms(50,000us): 長距離モードで使われることが多い安全値。
vl53l1x.setROISize(8, 8);
  VL53L1Xの測定画角を狭くすることができるが,PeakSignalが低下する
  X方向のSPAD数(4~16)height: Y方向のSPAD数(4~16)
  標準(デフォルト)は16x16
vl53l1x.startContinuous(50);
  連続測定モードの測定間隔[msec] 0を指定すると可能な限り最速になる
  推奨値50ms


6 実行結果

得られたSerial出力結果は次のようになりました。

01:17:51.643 -> distance[mm]:     1667  
01:17:51.718 -> distance[mm]:     1666  
01:17:51.845 -> distance[mm]:     1670  
01:17:51.937 -> distance[mm]:     1667  
01:17:52.030 -> distance[mm]:     1669  
01:17:52.124 -> distance[mm]:     1672  
01:17:52.217 -> distance[mm]:     1667  
01:17:52.283 -> distance[mm]:     1668  
01:17:52.368 -> distance[mm]:     1667  
01:17:52.490 -> distance[mm]:     1667  
01:17:52.490 -> statNum:           0 status: range valid
01:17:52.490 -> range:          1667  peak Signal:    5.938  ambient:       0.141
01:17:52.583 -> distance[mm]:     1667  
01:17:52.676 -> distance[mm]:     1672  
01:17:52.770 -> distance[mm]:     1666  
01:17:52.863 -> distance[mm]:     1671  
01:17:52.956 -> distance[mm]:     1673  
01:17:53.033 -> distance[mm]:     1672  
01:17:53.112 -> distance[mm]:     1666  
01:17:53.252 -> distance[mm]:     1669  
01:17:53.331 -> distance[mm]:     1665  
01:17:53.425 -> distance[mm]:     1668  
01:17:53.425 -> statNum:           0 status: range valid
01:17:53.425 -> range:          1668  peak Signal:    5.625  ambient:       0.180

センサを手にもって,周囲に向けたところ,4m程度までの距離測定ができました。
実行時に,測定距離4m以上の場合でも何らかの数値が得られます。
しかしstatusを表示させてみると,計測に成功しているかどうかがわかります。
 ・range valid (statNum = 0) 正常測定値が得られています。
 ・signal fail (statNum = 2) それらしい値が得られていますが,測定時の信号レベルが低いとき,および測定限界以遠のとき
 ・wrap target fail (statNum = 7) 測定失敗です
今のところこれ以外の表示は出てきません。
・statNum = 0 なら信頼
・statNum = 2 なら信頼度は低いが一応測定値は使う。(ただし,測定限界以遠の時には測定値は全く使えないので,測定限界以内であることが確実である場合のみ)
・statNum = 7 なら測定値は使えない
といったところでしょうか。

補足
vl53l1x.ranging_data.range_mm は直前に測定したvl53l1x.read()と同じ値
ranging_data.peak_signal_count_rate_MCPS は反射光の強度 MegaCountPerSecond
ranging_data.ambient_count_rate_MCPS 環境光の強度 MegaCountPerSecond
peakSignalとambientは値が離れているほど信頼性が高いと考えられる


vl53l1x.read()に関する補足 要注意
このプログラムでは,loopの最後に「delay(50);」があるので,表示は50msecごとのはずですが,表示のタイムスタンプを見ると,約100msecごとの表示になっています。
read()はデフォルトではread(true)として認識されている(lock=true)ため,プログラムとは無関係にセンサ内部で自走測定がなされていて,計測が終わりデータが準備されるまで,この関数からの戻りが待たされるようになっています。
すなわち,センサの測定終了は約100msecごとになっていることがわかります。

VL53L1Xのメソッド(関数)であるread()の使用には注意が必要です。
このプログラムでは,startContinuous(50)で動作しているため,センサは自走し,測定を繰り返しています。
read()はデフォルトではread(true)として認識されている(lock=true)ため,自走測定でのデータが準備されるまで,この関数からの戻りが待たされるようになっています。

VL53L1Xライブラリの説明では,read(false)として使用すると,待たされなくなるが,測定が完了前だと,得られる結果は未定だと書かれています。
もっと高速なloopの中での計測では,
static int distance = 0;
のようにstatic変数を作っておき,ループ内では
if (vl53l1x.dataReady()) distance = vl53l1x.read(false);
にすれば,待たされずに,最直前の測定値を利用できる。ただし,待たされないだけで,測定値の更新間隔は変わらりません。


7 センサの設定を変更し測定値の更新間隔を短くする

startContinuous()で自走測定するときの設定を変更し,測定範囲は1.3m以下とし,自走測定周期を短くなることを期待しました。
また,dataReady()をチェックしてread(false)を使うことにして,測定値が更新されたかどうかも表示するようにしました。 ループ内のdelayは10msecにしました。

//VL53l1x_JustTest_study.ino
//library: vl53l1x-arduino by Pololu

#include <Wire.h>
#include <VL53L1X.h>

VL53L1X vl53l1x;

void setup() {
  Serial.begin();
  delay(500);
  Wire.begin(SDA,SCL);
  Wire.setClock(400000); // use 400 kHz I2C
  vl53l1x.setTimeout(500); //[msec]
  if (!vl53l1x.init())
  {
    Serial.println("Failed to detect and initialize vl53l1x!");
    while (1);
  }
  vl53l1x.setDistanceMode(VL53L1X::Short);
  vl53l1x.setMeasurementTimingBudget(20000);
  vl53l1x.startContinuous(10);
}

void loop() {
  static int num = 0;
  static int distance = 0;
  static VL53L1X::RangeStatus status = VL53L1X::RangeValid;
  String update = "";
  if (vl53l1x.dataReady()) {
    distance = vl53l1x.read(false);
    status = vl53l1x.ranging_data.range_status;
    update = "update";
  }
  Serial.printf("%ld:    %5d %s\n", millis(), distance, update);

  if (num == 9){
    Serial.printf("statNum: %5d status: %s\n", status, VL53L1X::rangeStatusToString(status));
  }

  num++;
  if (num == 10) num = 0;
  delay(10);
}

測定結果を次に示します。第一列の数値はタイムスタンプで単位はミリ秒です。
10msecごとの時刻になっています。
第2列の数値は距離測定結果で単位はmmです。


24683:      898 
24693:      898 
24703:      899 update
24714:      899 
24724:      899 
24734:      897 update
24745:      897 
24755:      899 update
24766:      899 
24776:      899 
statNum:     0 status: range valid
  :
57217:     1671 
57227:     1666 update
57238:     1666 
57248:     1664 update
57259:     1664 
57269:     1665 update
57280:     1661 update
57291:     1661 
57301:     1667 update
57312:     1667 
statNum:     4 status: out of bounds fail

updateが表示されているところが,測定値が得られたことを表し,
そうでないところの測定値はstatic変数に残されていた前回の測定値を表示しているだけを意味します。
その結果,測定値の更新は20から30msecであることが確認されました。
また,測定距離が1.3mを超えると,statusが異常値を示すことも確認できました。


8 まとめ

Xiao ESP32S3にTOFレーザー距離センサVL53L1X(STMicroelectronics)を接続して周囲の対象物までの距離を測定しました。
1700mm程度を連続測定していると計測値に数ミリ程度にばらつきが見られました。
100mm程度では2ミリ程度のばらつきになりました。
測定レンジlong設定では,測定値の更新に100msほどかかりましたが,short設定では,20から30msecになりました。
用途によってread(false)とread(true)を使い分けする必要があります。





付録A

ESP32S3 (VL53L1X + ICM42670) の動作テスト
(ピンを共有する)

A1 はじめに

I2C通信を使用したセンサを2つ使う例は,あまりにも当たり前すぎで,例すらあまり見かけられないため,ここで扱うことにします。
ここではXiao ESP32S3にTOFレーザー距離センサVL53L1X + IMU(慣性計測ユニット)ICM42670を取り付けて,対象物までの距離と3軸加速度と3軸角速度を得ることとします。


A2 接続

VL53L1XのSDA,SCLとICM42670のSDA,SCLをESP32S3のSDA,SCLに並列接続します。
I2C通信では,ホストのESP32S3が,それぞれのI2C機器のアドレスを指定して通信するため,ESP32の同じSDA,SCL端子を使用しても混信は起こりません。
ここでは
 VL53L1Xのアドレス  0x29(7bit)
 ICM42670のアドレス  0x69(7bit)
が使用されます。(データシートやライブラリで確かめておく必要があります)
同じアドレス(アドレスの衝突)ではないことが確かめられました。



注意
ICM42670は高速通信に対応しているため,ノイズ,反射波に対して敏感です。
そのため,他のI2Cデバイスとの同時使用で,通信できず,初期化に失敗することがあります。
そのような場合は,以下の対策が考えられます。
・プルアップ抵抗を4.7kΩから2.2kΩに替える。
・並列接続ですがGND線,3.3V線はデバイス間を数珠つなぎにせず,それぞれESP32S3のGND,3.3Vにつなぎます。(信号レベルの安定化対策)
・デバイスの3.3VとGND間に0.1μFのセラミックコンデンサと10μFの電解コンデンサを並列に接続する。(高周波電源ノイズ対策)
・SDA線とSCL線をシールド線にする。フラットケーブルを使いSDA線とSCL線の間にGND線を通す。(信号線の浮遊容量対策)
・SDA線とSCL線の途中に10Ωほどのダンピング抵抗を入れる。(信号線の浮遊容量対策)

A3 プログラムコード

使用したプログラムコードは次のものです。
コンパイル前に次の2つのライブラリの登録が必要です。
 ICM42670P by TDK/Invensense
 vl53l1x-arduino by Pololu

//ICM42670P_VL53l1x_test.ino
//library: ICM42670P by TDK/Invensense
//library: vl53l1x-arduino by Pololu


#include <Wire.h>
#include <VL53L1X.h>
#include <ICM42670P.h>

VL53L1X vl53l1x;
ICM42670 IMU_icm42670(Wire, true);

float acc_fsrange;
float gyro_fsrange;

void setup() {
  int ret;
  Serial.begin(115200);
  //while(!Serial) {}
  delay(1000);

  //----vl53l1x----------------------------------------------
  Serial.println("\nl53l1x initialization started");
  Wire.begin(SDA,SCL);
  Wire.setClock(400000); // use 400 kHz I2C
  vl53l1x.setTimeout(500); //[msec]
  if (!vl53l1x.init())
  {
    Serial.println("Failed to detect and initialize vl53l1x!");
    while (1);
  }
  vl53l1x.setDistanceMode(VL53L1X::Long);
  vl53l1x.setMeasurementTimingBudget(50000); //測定タイミングバジェット(1回の距離測定)に許容される時間[micros]
  vl53l1x.startContinuous(50);
  Serial.println("l53l1x initialization completed");

  //----ICM42670----------------------------------------------
  // Initializing the ICM42670
  Serial.println("ICM42670 initialization started");
  ret = IMU_icm42670.begin();
  if (ret != 0) {
    Serial.print("ICM42670 initialization failed : ");
    Serial.println(ret);
    while(1);
  }
  Serial.println("ICM42670 initialization completed");
  delay(100);

  // Accel ODR = 100 Hz and Full Scale Range = 2G
  IMU_icm42670.startAccel(100,2);
  acc_fsrange = 2.0f;

  // Gyro ODR = 100 Hz and Full Scale Range = 250 dps
  IMU_icm42670.startGyro(100,250);
  gyro_fsrange = 250.0f;
  
  // Wait IMU_icm42670 to start
  delay(100);

  Serial.print("\nacceleration[m/s2] x,y,z,");
  Serial.print(" angular_velocity[deg/s] x,y,x,");
  Serial.println(" distance[mm]");
}

void loop() {
  inv_imu_sensor_event_t imu_event;

  IMU_icm42670.getDataFromRegisters(imu_event);

  float ax = convertRawAcceleration(imu_event.accel[0]); //acceleration_x [m/s2]
  float ay = convertRawAcceleration(imu_event.accel[1]); //acceleration_y [m/s2]
  float az = convertRawAcceleration(imu_event.accel[2]); //acceleration_z [m/s2]
  float gx = convertRawGyro(imu_event.gyro[0]); //angular_velocity_x [deg/s]
  float gy = convertRawGyro(imu_event.gyro[1]); //angular_velocity_y [deg/s]
  float gz = convertRawGyro(imu_event.gyro[2]); //angular_velocity_z [deg/s]

  Serial.printf("%6.2f, ", ax);
  Serial.printf("%6.2f, ", ay);
  Serial.printf("%6.2f,  ", az);
  Serial.printf("%6.2f, ", gx);
  Serial.printf("%6.2f, ", gy);
  Serial.printf("%6.2f,  ", gz);
  Serial.printf("%5d\n", vl53l1x.read());
  delay(500);
}

float convertRawAcceleration(int16_t aRaw) {
  // since we are using acc_fsrange g range
  // -2 g maps to a raw value of -32768
  // +2 g maps to a raw value of 32767
  
  float a = (aRaw * acc_fsrange) / 32768.0 * 9.8;
  return a; // [m/s^2]
}

float convertRawGyro(int16_t gRaw) {
  // since we are using gyro_fsrange degrees/seconds range
  // -250 maps to a raw value of -32768
  // +250 maps to a raw value of 32767
  
  float g = (gRaw * gyro_fsrange) / 32768.0;
  return g;  // [deg/s]
}

初期設定に関する補足
VL53L1XとICM42670に関して,それぞれ初期化を行っています。
SDA,SCLのGPIO番号の指示やI2Cアドレスの指示は気になるところです。

〇 SDA,SCLのGPIO番号の指示
 VL53L1Xに関してはWire.begin(SDA,SCL);で行っている
 ICM42670ではライブラリ内デフォルト設定で完結しており設定は不要なようです
〇 I2Cアドレスの指示
 VL53L1Xではライブラリ内デフォルト設定で完結しており設定は不要なようです
 ICM42670ではインスタンス生成の際にtrueまたはfalseで
 アドレスの最下位ビットを指示しています


A4 実行結果

次のようなSerial出力を得ました。

16:49:14.888 -> l53l1x initialization started
16:49:14.888 -> l53l1x initialization completed
16:49:14.888 -> ICM42670 initialization started
16:49:14.888 -> ICM42670 initialization completed
16:49:15.089 -> 
16:49:15.089 -> acceleration[m/s2] x,y,z, angular_velocity[deg/s] x,y,x, distance[mm]
16:49:15.135 ->   0.91,   0.18,   9.88,   -0.35,  -0.05,  -0.63,   1671
16:49:15.596 ->   0.91,   0.18,   9.90,   -0.31,   0.15,  -0.60,   1667
16:49:16.098 ->   0.91,   0.18,   9.90,   -0.40,  -0.03,  -0.75,   1674
16:49:16.643 ->   0.92,   0.17,   9.91,   -0.31,   0.02,  -0.66,   1673
16:49:17.103 ->   0.91,   0.17,   9.89,   -0.31,  -0.03,  -0.67,   1674
16:49:17.636 ->   0.91,   0.17,   9.90,   -0.34,   0.05,  -0.61,   1672
16:49:18.149 ->   0.91,   0.18,   9.91,   -0.37,   0.05,  -0.64,   1668
16:49:18.644 ->   0.91,   0.18,   9.91,   -0.34,  -0.05,  -0.73,   1673
16:49:19.157 ->   0.92,   0.17,   9.94,   -0.31,  -0.08,  -0.72,   1670
16:49:19.618 ->   0.93,   0.17,   9.92,   -0.31,   0.00,  -0.56,   1673
16:49:20.153 ->   0.94,   0.16,   9.94,   -0.35,   0.02,  -0.69,   1677
16:49:20.664 ->   0.93,   0.17,   9.92,   -0.34,   0.15,  -0.66,   1671
16:49:21.159 ->   0.90,   0.17,   9.91,   -0.34,   0.02,  -0.67,   1669
16:49:21.632 ->   0.89,   0.18,   9.90,   -0.37,  -0.05,  -0.64,   1676
16:49:22.133 ->   0.91,   0.18,   9.91,   -0.37,  -0.15,  -0.70,   1667
16:49:22.638 ->   0.91,   0.17,   9.90,   -0.37,   0.20,  -0.63,   1673
16:49:23.141 ->   0.90,   0.17,   9.90,   -0.37,   0.03,  -0.72,   1669
16:49:23.679 ->   0.91,   0.17,   9.89,   -0.31,  -0.06,  -0.73,   1665
16:49:24.176 ->   0.93,   0.16,   9.94,   -0.43,  -0.11,  -0.66,   1668
16:49:24.672 ->   0.92,   0.17,   9.91,   -0.37,   0.08,  -0.72,   1676
16:49:25.187 ->   0.92,   0.17,   9.91,   -0.27,   0.02,  -0.69,   1671
16:49:25.654 ->   0.91,   0.16,   9.91,   -0.37,   0.05,  -0.69,   1672
16:49:26.158 ->   0.93,   0.17,   9.90,   -0.37,   0.00,  -0.75,   1672
16:49:26.692 ->   0.92,   0.17,   9.91,   -0.29,   0.02,  -0.73,   1660
16:49:27.208 ->   0.91,   0.17,   9.91,   -0.32,   0.05,  -0.67,   1672
16:49:27.702 ->   0.92,   0.17,   9.91,   -0.43,   0.06,  -0.73,   1675
16:49:28.187 ->   0.93,   0.18,   9.92,   -0.31,   0.00,  -0.79,   1667
16:49:28.672 ->   0.92,   0.17,   9.91,   -0.34,  -0.02,  -0.69,   1678
16:49:29.217 ->   0.92,   0.17,   9.92,   -0.34,   0.02,  -0.73,   1674
16:49:29.678 ->   0.92,   0.17,   9.90,   -0.29,   0.03,  -0.67,   1668
16:49:30.210 ->   0.91,   0.17,   9.92,   -0.35,   0.00,  -0.66,   1675
16:49:30.684 ->   0.91,   0.17,   9.91,   -0.35,   0.00,  -0.69,   1675
16:49:31.233 ->   0.91,   0.18,   9.91,   -0.32,   0.02,  -0.69,   1674



付録B

ESP32S3 (VL53L1X + ICM42670) の動作テスト
(ピンを共有しない)

B1 はじめに

ESP32はI2Cポートが二つあり,それぞれ"Wire","Wire1"として利用できます。 "Wire"はデフォルトでは SDA:D4 SCL:D5 を使用していますが,"Wire1"を SDA:D7 SCL:D8 で使用することにします。 ここではXiao ESP32S3にTOFレーザー距離センサVL53L1X + IMU(慣性計測ユニット)ICM42670を取り付けて,対象物までの距離と3軸加速度と3軸角速度を得ることとします。


B2 接続

ICM42670は使用しているライブラリが"Wire"を使うことを前提としているので,その通り使うことにし,VL53L1Xに"Wire1"を使うことにします。
そのため次のようにピンを割り当てます。

デバイスI2CアドレスオブジェクトSDAピンSCLピン
ICM426700x69(7bit)WireSDA(d4)SCL(d5)
VL53L1X0x29(7bit)Wire1d7d8



注意
ICM42670は高速通信に対応しているため,ノイズ,反射波に対して敏感です。
そのため,他のI2Cデバイスとの同時使用で,通信できず,初期化に失敗することがあります。
そのような場合は,以下の対策が考えられます。
・プルアップ抵抗を4.7kΩから2.2kΩに替える。
・並列接続ですがGND線,3.3V線はデバイス間を数珠つなぎにせず,それぞれESP32S3のGND,3.3Vにつなぎます。(信号レベルの安定化対策)
・デバイスの3.3VとGND間に0.1μFのセラミックコンデンサと10μFの電解コンデンサを並列に接続する。(高周波電源ノイズ対策)
・SDA線とSCL線をシールド線にする。フラットケーブルを使いSDA線とSCL線の間にGND線を通す。(信号線の浮遊容量対策)
・SDA線とSCL線の途中に10Ωほどのダンピング抵抗を入れる。(信号線の浮遊容量対策)

B3 プログラムコード

使用したプログラムコードは次のものです。
赤文字のところだけが付録Aと異なります。
vl53l1x.setBus(&Wire1); でWire1を使うことをvl53l1xに伝えています。

コンパイル前に次の2つのライブラリの登録が必要です。
 ICM42670P by TDK/Invensense
 vl53l1x-arduino by Pololu

//ICM42670P_VL53l1x_separated.ino
//library: ICM42670P by TDK/Invensense
//library: vl53l1x-arduino by Pololu

#include <Wire.h> //下でincludeされているのでなくてもよい
#include <VL53L1X.h>
#include <ICM42670P.h>

VL53L1X vl53l1x;
ICM42670 IMU_icm42670(Wire, true);

float acc_fsrange;
float gyro_fsrange;

void setup() {
  int ret;
  Serial.begin(115200);
  //while(!Serial) {}
  delay(1000);

  //----vl53l1x----------------------------------------------
  Serial.println("\nl53l1x initialization started");
  Wire1.begin(D7,D8);
  Wire1.setClock(400000); // use 400 kHz I2C
  vl53l1x.setBus(&Wire1);
  vl53l1x.setTimeout(500); //[msec]
  if (!vl53l1x.init())
  {
    Serial.println("Failed to detect and initialize vl53l1x!");
    while (1);
  }
  vl53l1x.setDistanceMode(VL53L1X::Long);
  vl53l1x.setMeasurementTimingBudget(50000); //測定タイミングバジェット(1回の距離測定)に許容される時間[micros]
  vl53l1x.startContinuous(50);
  Serial.println("l53l1x initialization completed");

  //----ICM42670----------------------------------------------
  // Initializing the ICM42670
  Serial.println("ICM42670 initialization started");
  ret = IMU_icm42670.begin();
  if (ret != 0) {
    Serial.print("ICM42670 initialization failed : ");
    Serial.println(ret);
    while(1);
  }
  Serial.println("ICM42670 initialization completed");
  delay(100);

  // Accel ODR = 100 Hz and Full Scale Range = 2G
  IMU_icm42670.startAccel(100,2);
  acc_fsrange = 2.0f;

  // Gyro ODR = 100 Hz and Full Scale Range = 250 dps
  IMU_icm42670.startGyro(100,250);
  gyro_fsrange = 250.0f;
  
  // Wait IMU_icm42670 to start
  delay(100);

  Serial.print("\nacceleration[m/s2] x,y,z,");
  Serial.print(" angular_velocity[deg/s] x,y,x,");
  Serial.println(" distance[mm]");
}

void loop() {
  inv_imu_sensor_event_t imu_event;

  IMU_icm42670.getDataFromRegisters(imu_event);

  float ax = convertRawAcceleration(imu_event.accel[0]); //acceleration_x [m/s2]
  float ay = convertRawAcceleration(imu_event.accel[1]); //acceleration_y [m/s2]
  float az = convertRawAcceleration(imu_event.accel[2]); //acceleration_z [m/s2]
  float gx = convertRawGyro(imu_event.gyro[0]); //angular_velocity_x [deg/s]
  float gy = convertRawGyro(imu_event.gyro[1]); //angular_velocity_y [deg/s]
  float gz = convertRawGyro(imu_event.gyro[2]); //angular_velocity_z [deg/s]

  Serial.printf("%6.2f, ", ax);
  Serial.printf("%6.2f, ", ay);
  Serial.printf("%6.2f,  ", az);
  Serial.printf("%6.2f, ", gx);
  Serial.printf("%6.2f, ", gy);
  Serial.printf("%6.2f,  ", gz);
  Serial.printf("%5d\n", vl53l1x.read());
  delay(500);
}

float convertRawAcceleration(int16_t aRaw) {
  // since we are using acc_fsrange g range
  // -2 g maps to a raw value of -32768
  // +2 g maps to a raw value of 32767
  
  float a = (aRaw * acc_fsrange) / 32768.0 * 9.8;
  return a; // [m/s^2]
}

float convertRawGyro(int16_t gRaw) {
  // since we are using gyro_fsrange degrees/seconds range
  // -250 maps to a raw value of -32768
  // +250 maps to a raw value of 32767
  
  float g = (gRaw * gyro_fsrange) / 32768.0;
  return g;  // [deg/s]
}

初期設定に関する補足
VL53L1XとICM42670に関して,それぞれ初期化を行っています。
SDA,SCLのGPIO番号の指示やI2Cアドレスの指示は気になるところです。

〇 SDA,SCLのGPIO番号の指示
 VL53L1Xに関してはWire1.begin(D7,D8);で行っている
 ICM42670ではライブラリ内デフォルト設定で完結しており設定は不要なようです
〇 I2Cアドレスの指示
 VL53L1Xではライブラリ内デフォルト設定で完結しており設定は不要なようです
 ICM42670ではインスタンス生成の際にtrueまたはfalseで
 アドレスの最下位ビットを指示しています