今回は距離計測について書きます。地盤工学において変位計測は重要ですが、長期にわたり高精度を求めるならワイヤー式の変位計などを用いることになるでしょう。ひずみゲージ式のセンサーについては、第19回の方法でHX711などを用いてデータ取得が可能です。ここでは、非接触型のセンサーである赤外線ToF(Time-of-Flight)測距計と超音波測距計について紹介します。いずれも、ロボットの障害物回避などに用いられるもので、0.1mmなどといった精度を持つものではありません。しかし、後に示すようにそれなりの用途もあります。

 

赤外線ToFセンサー

VL53L0Xというセンサーです。ブレークアウトモジュールとして1000~1500円くらいを相場として売っています。このICはもはやおなじみのI2Cでマイコンに接続します。

 

 

写真の上にある黒いチップから光が出て、反射時間に基づいて距離を測るようです(この原理はよくわかりません。光の速度を直接測れるとは思えないので、干渉の原理などを利用しているのでしょうか)。それほど強い光ではないものの、直接覗き込まないほうがいいそうです。

 

 接続は以下のようにします。通信プロトコルはI2Cですので、もはやおなじみ、Vcc・GND・A4 (SDA)・A5 (SCL)の4本線で接続します。データシート(https://www.pololu.com/file/0J1187/VL53L0X.pdf)には動作電圧は「2.6 to 3.5 V」とあります。ほとんどのICに言えることですが、ICそのものは3.3V系ですが、ブレークアウトモジュールに電圧レギュレータがついていて、Vccを5Vに接続しても動作します。

 

 

 

以下がスケッチです。例によってライブラリをダウンロードしてください。

https://github.com/pololu/vl53l0x-arduino

VL53L0Xには4つの計測モードが用意されています。データシートによれば、以下の表の通りです。それぞれのモードを使う文をスケッチに残しながらコメントアウトして無効化してあるので、適宜コメントをはずして試してみて下さい。なお、スケッチは上記のライブラリにあるサンプルSingle.inoに基づいています(コメントを多少簡単にしてあります)。サンプルから解釈する限り、DefaultとLong rangeのどちらかとHigh accuracyとHigh speedのどちらかは組み合わせられる(4つのモードが個々に排他的ではない)ようです。距離はmmで返ってきます。

 

 Mode

 計測時間 (msec)

 計測範囲 (m)

 備考

 Default

 (既定)

 30

 1.2

 Standard

 High accuracy

 (高精度)

 200

 1.2

 Precise measurement

 Long range

 (広範囲)

 33

 2

 Long range, only for

 dark conditions

 High speed

 (高速)

 20

 1.2

 High speed where 

 accuracy is not priority

 

どの程度の精度があるのか?については、データシート(上記URL)のp.25~26に図があります。

 



#include <Wire.h>

#include <VL53L0X.h>

 

VL53L0X sensor;

 

// Uncomment this line to use long range mode.

//#define LONG_RANGE

 

// Uncomment ONE of these two lines to get higher speed at the cost of lower accuracy OR

// higher accuracy at the cost of lower speed

//#define HIGH_SPEED

//#define HIGH_ACCURACY

 

void setup()

{

  Serial.begin(9600);

  Wire.begin();

 

  sensor.init();

  sensor.setTimeout(500);

 

#if defined LONG_RANGE

  // lower the return signal rate limit (default is 0.25 MCPS)

  sensor.setSignalRateLimit(0.1);

  // increase laser pulse periods (defaults are 14 and 10 PCLKs)

  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);

  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);

#endif

 

#if defined HIGH_SPEED

  // reduce timing budget to 20 ms (default is about 33 ms)

  sensor.setMeasurementTimingBudget(20000);

#elif defined HIGH_ACCURACY

  // increase timing budget to 200 ms

  sensor.setMeasurementTimingBudget(200000);

#endif

}

 

void loop()

{

  Serial.print(sensor.readRangeSingleMillimeters());

  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  Serial.println();

}

 

 

(参考)

 上記のスケッチ中における#if defined XXXというのは、XXXが定義されていれば、その次の行グループをコンパイルするという意味です(これや#defineなどはコンパイル後のコマンドになるというよりもコンパイラへの指示であり、ディレクティブと呼ばれます)。先に書いたように、コメントアウトを外せば、#if definedがtrueになるので、その次の文がコンパイルされ、実行可能になります。

 

超音波センサー

 障害物回避のためのセンサーとして定番で、しかも安価なため(数百円程度)、Arduino初修セットにだいたいついてきます。Amazonなどで検索すると、見た目はほとんど同じながら品番が異なるものがいくつかあります。この品番は何を表すものなのかよくわかりません。ICチップそのものの品番なのか、それとも振動子(スピーカーのように見える発信機(T: Transmitter)と受信機(R: Receiver))まで含めたシステムとしてのモジュールの品番なのか不明です。HC-SR04・US-015・HY-SRF05などが検索にかかると思います。HC-SF04が安くて流通しているのですが、一部のロットにバグがあるそうで、動作が「ハマって」計測が止まってしまうことがあるそうです。どれも使い方は全く同じですが、計測範囲(4m程度)や精度に多少の相違があるようです。また、周波数はいずれも40kHzのようです。

 

 

 

原理としては反射波の到達時間を計測するものですが、気温によって音波速度が異なるため、厳密にはその補正を行う必要があります。音波速度は気温o0Cを参照として、1oC増加するごとに0.18%大きくなります。0oCと20oCでは、速度が約3.6%異なり、補正しなければこれがそのまま測距の誤差となります。接続とスケッチは以下の通りです。ここでは音速を単に340m/secとして、反射波到達までの時間(μsec)に340000mm/secを掛けて(対象物までの距離を求めるのでさらに2で割って)、mmで距離を出しています。珍しく、どのようなライブラリも使いません。Arduinoの標準関数でパルス到達時間を計っています。

 

 

 



/* Sonic displacement sensors */

int inputPin=3; // pin to read signal from sensor

int outputPin=4; // pin to send signal to sensor

 

void setup(void)

{  

    int cnt1;

     

    pinMode(inputPin, INPUT);

    pinMode(outputPin, OUTPUT);

 

    Serial.begin(9600);

    while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

    }

}

 

void loop(void)

{

    /* Obtain distance from sonic sensor */

    int arriv_time;

    int distance;

    digitalWrite(outputPin, LOW);

    delayMicroseconds(2);

    digitalWrite(outputPin, HIGH);  

    delayMicroseconds(10);

    digitalWrite(outputPin, LOW); 

    arriv_time=pulseIn(inputPin, HIGH);

    distance=arriv_time*340000/1000000/2;

    delay(100);

 

    /* Display in the PC */

    Serial.println(distance);

}

 

 

 

適用例

 第21回に続いて、積雪深センサーとしての適用を紹介します。第21回で、温度計アレーの柱の上におかしなヘッドがついていましたが、ここから地表に向けて、US-015(超音波)・HY-SRF05(超音波)VL53L0X(赤外線ToF)の3つで距離を測り、ヘッド高さから差し引いて積雪深を北海道の黒松内という場所で一冬の間、記録しました。VL53L0XはLong rangeとHigh accuracyモードを設定しました。斜面に垂直に向けており、以下に示しているのはこの法線方向の深度(鉛直方向ではない)です。

 

 

これらのセンサーは頻繁にデータ欠損が起こるので、記録時にはそれぞれ5回の計測時を記録して、全てプロットしました。5回の記録中に正常値が残らないこともあります。正常値と思われるものが記録されるまで繰り返すなど、Arduinoのスケッチ側の工夫が必要と思います。このサイトではこの他にインターバルカメラや第21回で紹介したDS18B20などで積雪深を測っており、これらと概ね整合する値が得られています。グラフの内容をまとめると、

 

・積雪期の読みはVL53L0X(赤外線ToF)が最も安定しているが、春に0mmに戻っていない。地表の植生を通り抜けていないよう。

・5月以降はかなり草が伸びてきて、いずれのセンサーもこれに反応している。

・グラフでは見づらいが、US-015は欠損値が多く、連続的なデータを得られていない。HY-SRF05のデータはより連続的だが、1-2月の極端な増減は現実的でない(カメラからも確認済み)。

 

今のところ、いずれも高価ではないので、どっちもとりあえず載せとけ、という感じで使っています。市販の超音波積雪深計も40kHzを用いているようですが、このように欠損が多いのか、アルゴリズムで工夫しているのか、それとも印加電圧が異なるのか、わかりません。