Cảm biến lùi xe / đỗ xe trong gara (còi kêu nhanh dần khi lại gần)
Đo khoảng cách bằng sóng siêu âm 2cm–4m, báo bằng 3 đèn xanh–vàng–đỏ và còi kêu nhanh dần khi xe tiến gần vật cản, kêu liền khi dưới 20cm. Dùng gắn tường gara để đỗ xe đúng chỗ, hoặc làm cảm biến lùi cho xe đạp điện, xe đồ chơi, robot.
✅ Đã kiểm thử
Xem chi tiết 16 phép đo
Trường hợp xấu nhất: 3 đèn + còi cùng bật, đang phát xung đo
- Q1: dẫn 29.2mA, Vce=0.03V (bão hòa tốt).
- D1: dòng 8.2mA (cho phép 20.0mA).
- D2: dòng 8.5mA (cho phép 20.0mA).
- D3: dòng 9.0mA (cho phép 20.0mA).
- Chân D4 cấp 8.2mA (an toàn ≤ 20.0mA).
- Chân D5 cấp 8.5mA (an toàn ≤ 20.0mA).
- Chân D6 cấp 9.0mA (an toàn ≤ 20.0mA).
- Chân D8 cấp 4.1mA (an toàn ≤ 20.0mA).
- Tổng dòng đỉnh từ USB 104.0mA (đủ với cục sạc 5V 1A).
- Dòng LED xanh: 8.2mA ✓
- Dòng LED vàng: 8.5mA ✓
- Dòng LED đỏ: 9.0mA ✓
- Dòng qua còi: 29.2mA ✓
- Áp chân ECHO vào D10: 5.00V ✓
Không có vật cản (tất cả tắt)
- Tổng dòng đỉnh từ USB 45.0mA (đủ với cục sạc 5V 1A).
- Còi tắt: 0.0mA ✓
Nguyên lý hoạt động
Arduino phát xung 10µs vào chân TRIG. HC-SR04 bắn 8 xung siêu âm 40kHz rồi giữ chân ECHO ở mức cao suốt thời gian sóng đi tới vật và dội về. Khoảng cách = thời gian × 0,0343 cm/µs ÷ 2. Mạch đo 5 lần liên tiếp và lấy giá trị giữa (trung vị) để loại bỏ các lần dội sai. Trên 100cm thì đèn xanh. 50–100cm đèn vàng, còi bíp chậm. 20–50cm đèn đỏ, còi bíp nhanh dần. Dưới 20cm còi kêu liền. Mỗi LED ăn khoảng 8mA qua trở 330Ω; còi ăn khoảng 30mA nên đi qua transistor S8050.
Sơ đồ đấu dây
Mỗi màu là một dây. Chấm tròn là điểm hàn. Chạm vào tên dây trong bảng để làm nổi bật.
| # | Dây | Nối các điểm |
|---|---|---|
| 1 | đỏ 5V | U1 5V ⟷ U2 VCC ⟷ BZ1 + |
| 2 | đen GND | U1 GND ⟷ U2 GND ⟷ Q1 E (phát) ⟷ D1 K · chân ngắn (−) ⟷ D2 K · chân ngắn (−) ⟷ D3 K · chân ngắn (−) |
| 3 | vàng TRIG | U1 D9 ⟷ U2 TRIG |
| 4 | xanh lá ECHO | U2 ECHO ⟷ U1 D10 |
| 5 | xanh dương BZ_DRV | U1 D8 ⟷ R1 1 |
| 6 | tím BZ_BASE | R1 2 ⟷ Q1 B (gốc) |
| 7 | xanh ngọc BZ_COL | BZ1 - ⟷ Q1 C (góp) |
| 8 | nâu G_DRV | U1 D4 ⟷ R2 1 |
| 9 | hồng G_A | R2 2 ⟷ D1 A · chân dài (+) |
| 10 | xám Y_DRV | U1 D5 ⟷ R3 1 |
| 11 | xanh rêu Y_A | R3 2 ⟷ D2 A · chân dài (+) |
| 12 | tím nhạt R_DRV | U1 D6 ⟷ R4 1 |
| 13 | vàng R_A | R4 2 ⟷ D3 A · chân dài (+) |
Danh sách linh kiện
| Ký hiệu | Linh kiện | Giá tham khảo | |
|---|---|---|---|
| U1 | Arduino Nano V3 (ATmega328P, chip nạp CH340) | 85.000đ | Tìm mua |
| U2 | Cảm biến siêu âm HC-SR04 (4 chân VCC-TRIG-ECHO-GND) | 20.000đ | Tìm mua |
| Q1 | Transistor S8050 (TO-92) | 500đ | Tìm mua |
| R1 | Điện trở 1kΩ 1/4W (nâu-đen-đỏ) | 200đ | Tìm mua |
| BZ1 | Còi chip chủ động 5V | 4.000đ | Tìm mua |
| D1 | LED xanh lá 5mm (green) | 300đ | Tìm mua |
| D2 | LED vàng 5mm (yellow) | 300đ | Tìm mua |
| D3 | LED đỏ 5mm (red) | 300đ | Tìm mua |
| R2 | Điện trở 330Ω 1/4W (cam-cam-nâu) | 200đ | Tìm mua |
| R3 | Điện trở 330Ω 1/4W (cam-cam-nâu) | 200đ | Tìm mua |
| R4 | Điện trở 330Ω 1/4W (cam-cam-nâu) | 200đ | Tìm mua |
| Tổng (chưa gồm board hàn, dây, thiếc) | 111.200đ |
Các bước làm
Code nạp cho mạch
Chọn board Arduino Nano.
/*
Mạch Gọn — Cảm biến lùi xe / đỗ xe gara
Board : Arduino Nano (ATmega328P)
Chân : D9 -> TRIG, D10 <- ECHO (HC-SR04, 5V)
D8 -> R 1k -> B S8050 (còi chủ động)
D4/D5/D6 -> 330Ω -> LED xanh/vàng/đỏ
*/
#include <Arduino.h>
// ----- Cấu hình (cm) -----
const uint8_t PIN_TRIG = 9, PIN_ECHO = 10, PIN_BUZ = 8;
const uint8_t PIN_G = 4, PIN_Y = 5, PIN_R = 6;
const int FAR_CM = 100; // xa hơn: an toàn, đèn xanh
const int MID_CM = 50; // 50–100: đèn vàng, bíp chậm
const int STOP_CM = 20; // dưới 20: còi kêu liền
const int MAX_CM = 400; // ngoài tầm đo
const uint8_t SAMPLES = 5; // số lần đo để lấy trung vị
const uint32_t IDLE_SILENT_MS = 30000; // đứng yên ở vùng đỏ quá 30s thì tắt còi (xe đã đỗ)
int lastCm = -1;
uint32_t stableSince = 0;
int stableRef = -1;
// đo 1 lần, trả về cm (-1 nếu không có tiếng dội)
int measureOnce() {
digitalWrite(PIN_TRIG, LOW); delayMicroseconds(3);
digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
unsigned long us = pulseIn(PIN_ECHO, HIGH, 25000UL); // ~4,3m tối đa
if (us == 0) return -1;
int cm = (int)(us * 0.0343 / 2.0 + 0.5);
return (cm >= 2 && cm <= MAX_CM) ? cm : -1;
}
// lọc trung vị: bỏ các lần dội sai
int measureMedian() {
int v[SAMPLES]; uint8_t n = 0;
for (uint8_t i = 0; i < SAMPLES; i++) {
int cm = measureOnce();
if (cm > 0) v[n++] = cm;
delay(12); // chờ sóng dội cũ tắt hẳn
}
if (n == 0) return -1;
for (uint8_t i = 1; i < n; i++) { int k = v[i]; int j = i - 1; while (j >= 0 && v[j] > k) { v[j + 1] = v[j]; j--; } v[j + 1] = k; }
return v[n / 2];
}
void leds(bool g, bool y, bool r) { digitalWrite(PIN_G, g); digitalWrite(PIN_Y, y); digitalWrite(PIN_R, r); }
void setup() {
Serial.begin(9600);
pinMode(PIN_TRIG, OUTPUT); pinMode(PIN_ECHO, INPUT);
pinMode(PIN_BUZ, OUTPUT); pinMode(PIN_G, OUTPUT); pinMode(PIN_Y, OUTPUT); pinMode(PIN_R, OUTPUT);
// tự kiểm tra đèn + còi lúc bật
leds(1, 0, 0); delay(150); leds(0, 1, 0); delay(150); leds(0, 0, 1); delay(150); leds(0, 0, 0);
digitalWrite(PIN_BUZ, HIGH); delay(60); digitalWrite(PIN_BUZ, LOW);
Serial.println(F("Cam bien lui xe san sang"));
}
void loop() {
int cm = measureMedian();
uint32_t now = millis();
if (cm < 0) cm = MAX_CM + 1; // không có vật trong tầm
// làm mượt nhẹ
lastCm = lastCm < 0 ? cm : (lastCm * 2 + cm) / 3;
// phát hiện xe đã dừng hẳn (khoảng cách không đổi ±2cm) để tắt còi
if (stableRef < 0 || abs(lastCm - stableRef) > 2) { stableRef = lastCm; stableSince = now; }
bool parked = now - stableSince > IDLE_SILENT_MS;
uint16_t onMs = 0, offMs = 0;
if (lastCm > FAR_CM) { leds(1, 0, 0); }
else if (lastCm > MID_CM) { leds(0, 1, 0); onMs = 60; offMs = 600; }
else if (lastCm > STOP_CM) {
leds(0, 0, 1);
onMs = 50;
offMs = map(lastCm, STOP_CM, MID_CM, 60, 300); // càng gần càng nhanh
} else { leds(0, 0, 1); onMs = 200; offMs = 0; } // kêu liền
if (parked && lastCm <= MID_CM) { onMs = 0; leds(0, 0, (now / 1000) % 2); } // đã đỗ: chỉ nháy đỏ
if (onMs) {
digitalWrite(PIN_BUZ, HIGH); delay(onMs);
if (offMs) { digitalWrite(PIN_BUZ, LOW); delay(offMs); }
} else {
digitalWrite(PIN_BUZ, LOW); delay(100);
}
static uint32_t lastLog = 0;
if (now - lastLog > 500) {
lastLog = now;
Serial.print(F("Khoang cach: "));
if (lastCm > MAX_CM) Serial.println(F("ngoai tam")); else { Serial.print(lastCm); Serial.println(F(" cm")); }
}
}
Đo kiểm bằng đồng hồ vạn năng
| Giữa VCC và GND của HC-SR04 | 4,6 – 5,1V |
| Serial Monitor 9600 khi để tay cách 30cm | khoảng 28–32 cm |
| Đưa tay lại gần dần | Đèn xanh → vàng → đỏ, còi bíp nhanh dần rồi kêu liền dưới 20cm |
Sửa lỗi thường gặp
Luôn báo 0cm hoặc không đo được
Kiểm tra TRIG/ECHO có bị đảo không; HC-SR04 cần đúng 5V. Vật mềm (vải, bông) hấp thụ sóng nên khó đo.
Số đo nhảy lung tung
Code đã lọc trung vị; nếu vẫn nhảy, giữ dây ngắn hơn, tránh đặt cảm biến sát tường bên (sóng dội ngang).
Còi không kêu
Kiểm tra là còi chủ động và chiều E-B-C của S8050.
Đèn quá sáng/quá tối
Đổi trở 330Ω thành 220Ω (sáng hơn) hoặc 1kΩ (tối hơn); không dùng dưới 150Ω.
⚠️ An toàn
- Mạch 5V an toàn khi chạm.
- Gắn trên xe thật: dùng nguồn 5V qua bộ đổi điện USB tẩu sạc, không đấu thẳng vào điện 12V của xe.
- Chỉ là thiết bị hỗ trợ, luôn quan sát khi lùi xe.