AI要約
やること
ロボットの衝突防止のために近接センサーを導入することになりました。
まずは秋月電子で350円で買える「超音波距離センサー」を試してみたいと思います。
材料
Arduino Unoと超音波距離センサー US-015
今回は複数センサー使用時の干渉(≒クロストーク)を防ぐ仕組みも学びたいので2個用意しました。

マザーボード用のビープスピーカーも用意しました。こういうのってLEDを光らせるのが定番ですが、音のほうがわかりやすいのでブザーを試してみます。このブザーは5Vの交流を流せば鳴ります。直流では「ミッ」しか鳴らないのでご注意を。
接続
US-015はVCCを5V、GNDをArduinoと共通のGNDに接続します。他にTrigとEchoがあるのでArduinoのデジタルピンに接続。
| Arduino | センサー |
|---|---|
| D2 | US-015① Trig |
| D3 | US-015① Echo |
| D4 | US-015② Trig |
| D5 | US-015② Echo |
| D11 | ブザー + |
| GND | ブザー - |

ブザーはこのようにD11とGNDに直結するのが簡単。単体で使う場合は極性は無視しても大丈夫です。

コード
こんな感じです。
//センサー数
const int NUM_SENSORS = 2;
//Trig, Echoピン
int trigPins[NUM_SENSORS] = {2, 4};
int echoPins[NUM_SENSORS] = {3, 5};
//ブザーピン
const int buzzerPin = 11;
//検出しきい値[cm]
const float THRESHOLD_CM = 10.0;
//検出タイムアウト[us], 5000us≒往復約85cm程度
const unsigned long TIMEOUT_US = 5000;
//距離配列[cm]
float distanceCm[NUM_SENSORS];
//検出配列
bool isNear[NUM_SENSORS];
void setup() {
Serial.begin(9600);
//センサー初期化
for (int i = 0; i < NUM_SENSORS; i++) {
pinMode(trigPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
digitalWrite(trigPins[i], LOW);
}
//ブザー初期化
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
}
//1つのセンサーで距離を測る関数
float measureDistanceCm(int index) {
int trig = trigPins[index];
int echo = echoPins[index];
//TrigをいったんLOW
digitalWrite(trig, LOW);
delayMicroseconds(2);
//10usのパルスを発射
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
//EchoがHIGHの間の時間を測る(タイムアウト付き)
unsigned long duration = pulseIn(echo, HIGH, TIMEOUT_US);
//エコーが返ってこなかったら-1.0を返す
if (duration == 0) {
return -1.0;
}
//返ってきたら距離[cm]
float d = duration * 340 / 10000 / 2;
return d;
}
void loop() {
//全センサー
for (int i = 0; i < NUM_SENSORS; i++) {
//距離[cm]
distanceCm[i] = measureDistanceCm(i);
//検出結果
if (distanceCm[i] > 0 && distanceCm[i] <= THRESHOLD_CM) {
isNear[i] = true;
} else {
isNear[i] = false;
}
//クロストーク防止のために少し待つ[ms]
delay(5);
}
//配列isNear[]の中にtrueが一つでもあるかチェック
bool anyNear = false;
for (int i = 0; i < NUM_SENSORS; i++) {
if (isNear[i]) {
anyNear = true;
break;
}
}
//あればブザーを鳴らす
if (anyNear) {
//パッシブブザーなのでtone()で交流を出す
tone(buzzerPin, 442); //4kHz
} else {
noTone(buzzerPin); // ブザー OFF
}
//ループ待機[ms]
delay(50);
}2個のセンサーを順番に稼働することでクロストークを防ぎます。10μsのパルス音を発射し、跳ね返って検出するまでの時間 duration [μs] を調べます。その後、音速340 [m/s] をかけたり往復しているので2で割るなどして物体との距離 [cm] を算出しています。
d = duration * 340 / 10000 / 2;2個のセンサーのうち一つでもしきい値以内に物体を検出していたらブザーを鳴らします。ブザーは tone() で周波数を指定した交流を流しています。オーケストラのアーの音にしてみました。(なぜ440Hzじゃなくて442Hzなのか)
tone(buzzerPin, 442);結果
動画の前半はしきい値10cmで目薬を通過させています。後半はしきい値30cmで検出範囲を調べています。検出範囲を大きくするとき、床を検出してしまうので本体を少し浮かせます。
検出範囲
たいたいこんな感じでしょうか。一つのセンサーには発信部と受信部の円筒が付いています。検出範囲はどちらかに偏るかと思っていましたが、ほぼ左右対称な感じでした(S/N比的な意味でね。伝われ)。

音波なのでノイズに弱い印象はありました。
おわりに
今回は超音波式の距離センサーでしたが、もう一つ試してみたいと思います。
