Arduinoの距離センサーの種類:HC-SR04、IR、VL53L0X、LiDAR
Arduinoの距離センサーを比較します。HC-SR04、JSN-SR04T、Sharp IR、VL53L0X/VL53L1X、TF-Luna、TCRT5000の測定範囲、精度、ビーム角、対象表面の影響とサンプルコードを紹介します。
Arduinoの距離センサーの種類を選ぶときは、一見「どれが一番遠くまで測れるか」が問題に思えます。しかし、実際に選択を左右するのは、測定対象の表面、必要な精度、ビームに求める細さ、周囲の環境です。同じHC-SR04でも、壁までの距離はセンチメートル単位の精度で測れるのに、ソファの柔らかい布地では測定が不安定になることがあります。ミリメートル単位の精度が得られる安価なレーザーセンサーも、日光の下では測定距離が半分になることがあります。このガイドでは、Arduinoプロジェクトでよく使われる6種類のセンサーを比較します。
比較するのは、超音波式のHC-SR04とその防水版のJSN-SR04T、赤外線の三角測量を使うSharp GP2Y0A21、レーザーの飛行時間(ToF)を使うVL53L0XとVL53L1X、小型LiDARのTF-Luna、短距離の近接センサーTCRT5000です。それぞれの動作原理、測定範囲、精度、ビーム角、対象表面への反応、インターフェースを説明し、コンパイル済みのサンプルスケッチを紹介します。最後に、どのプロジェクトにどのセンサーを選ぶかを表にまとめます。

距離センサーはどう測る?3つの基本原理
Arduinoで使う距離センサーのほとんどは、3つの方式のいずれかを使います。飛行時間方式では、音や光のパルスを送り、反射して戻るまでの時間を測ります。距離は時間と速度の積の半分です。超音波センサーは音で、VL53L0XとTF-Lunaは光で測ります。光は音より約100万倍速いため、ToFセンサーにはピコ秒単位で時間を測る専用チップが入っています。三角測量方式のSharp IRセンサーは、対象に赤外線を照射し、反射光が位置検出素子(PSD)のどこに当たるかを調べます。対象が近いと光点が一方の端へ、遠いと反対側へ移動します。反射強度方式のTCRT5000のような単純なセンサーは、戻ってくる光の強さだけを測ります。表面の色に大きく左右されるため、実際の距離測定ではなく近接検知に使います。
| 原理 | センサー | 長所 | 短所 |
|---|---|---|---|
| 音の飛行時間 | HC-SR04, JSN-SR04T | 安価で、色や光の影響を受けません | ビームが広く、柔らかい面や傾いた面に弱く、温度の影響を受けます |
| 光の飛行時間 | VL53L0X, VL53L1X, TF-Luna | 高速、ビームが細い、精度が高い | 日光やガラスが問題になります |
| 赤外線の三角測量 | Sharp GP2Y0A21 | 色の影響が少なく、アナログ出力が単純です | 出力が非線形で、測定範囲が狭く、10 cm未満では誤った値になります |
| 反射強度 | TCRT5000 | 非常に安価で高速 | 数mm〜数cmのみで、色に大きく依存します |
総合比較表
以下の表は、各センサーの一般的なモジュール仕様をまとめたものです。測定範囲はメーカー公表値で、実際のプロジェクトでは対象の表面や環境によって短くなることがあります。価格は国によって異なるため、相対的な目安で示しています。
| センサー | 測定範囲 | 精度 | ビーム角 | インターフェース | 電源 | 相対的な価格 |
|---|---|---|---|---|---|---|
| HC-SR04 | 2〜400 cm | 約±0.3〜1 cm | 約15° | Trig/Echoパルス | 5 V(HC-SR04P:3.3〜5 V) | 非常に安価 |
| JSN-SR04T | 約25〜450 cm | 約±1 cm | 広い(約45°以上) | Trig/Echo、一部のバージョンはUART | 5 V | 安価 |
| Sharp GP2Y0A21 | 10〜80 cm | 近距離では良好、遠距離では低い | 細い(数度) | アナログ電圧 | 4.5〜5.5 V | 中程度 |
| VL53L0X | 3 cm〜2 m(初期設定では約1.2 m) | 約±3% | 25° | I2C(0x29) | モジュールは3.3〜5 V | 安価 |
| VL53L1X | 4 cm〜4 m | 約±3%、分解能はmm単位 | 27°(15°まで狭められます) | I2C(0x29) | モジュールは3.3〜5 V | 中程度 |
| TF-Luna | 0.2〜8 m | ±6 cm(3 mまで)、±2%(3〜8 m) | 2° | UARTまたはI2C | 電源5 V、ロジック3.3 V | 高価 |
| TCRT5000 | 約0.2〜15 mm(2.5 mmで最良) | 距離ではなく有無を検知 | 細い | デジタル(DO)+アナログ(AO) | 3.3〜5 V | 非常に安価 |
HC-SR04:定番の超音波センサー
HC-SR04は40 kHzの音のパルスを8回送り、反射音が戻るまでECHOピンをHIGHに保ちます。ArduinoはpulseIn()でこのパルス幅をマイクロ秒単位で測ります。20 °Cでの音速は約343メートル毎秒、つまり1マイクロ秒あたり0.0343 cmです。音は対象まで往復するので、距離=時間×0.0343 / 2となります。音速は温度によって変わり、約331.3 + 0.606 × T m/sです。0 °Cと35 °Cでは約6%の差があり、2メートルでは最大12 cmの誤差になります。以下のコードはこの補正を適用し、5回の測定値の中央値を取って、時折発生する異常な反射音の影響を除きます。
1const int TRIG_PIN = 9;
2const int ECHO_PIN = 10;
3const float SICAKLIK = 20.0; // ortam sıcaklığı, °C / ambient temperature, °C
4float sesHizi; // cm/µs
5
6float mesafeOlc() {
7 digitalWrite(TRIG_PIN, LOW);
8 delayMicroseconds(2);
9 digitalWrite(TRIG_PIN, HIGH); // 10 µs tetik darbesi / 10 µs trigger pulse
10 delayMicroseconds(10);
11 digitalWrite(TRIG_PIN, LOW);
12 unsigned long sure = pulseIn(ECHO_PIN, HIGH, 30000UL); // 30 ms ≈ 5 m sınırı / ~5 m limit
13 if (sure == 0) return -1; // yankı yok / no echo
14 return sure * sesHizi / 2.0; // gidiş-dönüş / round trip
15}
16
17void setup() {
18 Serial.begin(9600);
19 pinMode(TRIG_PIN, OUTPUT);
20 pinMode(ECHO_PIN, INPUT);
21 sesHizi = (331.3 + 0.606 * SICAKLIK) / 10000.0; // m/s -> cm/µs (20 °C: 0,0343)
22}
23
24void loop() {
25 float olcum[5];
26 for (int i = 0; i < 5; i++) { // 5 ölçüm, aralarında 60 ms / 5 readings, 60 ms apart
27 olcum[i] = mesafeOlc();
28 delay(60);
29 }
30 for (int i = 1; i < 5; i++) { // sırala / sort
31 float x = olcum[i];
32 int j = i - 1;
33 while (j >= 0 && olcum[j] > x) { olcum[j + 1] = olcum[j]; j--; }
34 olcum[j + 1] = x;
35 }
36 float d = olcum[2]; // ortanca / median
37 if (d < 0) Serial.println("Menzil disi / out of range");
38 else { Serial.print(d, 1); Serial.println(" cm"); }
39}
40- 測定間隔は少なくとも60 ms空けてください。前のパルスの反射音がまだ室内を反射している間に再測定すると、誤った結果になります。
- 柔らかい面や傾いた面:布、フォーム材、カーテンは音を吸収します。45度を超えて傾いた面では、反射音がセンサーとは別の方向へ進みます。
- 広いビーム:約15度の円すい状の範囲は、2メートル先で幅50 cm近くに広がります。狭い廊下では側壁も検知することがあります。
- 3.3 Vのボード:標準のHC-SR04は5 Vが必要で、ECHO出力も5 Vです。ESP32やPicoではECHOに分圧回路を入れるか、3.3 Vで動作するHC-SR04Pを使ってください。
- 複数のセンサー:2台のHC-SR04を同時にトリガーすると、互いの反射音を拾います。順番にトリガーしてください。
HC-SR04の配線と、シリアルモニタやLCDでの使い方は、HC-SR04距離センサーの記事で詳しく説明しています。ここでは比較に焦点を当てます。
JSN-SR04T:防水の超音波センサー
JSN-SR04TはHC-SR04と同じトリガーとエコーの仕組みで動作しますが、トランスデューサーは電子回路基板から離れたケーブル先端の防水カプセルに収められています。そのため、貯水タンク、井戸、雨水タンク、屋外の駐車センサーなど、湿気のある場所に向いています。重要な違いは2つです。1つのトランスデューサーで送受信するため、近距離に不感帯(約20〜25 cm)があり、ビームもHC-SR04より広くなります。センサーはタンクの上蓋に、最高水位から少なくとも25 cm上に取り付けてください。以下のコードは距離を貯水率に換算します。
1// JSN-SR04T ile su deposu doluluğu / water tank level with a JSN-SR04T
2const int TRIG_PIN = 9;
3const int ECHO_PIN = 10;
4const float SENSOR_BOSLUK = 25.0; // sensörden en yüksek su seviyesine, cm (ölü bölge) / sensor to max level (blind zone)
5const float DEPO_DERINLIK = 120.0; // en yüksek seviyeden depo dibine, cm / max level to tank bottom
6
7float mesafeOlc() {
8 digitalWrite(TRIG_PIN, LOW);
9 delayMicroseconds(5);
10 digitalWrite(TRIG_PIN, HIGH);
11 delayMicroseconds(20); // JSN-SR04T 10 µs'den uzun darbeyi sever / likes a longer pulse
12 digitalWrite(TRIG_PIN, LOW);
13 unsigned long sure = pulseIn(ECHO_PIN, HIGH, 40000UL);
14 if (sure == 0) return -1;
15 return sure * 0.0343 / 2.0; // 20 °C ses hızı / speed of sound at 20 °C
16}
17
18void setup() {
19 Serial.begin(9600);
20 pinMode(TRIG_PIN, OUTPUT);
21 pinMode(ECHO_PIN, INPUT);
22}
23
24void loop() {
25 float d = mesafeOlc();
26 if (d < 0) {
27 Serial.println("Yanki yok / no echo");
28 } else {
29 float suYuksekligi = DEPO_DERINLIK - (d - SENSOR_BOSLUK); // dipten su yüksekliği / water height
30 float yuzde = constrain(suYuksekligi / DEPO_DERINLIK * 100.0, 0, 100);
31 Serial.print("Mesafe / distance: ");
32 Serial.print(d, 1);
33 Serial.print(" cm Doluluk / fill: %");
34 Serial.println(yuzde, 0);
35 }
36 delay(1000); // su yüzeyi dalgalanır, sık ölçme / water ripples, measure slowly
37}
38Sharp GP2Y0A21:アナログ赤外線センサー
Sharp GP2Y0A21YK0Fは、10〜80 cmで動作し、距離に応じたアナログ電圧を出力する赤外線センサーです。三角測量を使うため、反射強度を使うセンサーよりも対象の色の影響を受けにくくなっています。出力は線形ではなく、10 cmで約2.3 V、80 cmで約0.4 Vとなり、その間は負の指数のべき乗曲線に従います。コードでは近似式distance = 29.988 × V^-1.173でこの曲線を換算します。最大の落とし穴は10 cm未満です。対象が近づくと出力が再び下がり、5 cmにある物体が20 cmにあるように見えることがあります。対象が10 cmより近づかないように取り付けてください。
1// Sharp GP2Y0A21YK0F (10–80 cm), analog / analog output
2const int SHARP_PIN = A0;
3
4float sharpCm() {
5 long toplam = 0;
6 for (int i = 0; i < 20; i++) { // 20 okumanın ortalaması / average of 20 readings
7 toplam += analogRead(SHARP_PIN);
8 delay(2);
9 }
10 float volt = toplam / 20.0 * 5.0 / 1023.0;
11 if (volt < 0.35) return -1; // 80 cm'den uzak / farther than 80 cm
12 float cm = 29.988 * pow(volt, -1.173); // ters güç eğrisi / inverse power curve
13 if (cm > 80) return -1;
14 return cm; // 10 cm altı yanıltıcı / misleading below 10 cm
15}
16
17void setup() {
18 Serial.begin(9600);
19}
20
21void loop() {
22 float cm = sharpCm();
23 if (cm < 0) Serial.println("Menzil disi / out of range");
24 else { Serial.print(cm, 1); Serial.println(" cm"); }
25 delay(100);
26}
27Sharpセンサーは測定中に短く大きな電流パルスを消費し、電源ラインにノイズを発生させます。センサーのVCCピンとGNDピンの近くに10 µF程度のコンデンサを付けると、測定値が目に見えて安定します。同じシリーズには別の測定範囲の製品もあります。GP2Y0A41SK0Fは4〜30 cm、GP2Y0A02YK0Fは20〜150 cmで動作し、それぞれ曲線の係数が異なります。
VL53L0XとVL53L1X:レーザーToFセンサー
VL53L0XとVL53L1Xは、STMicroelectronics製の小型レーザー飛行時間センサーです。目に見えない940 nmのレーザーパルスを送り、光子カウンターで反射光が戻る時間を測定し、I2Cで結果を直接ミリメートル単位で返します。色にはほぼ依存せず、超音波センサーよりビームが細く、1回の測定に20〜50 msかかります。VL53L0Xは標準モードで約1.2メートル、長距離モードで2メートルまで測定します。VL53L1Xは4メートルまで届き、視野(ROI)をソフトウェアで狭められます。どちらも初期設定のI2Cアドレスは0x29です。以下のコードではPololuのVL53L0Xライブラリを使います。ライブラリマネージャで「VL53L0X」を検索し、Pololu版をインストールしてください。
1#include <Wire.h>
2#include <VL53L0X.h> // Pololu VL53L0X kütüphanesi / library
3
4VL53L0X sensor;
5
6void setup() {
7 Serial.begin(9600);
8 Wire.begin(); // Uno: SDA A4, SCL A5 / ESP32: SDA 21, SCL 22
9 sensor.setTimeout(500);
10 if (!sensor.init()) {
11 Serial.println("VL53L0X bulunamadi / not found");
12 while (true) {}
13 }
14 // Uzun menzil modu (2 m'ye kadar, daha gürültülü) / long range mode (up to 2 m, noisier):
15 // sensor.setSignalRateLimit(0.1);
16 // sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
17 // sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
18 sensor.setMeasurementTimingBudget(50000); // 50 ms: daha kararlı ölçüm / steadier reading
19 sensor.startContinuous();
20}
21
22void loop() {
23 uint16_t mm = sensor.readRangeContinuousMillimeters();
24 if (sensor.timeoutOccurred()) {
25 Serial.println("Zaman asimi / timeout");
26 } else if (mm >= 8190) { // 8190-8191: hedef yok / no target
27 Serial.println("Menzil disi / out of range");
28 } else {
29 Serial.print(mm);
30 Serial.println(" mm");
31 }
32}
33測定時間の割り当てによって精度と速度のバランスが決まります。20 msは高速ですがノイズが多く、200 msは低速ですが安定します。日光や強い赤外線源があると測定距離が大きく短くなるため、屋外測定では注意してください。2台のVL53L0Xを同じI2Cバスにつなぐ場合、両方のアドレスが0x29なので、一方をXSHUTピンで停止させ、もう一方に新しいアドレスを設定します(setAddress)。I2Cの詳細はI2Cとは?の記事で説明しています。
TF-Luna:小型LiDARで8メートルを測定
TF-LunaはBenewakeの小型単点LiDARです。850 nmの赤外線を変調して飛行時間を測り、わずか2度の非常に細いビームで0.2〜8メートルを測定し、毎秒最大250回の測定ができます。初期設定では、各測定結果をUARTで115200ボーの9バイトパケットとして送ります。内容は2つの0x59ヘッダーバイト、距離(cm)、信号強度、内部温度、チェックサムです。信号強度が100未満、または65535(露光過多)の場合、測定値は信頼できないものとして扱います。電源は5 VですがUARTのロジックレベルは3.3 Vなので、ESP32に直接接続できます。UnoのSoftwareSerialは115200ボーでは信頼性が低いため、ESP32やMegaなどハードウェアUARTを備えたボードを選んでください。UARTパケットの解析方法はUARTのシリアル通信の記事で説明しています。
1// TF-Luna LiDAR, UART (115200), ESP32 Serial2
2// TF-Luna TX -> GPIO 16, RX -> GPIO 17, VCC 5V, GND
3const int RXD2 = 16, TXD2 = 17;
4
5uint8_t kare[9]; // 0x59 0x59 DistL DistH AmpL AmpH TempL TempH Checksum
6int konum = 0;
7
8void setup() {
9 Serial.begin(115200);
10 Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
11}
12
13void loop() {
14 while (Serial2.available()) {
15 uint8_t b = Serial2.read();
16 if (konum < 2) { // iki 0x59 başlık baytını bekle / wait for two 0x59 header bytes
17 if (b == 0x59) kare[konum++] = b;
18 else konum = 0;
19 continue;
20 }
21 kare[konum++] = b;
22 if (konum < 9) continue;
23 konum = 0;
24
25 uint8_t toplam = 0;
26 for (int i = 0; i < 8; i++) toplam += kare[i];
27 if (toplam != kare[8]) continue; // sağlama toplamı hatalı / bad checksum
28
29 uint16_t mesafe = kare[2] | (kare[3] << 8); // cm
30 uint16_t guc = kare[4] | (kare[5] << 8); // sinyal gücü / signal strength
31 float derece = (kare[6] | (kare[7] << 8)) / 8.0 - 256.0;
32
33 if (guc < 100 || guc == 65535) { // zayıf ya da aşırı sinyal / weak or saturated
34 Serial.println("Guvenilmez / unreliable");
35 } else {
36 Serial.print(mesafe);
37 Serial.print(" cm guc / amp: ");
38 Serial.print(guc);
39 Serial.print(" ic sicaklik / chip temp: ");
40 Serial.println(derece, 1);
41 }
42 }
43}
44TCRT5000:近接検知とライン検知

TCRT5000は距離計ではなく反射型センサーです。赤外線LEDの光が表面で反射し、隣のフォトトランジスタが戻ってきた光の量を測ります。約2.5 mmで最もよく動作し、1.5 cmを超えると信号が急激に弱まります。白い面は多くの光を反射し、黒い面はほとんど反射しないため、同じ距離でも色によって値がまったく異なります。そのため、ライントレースロボットでの白黒の判別、エンコーダーディスクの穴のカウント、ごく近くの物体の検知に使われます。モジュール上のコンパレーターは、ポテンショメーターで設定したしきい値を超えるとデジタル出力を切り替えます。詳細はTCRT5000赤外線センサーの記事をご覧ください。
1// TCRT5000 modülü: DO dijital, AO analog / TCRT5000 module: DO digital, AO analog
2const int DO_PIN = 7;
3const int AO_PIN = A1;
4const int LED_PIN = 13;
5
6void setup() {
7 Serial.begin(9600);
8 pinMode(DO_PIN, INPUT);
9 pinMode(LED_PIN, OUTPUT);
10}
11
12void loop() {
13 bool nesneVar = (digitalRead(DO_PIN) == LOW); // çoğu modülde LOW = yansıma var / LOW = reflection on most modules
14 int yansima = analogRead(AO_PIN); // düşük değer = güçlü yansıma / low value = strong reflection
15 digitalWrite(LED_PIN, nesneVar);
16 Serial.print(nesneVar ? "Nesne VAR / object " : "Nesne yok / none ");
17 Serial.println(yansima);
18 delay(100);
19}
20対象表面と環境の影響
仕様上の測定範囲は、実際に測る表面によって変わります。超音波センサーは音を反射する硬い面には強い一方、音を吸収する布には弱くなります。光を使うセンサーは色、光沢、日光の影響を受けます。以下の表は、プロジェクトを設計するときに、どの条件でどのセンサーが信頼できるかを示しています。
| 表面/環境 | 超音波(HC-SR04) | Sharp IR | レーザーToF(VL53、TF-Luna) | TCRT5000 |
|---|---|---|---|---|
| 硬く平らな壁 | 非常に良好 | 良好 | 非常に良好 | 良好(ごく近距離のみ) |
| 布、フォーム材、カーテン | 弱い(音が吸収されます) | 良好 | 良好 | 中程度 |
| つや消しの黒い面 | 良好 | 中程度 | 測定距離が短くなります | 非常に弱い |
| ガラス、鏡、光沢のある金属 | 良好(音が反射します) | 誤った値になりやすい | 誤った値になりやすい(光が透過または別方向へ反射します) | 誤った値になりやすい |
| 傾いた面 | 弱い(反射音が別方向へ進みます) | 中程度 | 良好 | 中程度 |
| 日光、屋外 | 影響なし | 影響あり | 測定距離が大きく短くなります | 影響あり |
| 水面 | 良好(タンクの測定) | 弱い | 変動します | 不向き |
| 温度変化 | 音速が変わるため補正が必要です | 影響は小さい | 影響は小さい | 影響は小さい |
配線のまとめ:Uno、ESP32、Pico
| センサー | Arduino Uno | ESP32 | Raspberry Pi Pico | 注意点 |
|---|---|---|---|---|
| HC-SR04 / JSN-SR04T | TRIG D9, ECHO D10, 5V | TRIG 5、ECHO 18(分圧回路経由)、VIN 5V | TRIG GP14、ECHO GP15(分圧回路経由)、VBUS | ECHOは5 Vを出力します |
| Sharp GP2Y0A21 | A0, 5V | GPIO 34(分圧回路経由)、VIN 5V | GP26(分圧回路経由)、VBUS | 出力は3.1 Vに達することがあります |
| VL53L0X / VL53L1X | SDA A4, SCL A5 | SDA 21, SCL 22 | SDA GP4, SCL GP5 | アドレス0x29 |
| TF-Luna | SoftwareSerialは非推奨 | TX → GPIO 16, RX → GPIO 17 | TX → GP1(uart0 RX)、RX → GP0 | 電源5 V、ロジック3.3 V |
| TCRT5000モジュール | DO D7, AO A1 | DO 27, AO 34 | DO GP16, AO GP27 | 3.3〜5 V |
Raspberry Pi Picoでの超音波測定
MicroPythonではmachine.time_pulse_us()でパルス幅を測ります。ArduinoのpulseIn()と同じ役割で、タイムアウト時には負の値を返します。HC-SR04の電源はPicoのVBUS(USB 5 V)ピンから取り、ECHOラインには1 kΩ + 2 kΩの分圧回路を入れてください。または、3.3 Vで直接動作するHC-SR04Pを使ってください。VL53L0XとTF-Luna用のMicroPythonドライバもあります。TF-LunaのUARTパケットは、Arduinoのコードと同じ考え方でmachine.UARTを使って簡単に解析できます。
1from machine import Pin, time_pulse_us
2import time
3
4trig = Pin(14, Pin.OUT)
5echo = Pin(15, Pin.IN) # 5 V ECHO için gerilim bölücü şart / divider required for a 5 V ECHO
6SES_HIZI = 0.0343 # cm/µs, 20 °C
7
8def mesafe_olc():
9 trig.low()
10 time.sleep_us(2)
11 trig.high()
12 time.sleep_us(10) # 10 µs tetik / 10 µs trigger
13 trig.low()
14 sure = time_pulse_us(echo, 1, 30000) # zaman aşımında eksi döner / negative on timeout
15 if sure < 0:
16 return None
17 return sure * SES_HIZI / 2
18
19while True:
20 d = mesafe_olc()
21 print("Menzil disi" if d is None else "{:.1f} cm".format(d))
22 time.sleep_ms(100)
23プロジェクトに合う距離センサーは?
| プロジェクト | 推奨センサー | 理由 |
|---|---|---|
| 障害物を避けるロボット | HC-SR04(低予算向け)またはVL53L0X | 広いビームで障害物を見逃しにくく、VL53L0Xならより高速で小型です |
| 貯水タンクや井戸の水位 | JSN-SR04T | 防水プローブで、水面をよく検知します |
| 車の駐車センサー | JSN-SR04TまたはHC-SR04 | 屋外での耐久性があり、2〜3 mの測定範囲で十分です |
| ライントレースロボット | TCRT5000 | 白黒の判別に向いています |
| ミニ相撲ロボット、机上の精密測定 | VL53L0X / VL53L1X | ミリメートル単位の分解能、細いビーム、小型サイズ |
| Arduinoレーダー(サーボで走査) | HC-SR04またはTF-Luna | HC-SR04は安価で、TF-Lunaの2°のビームならさらに鮮明な地図を描けます |
| 身長計、出入口の通過カウンター | VL53L1XまたはTF-Luna | 長い測定距離と安定した測定値 |
| ドローン、長距離測定 | TF-Luna | 測定範囲8 m、最大250 Hz |
| 非接触水栓、手の検知 | Sharp GP2Y0A21 | 10〜80 cmの測定範囲と単純なアナログ出力 |
プロジェクトのアイデアも紹介します。サーボに載せたHC-SR04を回転させてArduinoレーダーの表示を作る、障害物を避けるロボットの前方にHC-SR04を1台、側面にVL53L0Xを2台使う、手を近づけるとスマートゴミ箱の蓋を開ける、OLEDディスプレイ付きの携帯型デジタルメジャーを作る、JSN-SR04TとESP32でタンクの貯水率をスマホに送る、といった使い方ができます。
よくある間違いと対処法
| 症状 | 考えられる原因 | 対処法 |
|---|---|---|
| HC-SR04が常に0または範囲外を示します | 反射音がない、配線や電源の問題 | 5 V電源とTRIG/ECHOピンを確認し、pulseInにタイムアウトを設定します |
| 超音波の測定値が時々飛びます | 前のパルスや側壁からの反射音 | 測定間隔を60 ms空け、メディアンフィルタを使います |
| JSN-SR04Tが近距離を測れません | 不感帯(20〜25 cm) | 対象から少なくとも25 cm離して取り付けます |
| Sharpが至近距離で誤った大きな値を返します | 10 cm未満で曲線が折り返します | 対象が10 cmより近づかないようにします |
| Sharpの測定値にノイズが多いです | 電流パルスが電源を乱しています | VCC-GND間に10 µFのコンデンサを入れ、測定値を平均します |
| VL53L0Xが見つかりません | I2Cの配線またはアドレスの重複 | I2CスキャナーでSDA/SCLとアドレス0x29を確認します |
| レーザーセンサーが屋外で短い距離を示します | 日光に含まれる赤外線 | 遮光する、測定時間の割り当てを増やす、または超音波を使います |
| TF-Lunaのデータが不正です | ボーレートが違うか、SoftwareSerialが追いつきません | 115200ボーとハードウェアUARTを使い、チェックサムを確認します |
距離センサーは、Arduinoプロジェクトに周囲の状況を把握させる最も簡単な方法です。適切なセンサーを選ぶことで、安定して動くプロジェクトになるか、トラブルに悩まされるかが変わります。この比較の表とコードを使って、必要に応じた予算と性能のバランスを取ってください。BlueGraysアプリには、HC-SR04での距離測定、駐車センサー、身長計、障害物を避けるロボット、ESP32の駐車センサー、TCRT5000での距離測定など、回路図とコード付きで手順を追えるプロジェクトがあります。
よくある質問
Arduinoに最適な距離センサーは?
どの用途にも最適なセンサーはありません。対象と環境によって選びます。一般的な低コスト用途にはHC-SR04、ミリメートル単位の精度と細いビームが必要ならVL53L0XやVL53L1X、湿気のある場所にはJSN-SR04T、数メートルを超える高速測定にはTF-Lunaが向いています。
HC-SR04はどこまで測れますか?
メーカー公表値は2 cm〜4メートルですが、実際に信頼できる測定範囲は通常2〜3メートルです。対象が大きく硬く、センサーに対して垂直なら上限近くまで測れます。柔らかい対象、小さい対象、傾いた対象では、測定距離が大きく短くなります。
超音波と赤外線の距離センサーは何が違いますか?
超音波センサーは音のパルスの反射時間を測ります。色や光の影響は受けませんが、ビームが広く、柔らかい面は苦手です。赤外線センサーは光を使い、ビームが細く高速ですが、日光、ガラス、一部の暗い面によって測定値が乱れることがあります。
VL53L0XとVL53L1Xは何が違いますか?
どちらもI2Cインターフェースを備えたレーザーToFセンサーです。VL53L0Xは約2メートルまで、VL53L1Xは4メートルまで測定でき、後者はより高速で、ソフトウェアで視野を狭められます。VL53L0Xは短距離を測る小型ロボットに、VL53L1Xはより長距離で精密な測定に向いています。
貯水タンクの水位にはどの距離センサーを使えばよいですか?
防水プローブを備えたJSN-SR04Tが最も一般的です。タンクの上蓋に、最高水位から少なくとも25 cm上に取り付けます。乾燥した密閉タンクではHC-SR04も使えますが、湿気や結露ですぐに壊れることがあります。
距離センサーはESP32やRaspberry Pi Picoでも使えますか?
はい。ただし、5 Vで動作するHC-SR04やJSN-SR04TのECHO出力と、Sharpのアナログ出力は、分圧回路で3.3 Vに下げる必要があります。VL53L0XモジュールとTF-Lunaはもともと3.3 Vに対応するロジックを使い、HC-SR04Pは3.3 Vで直接動作します。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
HC-SR04で距離を測定(シリアルモニタ表示)
HC-SR04センサーは、コウモリが暗闇で道を見つけるのと同じ仕組みで動作します。人には聞こえない音を出し、その反響を捉えて前方の物体までの距離を測ります。Arduinoは0.5秒ごとに距離をセンチメートル単位でコンピューターの画面に表示し、3〜100センチメートルの測定値を示します。駐車センサーや障害物を避けるロボットなどのプロジェクトの基礎になります。

HC-SR04で作る駐車センサー
車の駐車センサーを小さく再現します。物体が近づくほど、ビープ音の間隔が短くなります。距離センサーが前方の物体までの距離を測り、20センチメートルより遠ければ緑のLEDが点灯します。近づくと赤いLEDが点滅してブザーが鳴り、さらに近づくほど警告の間隔が短くなります。車が壁にぶつからずに駐車できる仕組みを、机の上で確かめられます。

身長測定プロジェクト
ドア枠に取り付けて、下に立った人の身長をセンチメートルで表示する身長計です。まず、下に誰もいない状態で1つ目のボタンを押し、距離センサーで床までの距離を測ります。次に、人が下に立って2つ目のボタンを押すと、Arduinoが2つの測定値の差を計算し、身長をディスプレイに表示します。病院にある身長計の電子版を自分で作れます。

障害物回避ロボット
自分で進む道を見つける、賢い車を作ってみませんか?障害物回避ロボットは、前面の超音波センサーで周囲を常に調べます。障害物を見つけると停止し、サーボモーターで左右を確認して、最も障害物の少ない方向を選んで進みます。自動運転の基礎を学ぶのにぴったりの入門プロジェクトです。

ESP32とHC-SR04で作る超音波距離計
HC-SR04超音波センサーは、発した音波が物体に反射して戻るまでの時間(Time of Flight)を測定して距離を計算します。このプロジェクトでは、ESP32からセンサーのTRIGピンに10マイクロ秒のパルスを送り、ECHOピンからの反射波の持続時間をpulseIn()で読み取ります。計算した距離をcm単位で16x2 I2C LCDに表示します。HC-SR04は5Vで動作するため、ECHOピンには分圧回路が必須です。分圧しないとESP32の3.3V GPIOが破損します。

ESP32駐車センサー(HC-SR04 + 5連LEDバー + ブザー + OLED)
車の駐車センサーをESP32で作ります!HC-SR04超音波センサーで前方の物体までの距離を測ります。距離が縮まるほど5連LEDバーが緑 → 黄 → 赤の順に点灯し、ブザーの鳴る間隔が短くなります。10 cm未満まで近づくとアラームが鳴り続け、すべてのLEDが点灯します。SSD1306 OLEDには現在の距離をcm単位の大きな文字で表示し、状態メッセージ(落ち着いて / 注意 / 接近 / 停止! / 危険)とLEDバーのシミュレーションも表示します。HC-SR04のpulseIn、複数のデジタル出力、ブザーを学べる定番のプロジェクトです。

TCRT5000で反射(近接)を読み取る
目に見えない光を出し、その反射量を測る小さなセンサーで、前方の表面を検出できます。物体や明るい色の表面にセンサーを近づけるほど戻ってくる光が増え、Arduinoがその値を0.5秒ごとに画面に数値で表示します。ライントレースロボットや非接触式の水栓には、このようなセンサーが使われています。

LCDディスプレイを使った距離測定
定規を使わずに距離を測る装置です。センサーの前で手を近づけたり遠ざけたりすると、数値が変わります。HC-SR04が音波を出して反響を捉え、Arduinoが距離をセンチメートル単位で計算し、2行のLCDディスプレイに1秒間に数回表示します。車の駐車センサーの仕組みを、机の上で確かめられます。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

