Tìm kiếm mã

Bài 26/31: Xe Thông Minh Phần 4: Tránh Vật Cản Sử Dụng Cảm Biến Siêu Âm | SunFounder Robojax

Bài 26/31: Xe Thông Minh Phần 4: Tránh Vật Cản Sử Dụng Cảm Biến Siêu Âm | SunFounder Robojax

Trong bài học này, chúng ta nâng cấp chiếc xe thông minh của bạn với khả năng nhìn và phản ứng với môi trường xung quanh bằng cảm biến siêu âm. Bằng cách đo khoảng cách đến các vật thể phía trước, chiếc xe có thể đưa ra quyết định thông minh: nó sẽ tiến về phía trước khi đường đi thông thoáng, dừng lại khi có vật thể nằm trong vùng cảnh báo và lùi lại khi chướng ngại vật ở quá gần. Dự án này xây dựng dựa trên các kiến thức nền tảng về điều khiển động cơ và cảm biến mà bạn đã học, tạo ra một chiếc xe thực sự tự hành.

26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.09.009

Đây không chỉ là một món đồ chơi; đây là một bước nền tảng để xây dựng các dự án robot phức tạp hơn. Logic bạn sẽ triển khai ở đây—cảm nhận, suy nghĩ, hành động—là logic tương tự được sử dụng trong mọi thứ từ robot hút bụi đến tự động hóa công nghiệp. Dưới đây là một vài ý tưởng để truyền cảm hứng cho các dự án của riêng bạn:

  • Robot thám hiểm tự hành: Tạo một robot có thể khám phá một căn phòng hoặc hành lang mà không va vào tường hoặc đồ đạc.
  • Hệ thống báo động tiệm cận: Gắn cảm biến siêu âm lên một servo để quét một khu vực và kích hoạt chuông báo động hoặc đèn khi có kẻ xâm nhập vào vùng xác định.
  • Trợ lý đỗ xe thông minh: Xây dựng một hệ thống sử dụng số liệu khoảng cách để dẫn dắt xe vào chỗ đỗ chật hẹp, cung cấp phản hồi bằng hình ảnh hoặc âm thanh.

Hướng dẫn này dựa trên bộ kit 3-trong-1 SunFounder Arduino và dự án "Play with Ultrasonic Module" của nó. Chúng ta sẽ đi qua phần đấu dây, giải thích mã ra quyết định và trình diễn chiếc xe hoạt động.

26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_02.26.146

Cách hoạt động của logic tránh chướng ngại vật

Cốt lõi của dự án này là một cây quyết định đơn giản nhưng mạnh mẽ. Cảm biến siêu âm liên tục đo khoảng cách đến vật thể ngay phía trước. Giá trị khoảng cách này sau đó được sử dụng để điều khiển động cơ của xe, như được minh họa trong sơ đồ dưới đây.

  • Nếu khoảng cách > 25 cm: Đường đi thông thoáng, vì vậy xe tiến về phía trước.
  • Nếu 10 cm < khoảng cách <= 25 cm: Một vật thể được phát hiện trong "vùng cảnh báo", vì vậy xe dừng lại để tránh va chạm.
  • Nếu 2 cm < khoảng cách <= 10 cm: Một vật thể ở quá gần một cách nguy hiểm. Xe lùi lại để tạo thêm khoảng trống.
  • Nếu khoảng cách <= 2 cm: Số liệu này có khả năng là lỗi (quá gần để đo chính xác), vì vậy xe dừng lại như một biện pháp an toàn.

Linh kiện phần cứng

Để xây dựng dự án này, bạn sẽ cần các linh kiện sau, tất cả đều có trong bộ kit 3-trong-1 SunFounder.

  • 1x Arduino Uno (hoặc bo mạch tương thích)
  • 1x Khung xe thông minh với hai động cơ có hộp số
  • 1x Mô-đun điều khiển động cơ L298N
  • 1x Cảm biến khoảng cách siêu âm HC-SR04
  • 1x Breadboard
  • Dây jumper
  • Nguồn điện cho xe (ví dụ: hộp pin)
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.00.000

Hướng dẫn đấu dây

Việc đấu dây kết nối bộ điều khiển động cơ, cảm biến siêu âm và Arduino. Bộ điều khiển động cơ điều khiển bánh xe của xe, trong khi cảm biến siêu âm đóng vai trò là "đôi mắt" của nó.

Dưới đây là sơ đồ kết nối từ tài liệu SunFounder:

Hãy phân tích các kết nối. Đầu tiên, cấp nguồn cho thanh dương và thanh âm của breadboard từ chân 5V và GND của Arduino. Cảm biến siêu âm sau đó được kết nối như sau:

  • VCC (Nguồn): Kết nối với thanh dương trên breadboard.
  • GND (Nối đất): Kết nối với thanh âm trên breadboard.
  • Trig (Kích hoạt): Kết nối với chân kỹ thuật số 3 trên Arduino. Chân này gửi xung siêu âm.
  • Echo (Nhận): Kết nối với chân kỹ thuật số 4 trên Arduino. Chân này nhận xung phản hồi.

Các kết nối của bộ điều khiển động cơ giống như trong các bài học trước. Bốn chân điều khiển (IN1, IN2, IN3, IN4) được kết nối với các chân kỹ thuật số 5, 6, 9 và 10 của Arduino. Các chân này điều khiển tốc độ và hướng của hai động cơ. Đảm bảo nguồn và nối đất của bộ điều khiển động cơ được kết nối đúng cách với hộp pin và nối đất của Arduino. (trong video tại 02:24)

Giải thích mã

Mã cho dự án này điều khiển hành vi của xe dựa trên số liệu khoảng cách từ cảm biến siêu âm. Logic rất đơn giản và dễ tùy chỉnh. Hãy xem các phần chính có thể cấu hình bởi người dùng.

1. Định nghĩa chân

Ở đầu sketch, các chân cho động cơ và cảm biến siêu âm được định nghĩa. Bạn có thể thay đổi chúng nếu bạn đã đấu dây các linh kiện của mình vào các chân Arduino khác.

const int A_1B = 5;
  const int A_1A = 6;
  const int B_1B = 9;
  const int B_1A = 10;
  
  const int trigPin = 3;
  const int echoPin = 4;

Ở đây, A_1A, A_1B, B_1AB_1B điều khiển động cơ trái và phải thông qua bộ điều khiển L298N. trigPinechoPin dành cho cảm biến siêu âm.

2. Biến hành vi và logic

Hành vi chính được điều khiển bên trong hàm loop(). Đây là nơi bạn có thể điều chỉnh "tính cách" của xe.

void loop() {
    float distance = readSensorData();
    if (distance > 25) {
      moveForward(200);
    }
    else if (distance < 10 && distance > 2) {
      moveBackward(200);
    } else {
      stopMove();
    }
  }

Đây là cách để tùy chỉnh nó:

  • Ngưỡng khoảng cách: Các số 2510 xác định vùng "an toàn" và "nguy hiểm" tính bằng centimet. Tăng 25 để xe dừng sớm hơn, hoặc giảm nó để cho phép xe đến gần chướng ngại vật hơn. Số 2 là biên an toàn để bỏ qua các kết quả đọc sai từ các vật thể quá gần.
  • Tốc độ động cơ: Giá trị 200 được truyền cho moveForward()moveBackward() đặt tốc độ của xe. Giá trị này có thể nằm trong khoảng từ 0 đến 255. Giá trị thấp hơn, như 150, sẽ làm xe di chuyển chậm hơn và thận trọng hơn.

Phần còn lại của mã bao gồm hàm readSensorData(), xử lý thời gian của cảm biến siêu âm để tính khoảng cách, và các hàm moveForward(), moveBackward(), và stopMove(), điều khiển driver động cơ để thực hiện hành động mong muốn.

Xử lý một lỗi phổ biến

Bạn có thể gặp lỗi như 'moveForward' was not declared in this scope. Điều này xảy ra vì Arduino IDE đọc mã từ trên xuống dưới. Khi nó đến hàm loop(), nó chưa biết về các hàm được định nghĩa bên dưới nó. Để khắc phục, bạn phải thêm "nguyên mẫu hàm" (function prototypes) trước hàm setup(). Đây chỉ đơn giản là khai báo tên hàm và kiểu trả về, kết thúc bằng dấu chấm phẩy.

void moveForward(int speed);
  void moveBackward(int speed);
  void stopMove();
  float readSensorData();

Thêm các dòng này cho trình biên dịch biết: "Các hàm này tồn tại và sẽ được định nghĩa sau," giúp giải quyết lỗi. (trong video tại 09:21)

Cải thiện độ ổn định của cảm biến

Trong quá trình thử nghiệm, bạn có thể nhận thấy xe dừng hoặc giật ngay cả khi đường đi thoáng. Điều này thường do vòng lặp chạy quá nhanh và cảm biến siêu âm không có đủ thời gian để nhận tín hiệu phản hồi, dẫn đến kết quả đọc là 0 cm. Để khắc phục, hãy thêm một độ trễ nhỏ ở cuối hàm loop() để cho cảm biến có thời gian hoạt động.

void loop() {
    float distance = readSensorData();
    if (distance > 25) {
      moveForward(200);
    }
    else if (distance < 10 && distance > 2) {
      moveBackward(200);
    } else {
      stopMove();
    }
    delay(100); // Thêm độ trễ 100ms để có kết quả đọc ổn định
  }

Độ trễ 100 mili giây thường đủ để có được các kết quả đo khoảng cách ổn định và nhất quán. (trong video tại 10:56)

Trình diễn dự án trực tiếp

Sau khi tải mã lên, hãy mở Serial Monitor. Bạn sẽ thấy văn bản cho biết trạng thái của xe, như "Forward", "Reverse" hoặc "Stop".

Trong phần trình diễn, xe được đặt đối diện với một chướng ngại vật. Khi chướng ngại vật cách hơn 25 cm, xe di chuyển về phía trước. Khi bạn đưa tay lại gần hơn, xe dừng lại khi khoảng cách giảm xuống dưới 25 cm. Nếu bạn đưa tay rất gần, trong vòng 10 cm, xe sẽ lùi lại. Hành vi này được thấy rõ trong video và xác nhận rằng logic tránh chướng ngại vật đang hoạt động chính xác. (trong video tại 11:53)

Kết luận

Chúc mừng! Bạn đã chế tạo thành công một chiếc xe thông minh có thể di chuyển trong môi trường và tránh chướng ngại vật. Dự án này kết hợp đầu vào cảm biến, logic ra quyết định và điều khiển động cơ thành một hệ thống duy nhất, hoạt động được. Bạn không chỉ học cách sử dụng cảm biến siêu âm mà còn học cách triển khai một thuật toán điều khiển đơn giản, là nền tảng cho các robot tự hành phức tạp hơn nhiều.

Các chương

  • [00:00] Giới thiệu về tránh chướng ngại vật
  • [01:16] Tổng quan dự án và điều kiện tiên quyết
  • [02:24] Đấu dây cảm biến siêu âm và driver động cơ
  • [04:56] Mở mã dự án
  • [05:12] Giải thích mã: Logic và hàm
  • [08:34] Tải mã lên và kiểm tra ban đầu
  • [09:21] Xử lý sự cố: Nguyên mẫu hàm
  • [10:56] Xử lý sự cố: Thêm độ trễ để ổn định
  • [11:53] Trình diễn trực tiếp tính năng tránh chướng ngại vật

Hình ảnh

27-SunFounder-Car-5-Follow-Hand
27-SunFounder-Car-5-Follow-Hand
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.09.009
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.09.009
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_02.26.146
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_02.26.146
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.00.000
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.00.000
899-Lesson 26/31: Avoiding Obstacle Using Ultrasonic Sensor
Ngôn ngữ: C++
/*
Lesson 26/31: Avoiding Obstacle Using Ultrasonic Sensor 
Get this code and watch video Download and resource page https://robojax.com/RJT609
YouTube video https://www.youtube.com/watch?v=uLBmRvaemxA

*/
const int A_1B = 5;
const int A_1A = 6;
const int B_1B = 9;
const int B_1A = 10;

const int trigPin = 3;
const int echoPin = 4;

void setup() {
  Serial.begin(9600);

  //motor
  pinMode(A_1B, OUTPUT);
  pinMode(A_1A, OUTPUT);
  pinMode(B_1B, OUTPUT);
  pinMode(B_1A, OUTPUT);

  //ultrasonic
  pinMode(echoPin, INPUT);
  pinMode(trigPin, OUTPUT);
}

void loop() {
  float distance = readSensorData();
  if (distance > 25) {
    moveForward(200);
  }
  else if (distance < 10 && distance > 2) {
    moveBackward(200);
  } else {
    stopMove();
  }
}

float readSensorData() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  float distance = pulseIn(echoPin, HIGH) / 58.00; //Equivalent to (340m/s*1us)/2
  return distance;
}


void moveForward(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void moveBackward(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void stopMove() {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}

Tài nguyên & tài liệu tham khảo

Tập tin📁

Thư viện Arduino (tệp nén)