Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉔ 距離センサ VL53L4CX

 Adafruitから入手したTOF(Time of Flight Distance)センサ VL53L4CX(ST Microelectronics)を利用します。

  VL6180X VL53L0X VL53L1X VL53L3CX VL53L4CX VL53L5CX
手段 赤外線 レーザー  レーザー レーザー レーザー レーザー
4 x 4または8 x 8のマルチゾーン
分解能 20cmでは1mm、60cmでは3mm   -   - 1mm   -   -
最大測定距離 100mm  2m(反射面白色)  4m 3m 1mmから最大6m 4m
インターフェース I2C  I2C(最大400kHz)  I2C(最大1MHz) I2C(最大1MHz) I2C(最大1MHz) I2C(400kHz~1MHz)
動作電圧[V] 2.7~3.0  2.6~3.5  2.8  2.6~3.5  2.6~3.5 I/O 1.8~3.3
モジュール動作電圧[V] 2.7~5.5 3.3~5、
2.6~5.5
 3.3   - 3.3/5 2.8/3.3

AdafruitのStemma QT/Qwiicボード

 VL53L4CXボード解説のページ

 Stemma QT/Qwiic(JST SH 4ピン)コネクタは2か所に装着されていて、どちらにつないでもかまいません。このコネクタを使ってI2Cで制御する場合、特に、ジャンパ線をつなぐなどは不要です。

 コネクタは、表と裏のどちらも差し込めそうですが、ピンが内部の上部に並んでいるので、差し込める方向は一意です。ロック機構はないですが、すぐに抜けるということはありません。

距離センサVL53L4CXのおもなスペック

 VL53L4CXのデータシートはこのWebページから

  • 940 nmの不可視レーザー
  • 動作電圧 2.6~3.5 V
  • 動作温度範囲  -30~85°C
  • インターフェース I2C(最大1MHz)
  • スレーブ・アドレス 0x29

使用環境

  • Arduino UNO R4 Minima
  • Arduino IDE 2.2.1
  • Windows10 22H2

接続

 Arduino UNO R4 MinimaのI2C信号とセンサ・ボードをJSTコネクタでつなぎます(Stemma QT/Qwiicボードの写真の比率は異なる)。

スレーブ・アドレスを確認

 従来からよく使われているi2cScanner.inoを動かしてスレーブ・アドレスを確認します。電源は3.3Vです。

  0x29を見つけてきました。

 


ライブラリの用意

 VL53L4CXで検索して、見つかったSTM32duino VL53L4CXライブラリ(ST Microelectronics)をインストールします。


サンプル・スケッチ

 メニューのファイル->スケッチ例から、STM32duino VL53L4CX のVL53L4CX_Sat_HelloWorld.inoを選択します。setup{}の79行の次に、1行追加します。

  while (!Serial)  delay(100); 

 コンパイル、実行します。ボードは机の上に置いているので、センサは上を向いています。少し離れたセンサの上部で、紙を上下に動かしているところです。

 

  • Count- シリアルモニターに送信された測定値の数
  • Objs- センサの前にある物体の数
  • status- センサの範囲ステータス
  • D- センサから物体までの距離をmm単位で測定
  • Signal- センサからの信号の速度
  • Ambient- センサの周囲のノイズ

 サンプル・スケッチからLEDの点灯部分を削除し、距離の測定値だけを表示するように修正しました。

//  <h2><center>&copy; COPYRIGHT(c) 2022 STMicroelectronics</center></h2>

#include <Arduino.h>
#include <Wire.h>
#include <vl53l4cx_class.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h> #define DEV_I2C Wire #define SerialPort Serial // Components. VL53L4CX sensor_vl53l4cx_sat(&DEV_I2C, A1); void setup() { SerialPort.begin(115200); // Initialize serial for output. while (!Serial) delay(100); SerialPort.println("Starting...VL53L4CX"); DEV_I2C.begin(); // Initialize I2C bus. // Configure VL53L4CX satellite component. sensor_vl53l4cx_sat.begin(); // Switch off VL53L4CX satellite component. sensor_vl53l4cx_sat.VL53L4CX_Off(); //Initialize VL53L4CX satellite component. sensor_vl53l4cx_sat.InitSensor(0x12); // Start Measurements sensor_vl53l4cx_sat.VL53L4CX_StartMeasurement(); } void loop() { VL53L4CX_MultiRangingData_t MultiRangingData; VL53L4CX_MultiRangingData_t *pMultiRangingData = &MultiRangingData; uint8_t NewDataReady = 0; int no_of_object_found = 0, j; int status; do { status = sensor_vl53l4cx_sat.VL53L4CX_GetMeasurementDataReady(&NewDataReady); } while (!NewDataReady); if ((!status) && (NewDataReady != 0)) { status = sensor_vl53l4cx_sat.VL53L4CX_GetMultiRangingData(pMultiRangingData); no_of_object_found = pMultiRangingData->NumberOfObjectsFound; int distanceMM = pMultiRangingData->RangeData[j].RangeMilliMeter; for (j = 0; j < no_of_object_found; j++) { SerialPort.print("D="); SerialPort.print(distanceMM); SerialPort.println("mm "); } SerialPort.println(""); if (status == 0) { status = sensor_vl53l4cx_sat.VL53L4CX_ClearInterruptAndStartMeasurement(); } } delay(500); }

4桁の7セグメントLED表示器をつないで測定結果を表示する

 連載の第4回目の記事を参照しながら表示器を接続します。

Arduino UNO R4 Minimaでセンサ・インターフェーシング ④ 温湿度センサSi7021の測定結果を7セグメントLEDに表示


 スケッチです。

 7セグメントLED表示器は、第12回 温湿度センサ SHTC3でスレーブ・アドレスが重なったので、デフォルトの0x70から、ジャンパのA0をショートして0x71に変更してあります。デフォルトのまま使うときは0x70で使ってください。


//  <h2><center>&copy; COPYRIGHT(c) 2022 STMicroelectronics</center></h2>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Arduino.h>
#include <Wire.h>
#include <vl53l4cx_class.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>

#define DEV_I2C Wire
#define SerialPort Serial

Adafruit_7segment matrix = Adafruit_7segment();

// Components.
VL53L4CX sensor_vl53l4cx_sat(&DEV_I2C, A1);

void setup() {
  SerialPort.begin(115200);  // Initialize serial for output.
  while (!Serial)  delay(100); 
  SerialPort.println("Starting...VL53L4CX + 7segmentLED");

  DEV_I2C.begin();  // Initialize I2C bus.

  // Configure VL53L4CX satellite component.
  sensor_vl53l4cx_sat.begin();

  // Switch off VL53L4CX satellite component.
  sensor_vl53l4cx_sat.VL53L4CX_Off();

  //Initialize VL53L4CX satellite component.
  sensor_vl53l4cx_sat.InitSensor(0x12);

  // Start Measurements
  sensor_vl53l4cx_sat.VL53L4CX_StartMeasurement();

  matrix.begin(0x71);
  matrix.setBrightness(0x05);  // default 0x0E
}

void loop() {
  VL53L4CX_MultiRangingData_t MultiRangingData;
  VL53L4CX_MultiRangingData_t *pMultiRangingData = &MultiRangingData;
  uint8_t NewDataReady = 0;
  int no_of_object_found = 0, j;
  int status;

  do {
    status = sensor_vl53l4cx_sat.VL53L4CX_GetMeasurementDataReady(&NewDataReady);
  } while (!NewDataReady);

  if ((!status) && (NewDataReady != 0)) {
    status = sensor_vl53l4cx_sat.VL53L4CX_GetMultiRangingData(pMultiRangingData);
    no_of_object_found = pMultiRangingData->NumberOfObjectsFound;
    int distanceMM = pMultiRangingData->RangeData[j].RangeMilliMeter;
    
    for (j = 0; j < no_of_object_found; j++) {
      SerialPort.print("D=");
      SerialPort.print(distanceMM);  SerialPort.println("mm ");

      matrix.print(distanceMM, DEC);
      matrix.writeDisplay();
    }
    SerialPort.println("");
    if (status == 0) {
      status = sensor_vl53l4cx_sat.VL53L4CX_ClearInterruptAndStartMeasurement();
    }
  }

  delay(500); 
}


 実行例です。

グラフィック・ディスプレイに測定結果を表示

 次の記事を参考に、グラフィック・ディスプレイに測定した距離を表示します。

  Arduino UNO R4 Minimaでセンサ・インターフェーシング ⑤ 温湿度センサSi7021の測定結果をグラフィック・ディスプレイに表示

 スケッチです。


//  <h2><center>&copy; COPYRIGHT(c) 2022 STMicroelectronics</center></h2>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Arduino.h>
#include <Wire.h>
#include <vl53l4cx_class.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>

#define DEV_I2C Wire
#define SerialPort Serial

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET    -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Components.
VL53L4CX sensor_vl53l4cx_sat(&DEV_I2C, A1);

void setup() {
  SerialPort.begin(115200);  // Initialize serial for output.
  while (!Serial)  delay(100); 
  SerialPort.println("Starting...VL53L4CX + OLED ssd1306");

  DEV_I2C.begin();  // Initialize I2C bus.

  // Configure VL53L4CX satellite component.
  sensor_vl53l4cx_sat.begin();

  // Switch off VL53L4CX satellite component.
  sensor_vl53l4cx_sat.VL53L4CX_Off();

  //Initialize VL53L4CX satellite component.
  sensor_vl53l4cx_sat.InitSensor(0x12);

  // Start Measurements
  sensor_vl53l4cx_sat.VL53L4CX_StartMeasurement();

  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.clearDisplay();
  display.drawRect(0, 0, display.width(), display.height(), SSD1306_WHITE);
  display.setTextSize(1);                // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);   // Draw white text
  display.setCursor(3,3);
  display.println("Distance (mm): ");
  display.display();
  delay(200);
}

void loop() {
  VL53L4CX_MultiRangingData_t MultiRangingData;
  VL53L4CX_MultiRangingData_t *pMultiRangingData = &MultiRangingData;
  uint8_t NewDataReady = 0;
  int no_of_object_found = 0, j;
  int status;

  do {
    status = sensor_vl53l4cx_sat.VL53L4CX_GetMeasurementDataReady(&NewDataReady);
  } while (!NewDataReady);

  if ((!status) && (NewDataReady != 0)) {
    status = sensor_vl53l4cx_sat.VL53L4CX_GetMultiRangingData(pMultiRangingData);
    no_of_object_found = pMultiRangingData->NumberOfObjectsFound;
    int distanceMM = pMultiRangingData->RangeData[j].RangeMilliMeter;
    
    for (j = 0; j < no_of_object_found; j++) {
      SerialPort.print("D=");
      SerialPort.print(distanceMM);  SerialPort.println("mm ");

      display.setTextSize(2);   // Draw 2X-scale text
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(10,17);
      display.fillRect(1, 17, 116, 44, SSD1306_BLACK);
      display.println(distanceMM);
      display.display();
    }
    SerialPort.println("");
    if (status == 0) {
      status = sensor_vl53l4cx_sat.VL53L4CX_ClearInterruptAndStartMeasurement();
    }
  }

  delay(500); 
}

 実行例です。

未確認 三つの距離範囲

 GiHubにあるstm32duino/VL53L4CXのソースVL53L4CX/src/vl53l4cx_api.cppの中に、VL53L4CX_SetDistanceMode()関数が用意されています。

 setup{}内の最後のVL53L4CX_StartMeasurement()にVL53L4CX_SetDistanceMode()を追加する実験をしました。

  // Start Measurements
  sensor_vl53l4cx_sat.VL53L4CX_StartMeasurement();

が実行されたとき、デフォルトで、DistanceModeは VL53L4CX_DISTANCEMODE_SHORTが設定されているように見えます。上記の関数を実行した後に、

  sensor_vl53l4cx_sat.VL53L4CX_SetDistanceMode(VL53L4CX_DISTANCEMODE_MEDIUM);

もしくは、

  sensor_vl53l4cx_sat.VL53L4CX_SetDistanceMode(VL53L4CX_DISTANCEMODE_LONG);

を実行してみると、計測範囲が変更されているように見えます。バラックで組み立てて実験しているので、長距離の値が正しいのかどうかははっきりわかりません。逆に、近距離の値がおかしくなります。

前へ

Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉓ 距離センサ VL53L0X

次へ

Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉕ CO2センサSCD41