Cảm Biến Sóng Siêu Âm (Ultrasonic Sensor HC-SR04)
Hình 1: Hai loa siêu âm gắn chữ T (Transmitter - phát chùm sóng âm 40kHz) và R (Receiver - thu nhận sóng dội lại từ vật cản).
| Tên chân | Điện áp / Tín hiệu | Chế độ pinMode | Chức năng & Nguyên lý hoạt động |
|---|---|---|---|
| VCC | 5V DC | Nguồn | Cấp nguồn dương 5V ổn định cho module cảm biến hoạt động. |
| GND | 0V | Nối đất | Nối về chân cực âm GND chung của Arduino UNO. |
| Trig (Trigger) | Digital Output | pinMode(trigPin, OUTPUT); |
Nhận xung kích phát từ Arduino (kéo HIGH tối thiểu 10 microsecond). Cảm biến sẽ tự động phát ra 8 chu kỳ xung sóng siêu âm ở tần số 40 kHz. |
| Echo | Digital Input | pinMode(echoPin, INPUT); |
Chân trả về thời gian. Ngay khi phát sóng, chân Echo chuyển lên mức HIGH. Khi nhận được sóng dội về từ vật cản, chân Echo lập tức rớt về LOW. |
- Vận tốc truyền sóng âm trong không khí:
v = 340 m/s = 0.034 cm/microsecond (µs)(tương đương1 cm mất 29.41 µs). - Thời gian đo được bởi hàm pulseIn: Là tổng thời gian sóng âm di chuyển 2 chiều (từ cảm biến phát tới vật cản + dội ngược trở lại).
- Công thức suy ra khoảng cách d (cm):
Khoảng cách (cm) = (Thời gian duration [µs] × 0.034) / 2 = duration / 58.8
- Ví dụ: Nếu thời gian đo được là
1 millisecond = 1000 µsthì:d = (1000 × 0.034) / 2 = 17 cm.
• Đoạn mã chuẩn kích phát xung Trig và đọc thời gian Echo:
const int trigPin = 9;
const int echoPin = 10;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
}
void loop() {
// 1. Kích hoạt chân Trig bằng xung HIGH kéo dài chính xác 10 microseconds
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// 2. Đo thời gian chân Echo duy trì ở trạng thái HIGH (đơn vị: microsecond)
unsigned long duration = pulseIn(echoPin, HIGH);
// 3. Tính khoảng cách ra centimet (cm)
float distance = (duration * 0.034) / 2.0;
// 4. In ra Serial Monitor
Serial.print("Khoang cach: ");
Serial.print(distance);
Serial.println(" cm");
delay(100); // Tạm dừng 100ms giữa các lần đo
}
Ý tưởng: Dùng hàm map(distance, 5, 50, 50, 600) để chuyển đổi khoảng cách đo được (từ 5cm đến 50cm) sang chu kỳ chớp tắt (từ 50ms rất nhanh đến 600ms chớp chậm).
const int trigPin = 9;
const int echoPin = 10;
const int ledPin = 13;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
unsigned long duration = pulseIn(echoPin, HIGH);
int distance = (duration * 0.034) / 2;
// Giới hạn dải khoảng cách từ 5cm đến 50cm
if (distance >= 5 && distance <= 50) {
int blinkSpeed = map(distance, 5, 50, 50, 600); // Gần: delay 50ms, Xa: delay 600ms
digitalWrite(ledPin, HIGH);
delay(blinkSpeed);
digitalWrite(ledPin, LOW);
delay(blinkSpeed);
} else if (distance < 5) {
digitalWrite(ledPin, HIGH); // Quá gần nguy hiểm: LED sáng liên tục
} else {
digitalWrite(ledPin, LOW); // Quá xa: Tắt LED
delay(100);
}
}
Cảm Biến Quang Trở (Photoresistor Sensor / LDR)
Hình 2: Module quang trở tích hợp IC so sánh điện áp LM393, chiết áp biến trở xoay màu xanh tinh chỉnh ngưỡng sáng và 4 chân giao tiếp (VCC, GND, D0, A0).
- Linh kiện quang trở (Light Dependent Resistor - LDR) được chế tạo từ vật liệu bán dẫn Cadmium Sulfide (CdS).
- Điện trở của quang trở có mối quan hệ TỶ LỆ NGHỊCH với cường độ ánh sáng chiếu vào:
• Trời càng sáng: Photon giải phóng nhiều electron tự do → Điện trở giảm mạnh (còn vài trăm Ω).
• Trời càng tối: Ít hạt mang điện → Điện trở tăng cực đại (hàng trăm kΩ đến hàng MΩ).
- VCC: Nối nguồn dương 5V DC.
- GND: Nối về cực âm GND chung.
- D0 (Digital Output): Xuất mức nhị phân 0 hoặc 1 so sánh qua IC LM393:
• Trời SÁNG: Xuất mức0 (LOW).
• Trời TỐI: Xuất mức1 (HIGH). - A0 (Analog Output): Xuất điện áp liên tục từ 0V đến 5V tỉ lệ với cường độ ánh sáng, đọc qua bộ ADC Arduino (giá trị từ
0 đến 1023).
• Đoạn mã đọc giá trị Analog A0 & Digital D0 từ quang trở:
const int ldrDigitalPin = 7; // Nối vào chân D0
const int ldrAnalogPin = A0; // Nối vào chân A0
void setup() {
pinMode(ldrDigitalPin, INPUT);
Serial.begin(9600);
}
void loop() {
int isDark = digitalRead(ldrDigitalPin); // 1: Trời tối, 0: Trời sáng
int lightLevel = analogRead(ldrAnalogPin); // 0 (cực sáng) -> 1023 (cực tối)
Serial.print("Digital D0: ");
Serial.print(isDark ? "Troi TOI (1)" : "Troi SANG (0)");
Serial.print(" | Analog A0: ");
Serial.println(lightLevel);
delay(200);
}
Còi Báo Động (Buzzer) & Nguyên Lý Gốm Áp Điện (Piezo)
Hình 3: Còi chíp 2 chân có cực tính tương tự LED: Chân dài là cực dương (+), Chân ngắn là cực âm (-).
Hình 4: Tấm màng kim loại phủ gốm Piezoelectric co giãn theo xung điện trường để rung không khí tạo sóng âm thanh.
| Tiêu chí | Còi Chủ Động (Active Buzzer) | Còi Thụ Động (Passive Buzzer / Piezo) |
|---|---|---|
| Mạch dao động nội | Có sẵn mạch dao động tạo tần số cố định bên trong còi. | Không có mạch dao động, chỉ có màng loa piezo thuần túy. |
| Cách phát âm thanh | Chỉ cần cấp điện áp 5V (HIGH) là tự động kêu tiếng bíp liên tục. | Phải cấp xung vuông PWM hoặc đổi trạng thái HIGH/LOW liên tục ở tần số mong muốn. |
| Khả năng phát nhạc | Không đổi được tần số (chỉ phát 1 tone duy nhất). | Phát được mọi nốt nhạc Đồ Rê Mi và các bài hát phức tạp. |
• Kỹ thuật phát âm thanh tần số F trong thời gian D bằng xung vuông thủ công:
// Hàm playTone: Tự tạo xung vuông với tần số frequency (Hz) và độ dài duration (ms)
void playTone(int buzzerPin, long frequency, long duration) {
long period = 1000000 / frequency; // Chu kỳ sóng (tính bằng microsecond)
long numCycles = duration * frequency / 1000; // Số chu kỳ cần lặp
for (long i = 0; i < numCycles; i++) {
digitalWrite(buzzerPin, HIGH);
delayMicroseconds(period / 2); // Nửa chu kỳ ở mức cao
digitalWrite(buzzerPin, LOW);
delayMicroseconds(period / 2); // Nửa chu kỳ ở mức thấp
}
}
// Lưu ý: Trong Arduino có sẵn hàm hỗ trợ chính thức:
// tone(buzzerPin, frequency, duration);
// noTone(buzzerPin);
* Kho mã nguồn phát các bản nhạc nổi tiếng (Super Mario, Star Wars, Harry Potter, v.v.): https://github.com/robsoncouto/arduino-songs
Bài Tập Tổng Hợp: Dự Án "Đèn Học Thông Minh" (Smart Lamp)
- Cấp độ 1: Khi trời tối (quang trở phát hiện) VÀ có người lại gần bàn học (< 50 cm đo bằng HC-SR04) → Tự động BẬT đèn LED. Nếu trời sáng hoặc không có người → TẮT đèn.
- Cấp độ 2 (Chống mỏi mắt / Cảnh báo thời gian): Nếu người học ngồi liên tục quá 5 giây (trong thực tế là 45-60 phút) → Đèn LED chuyển sang nhấp nháy liên tục để nhắc nhở người học đứng dậy giải lao (dùng hàm
millis()để tính giờ). - Cấp độ 3 (Âm thanh tạm biệt): Khi người học đứng dậy đi ra ngoài bàn học (> 50 cm) sau khi đã ngồi học → Còi Buzzer phát ra một đoạn nhạc giai điệu chúc mừng thư giãn!
• Toàn bộ mã nguồn hoàn chỉnh (C++ / Arduino IDE):
/*
* DU AN: DEN HOC THONG MINH (SMART STUDY LAMP)
* Fit HCMUS - Thuc hanh IoT Tuan 4
* Linh kien: Arduino UNO, HC-SR04, Quang tro LDR, Den LED, Coi Buzzer
*/
// Dinh nghia cac chan cam
const int trigPin = 9;
const int echoPin = 10;
const int ldrDigitalPin = 7; // Hoac doc qua A0
const int ledPin = 8;
const int buzzerPin = 6;
// Bien trang thai va hen gio bang millis()
bool isStudying = false;
unsigned long studyStartTime = 0;
const unsigned long OVER_TIME_LIMIT = 5000; // 5 giay (demo)
// Ham do khoang cach sieu am (cm)
float getDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
unsigned long duration = pulseIn(echoPin, HIGH, 30000); // Timeout 30ms
if (duration == 0) return 999.0;
return (duration * 0.034) / 2.0;
}
// Giai dieu vui tuoi phat qua buzzer khi nguoi dung dung day
void playGoodbyeMelody() {
int notes[] = { 262, 294, 330, 349, 392, 440, 494, 523 }; // C4 -> C5
for (int i = 0; i < 8; i++) {
tone(buzzerPin, notes[i], 120);
delay(150);
}
noTone(buzzerPin);
}
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(ldrDigitalPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
Serial.begin(9600);
Serial.println("=== HE THONG DEN HOC THONG MINH KHOI DONG ===");
}
void loop() {
float distance = getDistance();
int isDark = digitalRead(ldrDigitalPin); // 1 la troi toi, 0 la troi sang
bool personNear = (distance > 0 && distance <= 50.0); // Nguoi cach ban < 50cm
// Kiem tra dieu kien bat den hoc: Troi toi VA co nguoi lai gan
if (isDark == 1 && personNear) {
if (!isStudying) {
// Bat dau phien ngoi hoc
isStudying = true;
studyStartTime = millis();
digitalWrite(ledPin, HIGH);
Serial.println("[BAT DEN] Nguoi hoc da vao ban!");
} else {
// Da ngoi hoc, kiem tra da qua 5s chua
unsigned long duration = millis() - studyStartTime;
if (duration >= OVER_TIME_LIMIT) {
// Canh bao ngoi qua lau: Nhap nhay den LED
digitalWrite(ledPin, (millis() / 250) % 2 == 0 ? HIGH : LOW);
Serial.println("[CANH BAO] Ban da ngoi hoc qua 5 giay! Hay nghi ngoi.");
} else {
digitalWrite(ledPin, HIGH); // Van trong thoi gian an toan
}
}
} else {
// Khong thoa man dieu kien (Nguoi di ra ngoai hoac troi da sang)
if (isStudying) {
// Nguoi hoc vua roi ban! Phat nhac chao tam biet
Serial.println("[TAM BIET] Nguoi hoc da roi ban, phat nhac thu gian...");
digitalWrite(ledPin, LOW);
playGoodbyeMelody();
isStudying = false;
} else {
digitalWrite(ledPin, LOW);
}
}
delay(100);
}
12 Câu Hỏi Ôn Tập Cuối Buổi & Lời Giải Chi Tiết
Đáp án: Có 2 chân xử lý tín hiệu là chân Trig (Trigger) và chân Echo (ngoài ra còn 2 chân cấp nguồn là VCC 5V và GND).
Đáp án: Cả 2 chân đều sử dụng tín hiệu Digital (mức logic HIGH và LOW).
Đáp án:
• Chân Echo: khai báo là INPUT (vi điều khiển nhận xung phản hồi từ cảm biến).
• Chân Trig: khai báo là OUTPUT (vi điều khiển xuất xung kích phát sang cảm biến).
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pulseIn() trả về thời gian bằng microsecond:
unsigned long duration = pulseIn(echoPin, HIGH);
Đáp án: Kết quả là 17 cm.
Giải thích chi tiết:
• Thời gian t = 1 millisecond = 1000 microsecond (µs).
• Vận tốc sóng âm v = 0.034 cm/µs.
• Do sóng đi 2 chiều (phát tới vật cản và dội về) nên khoảng cách một chiều là:
d = (v × t) / 2 = (0.034 × 1000) / 2 = 34 / 2 = 17 cm.
0,1 giây = 100 milliseconds, sử dụng hàm:
delay(100);
0,1 millisecond = 100 microseconds, sử dụng hàm:
delayMicroseconds(100);
Đáp án: Tỷ lệ nghịch. Cường độ ánh sáng chiếu vào càng tăng thì giá trị điện trở của quang trở càng giảm mạnh.
Đáp án: Màng gốm áp điện (Piezo / Piezoelectric element). Khi có điện áp biến thiên cấp vào, tinh thể gốm áp điện co giãn cơ học với tần số cao làm rung màng loa kim loại, từ đó tạo ra sóng âm thanh trong không khí.
delayMicroseconds:
void playTone(int buzzerPin, long frequency, long duration) {
long period = 1000000 / frequency; // Chu kỳ (µs)
long numCycles = duration * frequency / 1000; // Số chu kỳ cần lặp
for (long i = 0; i < numCycles; i++) {
digitalWrite(buzzerPin, HIGH);
delayMicroseconds(period / 2);
digitalWrite(buzzerPin, LOW);
delayMicroseconds(period / 2);
}
}
Đáp án:
• Đấu nối: Chân Analog A0 của module quang trở nối vào chân A0 Arduino. Cực dương (+) của còi Buzzer nối vào chân D8, cực âm (-) nối vào GND.
• Đoạn mã lập trình hoàn chỉnh:
const int ldrPin = A0;
const int buzzerPin = 8;
void setup() {
pinMode(buzzerPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
int ldrValue = analogRead(ldrPin);
Serial.print("Gia tri quang tro: ");
Serial.println(ldrValue);
if (ldrValue < 500) {
// Gia tri < 500: Bat buzzer (phat am thanh tan so 1000Hz)
tone(buzzerPin, 1000);
} else {
// Gia tri >= 500: Tat buzzer
noTone(buzzerPin);
}
delay(50);
}