距離センサーを使ってみる その1(VL53L0X)
はじめに
今回は距離センサーのVL53L0Xを使ってみました。自動運転アルゴリズム開発プラットフォームのRumiCarでも使われていたものです。
▼RumiCarのリポジトリはこちら
https://github.com/RumiCar-group/RumiCar
リポジトリの写真で、前面に3つ搭載されているのがVL53L0Xです。
▼RumiCar向けに製作されている方の記事がありました。複数のVL53L0Xを使うときは、XSHUTピンも利用するみたいです。
https://elchika.com/article/0b3028f8-6417-4f0e-8359-be417aab77f4/
▼製作中のRumiCar-C3についてはこちら
https://protopedia.net/prototype/5030
▼センサーをどう取り付けるか...
概要
▼秋月電子での販売ページはこちら。これも購入しましたが、今回使うのはAmazonで購入したものです。
https://akizukidenshi.com/catalog/g/g112590/
▼STのページはこちら
https://www.st.com/ja/imaging-and-photonics-solutions/vl53l0x.html
データシートによると、Class 1のレーザーを使っているようですね。COLLECTORは25°、EMITTERは35°です。設計する上で測定範囲は大事なので、後で確認します。
I2C通信で使うことができて、アドレスはプログラムで変更できます。
回路を組む
マイコンはXIAO ESP32C3を使っています。I2C通信用のピンと、XSHUTピンを繋いでいます。
▼ジャンパ線で配線しました。
プログラムを書く
サンプルプログラムを試してみる
まずはサンプルプログラムを試してみます。
▼Arduino IDEのライブラリからインストールできるものを使います。
https://github.com/pololu/vl53l0x-arduino
▼Continuousを試したときのシリアルモニタ。距離に合わせて数値が変化します。
車体を設計するにあたって、どのくらいの角度範囲で反応するのかが気になっていたのですが、直線的に飛んでいるようです。
▼板を当ててみると、このぐらいの角度で反応しました。
アドレスを変更してみる
後で三つ使うので、アドレスを変更してみます。まずは今のアドレスを調べてみました。
▼こちらでも紹介されている、I2C Scannerです。
https://playground.arduino.cc/Main/I2cScanner/
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
}
void loop() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
▼現在のアドレスは0x29のようです。
アドレスを変更してみます。
▼ライブラリのsetAddress関数を使います。
https://github.com/pololu/vl53l0x-arduino#:~:text=void%20setAddress(uint8_t%20new_addr)
▼これまでのプログラムを組み合わせたものがこちら。アドレスを0x30にしてみます。
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
void setup() {
Serial.begin(9600);
Wire.begin();
sensor.setTimeout(500);
if (!sensor.init()) {
Serial.println("Failed to detect and initialize sensor!");
}
sensor.startContinuous(100);
sensor.setAddress(0x30);
}
void loop() {
byte error, address;
Serial.print(sensor.readRangeContinuousMillimeters());
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
}
▼アドレスが0x30に変更されました。
XSHUTピンを使ってみる
D10ピンに繋いだXSHUTピンがLOWだとリセット状態になり、動作しなくなります。これで複数のセンサーのアドレスを変更します。
XSHUTピンをはじめはLOWにしておいて、HIGHにしてからアドレスを設定するプログラムを書いて実行してみました。すると、HIGHにしてからinit()による初期化をすぐに行うと、初期化に失敗しました。delay(10)を入れると解決したので、タイミングの問題かな?と思います。
▼プログラムはこちら
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
const int XSHUT1 = D10;
void i2c_scan() {
byte error, address;
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
}
void setup() {
Serial.begin(9600);
Wire.begin();
pinMode(XSHUT1, OUTPUT);
digitalWrite(XSHUT1, LOW);
delay(1000);
i2c_scan();
digitalWrite(XSHUT1, HIGH);
// これが無いと初期化に失敗する!
delay(10);
if (!sensor.init()) {
Serial.println("Failed to detect and initialize sensor!");
}
sensor.setTimeout(500);
sensor.startContinuous(10);
sensor.setAddress(0x30);
i2c_scan();
}
void loop() {
Serial.println(sensor.readRangeContinuousMillimeters());
if (sensor.timeoutOccurred()) { Serial.println(" TIMEOUT"); }
}
最後に
大体の測定範囲、アドレスの変更方法が分かったので、RumiCar-C3の設計に反映しようと思います。どう収めるかが悩みどころ...
プログラムでアドレスを自由に設定できるのは面白いですね。用途次第ではあると思いますが、大量に取り付けることもできるのでしょうか。