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ボード
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>© 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>© 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>© 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);
もしくは、
を実行してみると、計測範囲が変更されているように見えます。バラックで組み立てて実験しているので、長距離の値が正しいのかどうかははっきりわかりません。逆に、近距離の値がおかしくなります。