はじめに
- 作成したクラシックマウスの各パーツの解説。
- 今回は「距離センサー VL53L0X」。
距離センサー VL53L0X
距離センサーは、光の反射光量を利用するのが一般的なようだが、調整が面倒なイメージがあって、手間の少なそうなToFセンサーを選んでみた。
Amazonで購入したもの(青色)を使っているが、他に秋月で購入したもの、Amazonで紫色のものも試してみた。どれも同じように使えるが、精度や性能に関しては個体差があるように思う。
- 利用方法
- 正面と左右に計3個取り付けている。壁との距離計測に使っているが、壁判定に用いる場合には、現在いる区画の壁だけでなく、 1つ先の壁も見る ようにしている。このため40CM程度までは計測する必要がある。
- 探索を早めるために一つ先の壁を見るようにしているが、どの程度の効果があるのか良くわからない。現区画の壁だけ見るようにするかも。
- 取付高さ
- 高い位置(4~5cm)に取り付けたほうが良い気がする。低い位置に取り付けると、床からの反射の影響のせいか、計測できる距離が短くなる(一定の距離以上が全て同じ数字で計測されてしまう)。一つ先の壁を見るには、これでは困るので、高い位置に取り付けている。
- 誤差
- 個体差があるが、総じて少し大きめに計測される傾向があるように思う。5mmから10mm程度。会場の照明や、壁の材質にも影響されるのかもしれません。データシートにはOFFSET調整方法が記載されているようですが、ここでは計測結果を適宜調整して対応しています。
- 計測数字そのものにも振れがある。5~10mm程度のイメージ。平均値をとる対応策が考えられるが、その分時間がかかる。
- 最短距離は1~2CM程度。これ以下は数字があまり変わらない。個体差があって、1cm以下でもそれなりの数字を返すものもある。
- 以上を考慮すると、計測数字に全面的に依存するのは危険。ある程度の誤差を前提として機体をコントロールする必要がある。
- 計測頻度/精度
- いくつか選択肢があるが、以下の2つを検討した。
- Normal: 計測頻度 30ms
- Accuracy: 計測頻度 200ms
- 200msは長すぎると判断して、Normalを選択。計測結果も平均値は取らず、1回目の数字をそのまま使っている。
- いくつか選択肢があるが、以下の2つを検討した。
- 計測モード
- 連続計測モード:開始命令を与えると、センサーが連続的に計測を開始する。計測頻度は指定できるが、ここでは最短(30ms)を指定している。必要な時にすぐ結果が取り出せるが、最悪30ms前の数字の可能性がある。マウスが高速で動いている場合は留意する必要があるが、この機体ではあまり影響はなさそう。
- シングル計測モード:計測したいときに都度命令を発行して結果を取得する。1回の計測に30msかかるので、計測回数が多いと速度に差が出てくる。今回は連続計測モードで利用している。
- 複数アドレス
- 本モジュールは、I2Cアドレスが固定されている(0X29)。ハード的に変更する手段がなさそうなので、複数使用する場合はXSHUTピンを使ってソフト的に変更する必要がある。
- 全てのモジュールのXSHUTピンをLOWにする。
- 一つ目のモジュールのXSHUTを開放する(pinMode(10,INPUT))。
- 初期化 .INIT()
- 変更後I2Cアドレス設定 .setAddress()
- 連続計測開始 .startContinuous(0)
- 2つ目のモジュールのXSHUT開放 以下同じ
- 本モジュールは、I2Cアドレスが固定されている(0X29)。ハード的に変更する手段がなさそうなので、複数使用する場合はXSHUTピンを使ってソフト的に変更する必要がある。
- ライブラリ
- 皆と同じようにPololu Arduino Library for VL53L0X を使いました。
- Sampleプログラムを適宜利用しています。以下ご参照。
- sensorの宣言は配列が使えます。
#include <VL53L0X.h>
VL53L0X sensor[3];
///// 以下SETUP内 ////////////
//VL53:初期化,I2Cアドレス変更 開始
pinMode(10,OUTPUT);
digitalWrite(10,LOW);
pinMode(11,OUTPUT);
digitalWrite(11,LOW);
pinMode(12,OUTPUT);
digitalWrite(12,LOW);
pinMode(10,INPUT);
sensor[0].setTimeout(250);
if (!sensor[0].init())
{
oled.println("sensor[0] Failed to detect and initialize sensor!");
while (1) {}
}
sensor[0].setAddress(0X20);
sensor[0].startContinuous(0); // 連続計測モード
oled.print(" I2C");
oled.print(sensor[0].getAddress(),HEX);
pinMode(11,INPUT);
sensor[1].setTimeout(250);
if (!sensor[1].init())
{
oled.println("sensor[1] Failed to detect and initialize sensor!");
while (1) {}
}
sensor[1].setAddress(0X21);
sensor[1].startContinuous(0); // 連続計測モード
oled.print(" I2C ");
oled.print(sensor[1].getAddress(),HEX);
pinMode(12,INPUT);
sensor[2].setTimeout(250);
if (!sensor[2].init())
{
oled.println("sensor[2] Failed to detect and initialize sensor!");
while (1) {}
}
sensor[2].setAddress(0X22);
sensor[2].startContinuous(0); // 連続計測モード
oled.print(" I2C");
oled.print(sensor[2].getAddress(),HEX);
//VL53:初期化,I2Cアドレス変更 終了
///// 以下必要な時に取得 ////////////
float d_cm;
d_cm = sensor[ ].readRangeContinuousMillimeters()*0.1;
以上