M5StickC(ESP32)による「ELEGOO Arduino用UNO R3スターターキット」を利用したArduino入門 その8 超音波センサモジュール

現時点の情報です。最新情報はM5StickC非公式日本語リファレンスを確認してみてください。

概要

前回はサービでした。今回は「Lesson 10 超音波センサモジュール」を説明したいと思います。

超音波センサモジュールとは?

秋月さんにて、キットに入っているのと同じセンサーがありました。超音波を使って距離を測定するセンサーになります。2つ丸い部品がついていますが左側がTと書いてあったので送信、右側のRと書いてあるのが受信用の部品になります。

送信側から超音波を出して、反射した超音波を受信するまでの時間から距離を計算します。データシートをみると40KHzの超音波を使って2cmから4mまでの距離を測定できると書いてありました。

距離の計算方法

音速は温度などによって変わりますが、秒速340メートルぐらいで計算することが多いです。今回測定している時間は送信した超音波が対象物にあたって、戻ってくるまでの値ですので往復です。取得した値を片道分の半分にして計算すればよいことになります。

距離(cm) = 往復の時間(us) * 0.034(音速) / 2(往復分を片道換算)

上記で計算することができます。

データシートをみたところ、上記の表記がありました。

トリガーは10マイクロ秒以上で、少なくとも60ミリ秒以上の間隔をあけて送信すること。受信は8個の40KHzのシグナルを送信して、距離はエコーのマイクロ秒を58で割った値がセンチ単位で取得できると書いてあります。

接続方法(注意が必要!)

秋月さんによるとGNDから接続してくださいとのことです。また、実はこのセンサーはM5StickCで使うのにはちょっと問題があります。5Vで動くセンサーのため電源を5Vに接続する必要があります。

※M5StickCのRTC表記があるバージョンの場合にはM5.begin()を実行しないと5V出力がされないため、スケッチを修正する必要があります。

動作としてはTrig端子に10マイクロ秒以上のパルスを入れると、Echo端子から結果が返ってきます。M5StickCの電源は3.3Vですので、送信するパルスも3.3Vとなります。センサー側は5Vですので、想定している電圧より低くなってしまいます。ただし、概ね3V以上はHIGHと認識してくれるセンサーが多いので、送信パルスは仕様外ですが、なんとか動くことが多いと思います。

この場合、受信するエコー信号が問題になります。ESP32は3.6V以上の信号を入力することを保証していません。そのため、5Vの信号を入力すると壊れる可能性があります。

ESP32は比較的丈夫なため、保証外の使い方をしても壊れることは少ないですが、他のボードの場合にはすぐに壊れてしまうことが多いので注意してください。

安全な使い方その1 抵抗での分圧

Echo信号に抵抗を3つ接続し、2つ分のところを入力することで、5Vの3分の2である3.3Vの電圧を取り出すことができるはずです。

この回路の場合にはTrig端子には3.3Vで出力しているままですので、センサー側の入力がシビアな場合には問題が発生します。

安全な使い方その2 レベルシフト回路

上記のようなレベル変換の回路を使うことでセンサー側と、ESP32側で電圧が異なる回路になります。この回路はTrig信号も5Vに変換してくれるので、センサー側はすべて5Vとして動作し、ESP32側は3.3Vとして正しく動きます。

ちょっと自信がないですが、上記みたいな回路になると思います。High LevelのVCCに5Vを接続して、Low LevelのVCCに3.3Vを接続します。Low LevelのTI(送信入力)に26のTrig出力を接続し、High LevelのTO(送信受信)をTrig端子に接続します。Echo端子も同じようにHigh LevelのRIに接続し、Low LevelのROを36に接続します。GNDは全部共通ですね。

SPIやI2Cのような高速通信をする場合には、この回路のようなレベル変換が必要になります。

安全な使い方その3 フォトカプラ

フォトカプラという部品があります。これはICの中にLEDと明るさセンサーが入っており、5V側でLEDを光らせることで、3.3V側の明るさセンサーが動作するような動きとなります。5V側と3.3V側で電気的に絶縁されているので、異なる電圧の回路を接続する場合に使います。

フォトカプラのところを、わかりやすくするためにLEDとフォトトランジスタにしてあります。この回路だとGPIO36がフローティングになっている気がするので、さらにプルダウン回路をつけないといけませんね、、、

比較的低速の通信などで使われる手法です。電気的に絶縁しているので、お互いに違う電圧の電源を搭載している端末同士を接続する場合によく使われます。

安全な使い方その4 Grove側端子を使う

M5StickCだけなのですが、Grove側端子のGPIO32と33は5V入力をしても大丈夫な保護回路が付いているようです。Groveケーブルをもっていないと接続するのは難しいと思いますが、こちらの端子を使うことで5V入力も可能になります。ただし、送信は3.3Vのままになります。

安全な使い方その5 他のセンサーを使う

たとえば、上記はGroveケーブルで接続するレーザーを使った距離センサーです。最大2メートルまでですが、レーザーの方が超音波よりは精度も高いです。

超音波を利用したユニットは、現在開発中のようですのでもう少ししたら販売される可能性があります。

スケッチ例

//#include <M5StickC.h>
int TrigPin = 26;  // Trigピン
int EchoPin = 36;  // Echoピン
void setup() {
  // シリアル初期化
  Serial.begin(115200);
  delay(100);
  // M5StickCのユーザーはシリアル初期化の代わりに全体初期化を呼び出してください
  //M5.begin();
  // ピン初期化
  pinMode(TrigPin, OUTPUT);
  pinMode(EchoPin, INPUT);
  // LOWに落としておく
  digitalWrite(TrigPin, LOW);
}
void loop() {
  // トリガー発信
  digitalWrite(TrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW);
  // 最大測定距離(cm)
  unsigned long max = 400;
  // Echoが戻ってくる時間を取得
  unsigned long time = pulseIn(EchoPin, HIGH, 58 * max);
  // 距離計算
  int distance = time / 58;
  // 出力
  Serial.printf("時間 = %6ld us, 距離 = %4d cm\n", time, distance);
  // Wait
  delay(100);
}

私は短期の実験なので、5V直結回路でためしてみました。上記のスケッチで約100ミリ秒ごとに距離センサーの結果が出力されると思います。

  // トリガー発信
  digitalWrite(TrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW);

上記がトリガーを発信しているところになります。10マイクロ秒のWaitを入れていますが、最低10マイクロ秒であればいいので、delay(1)の1ミリ秒などでも動きます。1秒でも動いたので単にLOWに落ちたところで判定しているようです。

  // 最大測定距離(cm)
  unsigned long max = 400;
  // Echoが戻ってくる時間を取得
  unsigned long time = pulseIn(EchoPin, HIGH, 58 * max);

上記が時間を測定している関数です。pulseIn()関数という便利な関数があり、パルスの長さを測定してくれます。この場合EchoPinがHIGHになっている時間を測定します。最後に58*maxがありますが、これがタイムアウト時間です。今回のセンサーは最大400センチなので、400センチを超える値の場合には0が返却されます。

省略した場合には1秒ですので1,000,000マイクロ秒が入ります。省略してみると、たまに変な値が戻ってくるので、タイムアウトは設定したほうがいいと思います。

※現在240Mhz以外のCPU速度で動かしているとpulseIn()関数の戻り値がおかしいようです。修正リクエストを出したので、そのうち修正されると思います

  // 距離計算
  int distance = time / 58;

距離を計算しています。time * 0.034 / 2の方が実際の値に近いですが、音速は条件によりかなり変化するので誤差程度の差になります。

まとめ

超音波センサーは安価なセンサーですので、非常に誤差が大きいです。いろいろな距離での結果を確認してみてください。人感センサー的なものに使いたい場合には超音波センサーよりPIRセンサーなどの方が適しているかもしれません。

高精度が必要であればレーザーを使ったToFセンサーなども検討してみてください。

続編

コメント

  1. 超音波センサで簡易的な風速計を作ろうなどと考えておりましたが、
    探してみたらやはりたなかさんのBlogにたどり着きました(^^;

    すぐに作る(できる)わけではないですが、
    そのうちトライしたら、ご報告します。

  2. linclip より:

    こちらを見て試してみました。
    「安全な使い方その1 抵抗での分圧」のところ、「2つ分のところを入力する」ではなくて「1つ分」が正解でした!