DEV Community

張旭豐
張旭豐

Posted on

用超聲波加紅外線達成全向障礙偵測:Arduino 雙感測器整合

Arduino 超聲波與紅外線感測器整合:打造全向障礙偵測系統

為光譜裡誰做:阿哲(想做避障小車)
Parent Gene:超聲波感測(14)、紅外線感測(09)

概念句:用超聲波加紅外線達成全向障礙偵測


想像一下:你在桌子上的小型避障小車,忽然遇到一隻手、一塊淺色保麗龍、和遠處的牆——三種不同的障礙,它都能正確停下來嗎?

單一感測器做不到。但把超聲波感測器(HC-SR04)紅外線感測器加在一起,就可以。

1. 為什麼要整合?(互補特性分析)

超音波感測器(HC-SR04)

  • 原理:發射超聲波,計算回傳時間 \text{Distance} = \frac{\text{Sonic Speed} \times \text{Time}}{2}。
  • 優點:測距範圍廣(約 2cm ~ 400cm),對物體顏色不敏感。
  • 缺點
    • 盲區:太近的物體測不准。
    • 聲波散射:面對傾斜表面或吸音材料(海綿、布料)時,聲波被散射而回傳失敗,導致「看不見」障礙物。

紅外線感測器

  • 原理:發射紅外光,偵測反射回來的光強度。
  • 優點:反應速度快,適合近距離偵測(邊緣偵測、極近障礙)。
  • 缺點
    • 深色物體吸收紅外光:黑色或深色表面會讓偵測距離大幅縮短甚至完全偵測不到。
    • 環境光干擾:強烈陽光(含紅外線成分)可能造成誤判。

整合策略:雙重驗證

情境 超音波結果 紅外線結果 系統判定
遠處有牆 \text{Distance} < 20\text{cm} 無觸發 障礙物(遠)
面對淺色保麗龍(多孔) 無回傳(散射) 觸發(吸光少) 僅超聲波(超聲波盲,IR 補上)
面前有白色牆壁 \text{Distance} < 5\text{cm} 觸發 障礙物(極近)
空曠環境 \text{Distance} > 20\text{cm} 無觸發 安全

阿哲可能遇到的問題:為什麼淺色保麗龍讓超聲波「失效」了,但紅外線卻測到了?因為保麗龍表面軟、多孔,聲波散射回不上來,但紅外光仍能反射回讀——兩種感測器的物理特性不同,剛好互補。


2. 硬體接線

元件清單

  • Arduino Uno 或 Nano × 1(約 NT200-300)
  • HC-SR04 超聲波模組 × 1(約 NT50-80)
  • 紅外線障礙偵測模組 × 1(約 NT30-50)
  • 麵包板、杜邦線

接線表

元件 引腳 Arduino 引腳 說明
HC-SR04 VCC 5V 電源
Trig D9 觸發脈衝
Echo D10 接收回傳
GND GND 接地
IR Sensor VCC 5V 電源
OUT D2 偵測訊號(Low = 偵測到)
GND GND 接地

3. 程式碼實現

// 定義引腳
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
const int IR_PIN = 2;

const long MAX_DISTANCE = 300; // sentinel 值:代表「測不到/超範圍」,不是真實可測距離(pulseIn timeout 限制實測上限約 51cm)
const int DEBOUNCE_COUNT = 3;   // 連續偵測次數

int stableCount = 0; // 紅外線穩定計數

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(IR_PIN, INPUT);
  digitalWrite(TRIG_PIN, LOW);
  Serial.println("System Initialized: 超聲波 + 紅外線融合");
  Serial.println(">> 校準:打開 Serial Monitor,確認數值正常 <<");
}

long getUltrasonicDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // pulseIn timeout = 3000μs → 實測上限約 51cm(來回 102cm)。超過就回傳 MAX_DISTANCE(sentinel)
  long duration = pulseIn(ECHO_PIN, HIGH, 3000);
  if (duration == 0) return MAX_DISTANCE; // 無回傳視為超範圍 / 未知
  return duration * 0.034 / 2;
}

void loop() {
  long distance = getUltrasonicDistance();
  int irDetected = digitalRead(IR_PIN);

  Serial.print("距離: ");
  Serial.print(distance);
  Serial.print(" cm | IR: ");
  Serial.println(irDetected == LOW ? "偵測到!" : "無");

  // 整合邏輯:加括號避免優先順序錯誤
  bool ultrasonicTrigger = (distance > 0 && distance < 20);
  bool irTrigger = (irDetected == LOW);

  // 防雜訊:紅外線連續 3 次偵測到才算數
  if (irTrigger) {
    stableCount++;
  } else {
    stableCount = 0;
  }

  if (ultrasonicTrigger || (stableCount >= DEBOUNCE_COUNT)) {
    Serial.println(">>> 障礙物!停車! <<<");
    // motorStop(); // 在這裡加入馬達停止指令
  } else {
    Serial.println("路徑暢通,前進中...");
    // motorForward(); // 在這裡加入馬達前進指令
  }

  delay(200);
}
Enter fullscreen mode Exit fullscreen mode

技術細節:為什麼要加 timeout?

pulseIn()預設可以等很久。如果超聲波沒收到回傳(例如面對吸音海綿),它會卡住直到收到為止——這段時間小車可能已經撞上了。

加入 timeout 參數(微秒)後,3ms(= 3000 微秒)內沒收到回傳就回傳 0,我們立刻知道「這次沒測到」,而不會卡死。聲音在空氣中每秒約走 340 公尺,也就是每秒 34,000 公分,所以每微秒約 0.034 公分duration * 0.034 / 2 這個公式就是把微秒轉換成來回的距離(公分)。

MAX_DISTANCE 只是 sentinel 值,表示「測不到」,不代表真的 300cm。當超聲波完全收不到回傳時,pulseIn 回傳 0,我們回傳 MAX_DISTANCE,邏輯會走到 distance > 0 && distance < 20 這個超聲波觸發條件,結果是 false——這時候紅外線的 stableCount 就會在它感測到障礙時觸發。兩個感測器互相當作 backup。


4. 動手驗證(阿哲測試清單)

  1. 超聲波測試:拿一本書慢慢靠近,Serial Monitor 顯示的數值是否符合實際距離?
  2. 紅外線測試:用手靠近/遠離模組,觀察訊號燈和 Serial Monitor 輸出。
  3. 軟質材料測試:拿一塊白色或淺色保麗龍測試——超聲波可能失效(散射),但紅外線仍能偵測到(淺色表面反射紅外光良好),這正是兩種感測器互補的好例子。黑色海綿則是兩者的共同盲區——聲波散射 + 紅外光吸收,同時失效。
  4. 整合測試:同時觸發兩個感測器,確認「雙重驗證」邏輯正確。

5. 讓阿哲問的問答

Q:為什麼保麗龍讓超聲波測不准?
A:超聲波靠「聲波反射」回傳資訊。保麗龍、海綿等軟質/多孔材料會把聲波散射吃掉,幾乎沒有反射。紅外線靠「光反射」,如果表面是淺色,同樣能反射回讀——兩者互補。

Q:可以把這個邏輯用在循線小車上嗎?
A:可以。把紅外線模組朝下安裝,當車輪接近桌面邊緣時,紅外線訊號會從「無反射」變成「有反射」(桌面 vs. 懸空),就能及時停住。

Q:pulseIn 的 timeout 要設多少?
A:這題是物理+設定的混合問題。pulseIn() 的 timeout 參數單位是微秒(μs)。聲音在空氣中每秒約走 340 公尺(每秒 34,000 公分),所以每微秒約走 0.034 公分。來回 100cm(大約手臂伸直的距離)約需 2.9ms(= 2900 微秒)。pulseIn()3000(微秒)表示:等 3ms 還沒有回傳就放棄。實務上 3ms timeout 讓 HC-SR04 最遠約測到 51cm(單程)——超過這個距離的障礙,會被視為「無障礙」。這是超聲波感測器的物理上限,不是程式的錯。


結論

超聲波的「遠距掃描」與紅外線的「近距補完」,剛好從兩個方向覆蓋了單一感測器的盲區。

這個整合做起來不貴(全部材料約 NT300 以內),邏輯也清晰——而且讓你真正理解「感測器融合」在實務上長什麼樣子。

動手門檻:國中生程度可以接線,但程式邏輯建議有高一以上基礎。或請旭豐帶你走一遍。

Top comments (0)