شِفر (کود) جستجو

درس ۲۶/۳۱: ماشین هوشمند قسمت ۴: اجتناب از مانع با استفاده از حساس(حس کننده) اولتراسونیک | SunFounder Robojax

درس ۲۶/۳۱: ماشین هوشمند قسمت ۴: اجتناب از مانع با استفاده از حساس(حس کننده) اولتراسونیک | SunFounder Robojax

در این درس، خودروی هوشمند خود را با قابلیت دیدن و واکنش به محیط اطراف با استفاده از یک حساس(حس کننده) اولتراسونیک ارتقا می‌دهیم. با اندازه‌گیری فاصله تا اشیاء جلوی خودرو، خودرو می‌تواند تصمیمات هوشمندانه‌ای بگیرد: وقتی مسیر باز است به جلو حرکت می‌کند، وقتی یک شیء در منطقه هشدار قرار دارد می‌ایستد، و وقتی مانع بیش از حد نزدیک می‌شود به عقب برمی‌گردد. این پروژه بر پایه کنترل موتور و اصول سنسورهایی است که قبلاً یاد گرفته‌اید، و نتیجه آن یک وسیله نقلیه واقعاً خودمختار است.

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

این فقط یک اسباب‌بازی نیست؛ بلکه گامی اساسی به سوی ساخت پروژه‌های رباتیک پیچیده‌تر است. منطقی که در اینجا پیاده‌سازی می‌کنید—حس کردن، فکر کردن، عمل کردن—همان منطقی است که در همه چیز از جاروبرقی‌های رباتیک تا اتوماسیون صنعتی استفاده می‌شود. در اینجا چند ایده برای الهام گرفتن در ساخت‌های خودتان آورده شده است:

  • مریخ‌نورد خودمختار: رباتی بسازید که بتواند یک اتاق یا راهرو را بدون برخورد به دیوارها یا مبلمان کاوش کند.
  • سیستم هشدار مجاورت: حساس(حس کننده) اولتراسونیک را روی یک سرو موتور نصب کنید تا یک منطقه را اسکن کند و وقتی یک مزاحم وارد منطقه تعریف‌شده می‌شود، آلارم یا چراغی را فعال کند.
  • دستیار هوشمند پارک: سیستمی بسازید که از خوانش‌های فاصله برای هدایت یک وسیله نقلیه به یک فضای تنگ استفاده کند و بازخورد بصری یا صوتی ارائه دهد.

این راهنما بر اساس کیت ۳-در-۱ SunFounder آردوینو و پروژه «بازی با ماجیول اولتراسونیک» آن است. ما سیم‌بندی را مرور می‌کنیم، شِفر (کود) تصمیم‌گیری را توضیح می‌دهیم و خودرو را در عمل نشان می‌دهیم.

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

چگونه منطق اجتناب از مانع کار می‌کند

هسته این پروژه یک درخت تصمیم ساده اما قدرتمند است. حساس(حس کننده) اولتراسونیک به طور مداوم فاصله تا شیء مستقیماً جلوی خود را اندازه‌گیری می‌کند. سپس این مقدار فاصله برای کنترل موتورهای خودرو استفاده می‌شود، همانطور که در نمودار زیر نشان داده شده است.

  • اگر فاصله > ۲۵ سانتی‌متر: مسیر باز است، بنابراین خودرو به جلو حرکت می‌کند.
  • اگر ۱۰ سانتی‌متر < فاصله <= ۲۵ سانتی‌متر: یک شیء در «منطقه هشدار» شناسایی می‌شود، بنابراین خودرو برای جلوگیری از برخورد می‌ایستد.
  • اگر ۲ سانتی‌متر < فاصله <= ۱۰ سانتی‌متر: یک شیء به طور خطرناکی نزدیک است. خودرو برای ایجاد فضای بیشتر به عقب برمی‌گردد.
  • اگر فاصله <= ۲ سانتی‌متر: خوانش احتمالاً خطا است (بیش از حد نزدیک برای اندازه‌گیری دقیق)، بنابراین خودرو به عنوان یک اقدام ایمنی می‌ایستد.

قطعات سخت‌افزاری

برای ساخت این پروژه، به قطعات زیر نیاز دارید که همه آنها در کیت ۳-در-۱ SunFounder گنجانده شده‌اند.

  • ۱x آردوینو اونو (یا برد سازگار)
  • ۱x شاسی خودروی هوشمند با دو موتور دنده‌ای
  • ۱x ماجیول درایور موتور L298N
  • ۱x حساس(حس کننده) فاصله اولتراسونیک HC-SR04
  • ۱x بردبورد
  • سیم‌های جامپر
  • منبع تغذیه برای خودرو (مثلاً بسته باتری)
26-SunFounder-Car-4-Ultrasonic.mp4_snapshot_00.00.000

راهنمای سیم‌بندی

سیم‌بندی درایور موتور، حساس(حس کننده) اولتراسونیک و آردوینو را به هم متصل می‌کند. درایور موتور چرخ‌های خودرو را کنترل می‌کند، در حالی که حساس(حس کننده) اولتراسونیک به عنوان «چشم‌های» آن عمل می‌کند.

در اینجا نمودار اتصال از مستندات SunFounder آمده است:

بیایید اتصالات را تجزیه کنیم. ابتدا ریل‌های مثبت و منفی بردبورد را از پایه‌های ۵ ولت و GND آردوینو تغذیه کنید. سپس حساس(حس کننده) اولتراسونیک به صورت زیر متصل می‌شود:

  • VCC (برق): به ریل مثبت روی بردبورد متصل می‌شود.
  • GND (زمین): به ریل منفی روی بردبورد متصل می‌شود.
  • Trig (محرک): به پایه دیجیتال ۳ روی آردوینو متصل می‌شود. این پایه پالس اولتراسونیک را ارسال می‌کند.
  • Echo (دریافت): به پایه دیجیتال ۴ روی آردوینو متصل می‌شود. این پایه پالس بازتاب‌شده را دریافت می‌کند.

اتصالات درایور موتور مانند درس‌های قبلی است. چهار پایه کنترل (IN1، IN2، IN3، IN4) به پایه‌های دیجیتال ۵، ۶، ۹ و ۱۰ آردوینو متصل می‌شوند. این پایه‌ها سرعت و جهت دو موتور را کنترل می‌کنند. اطمینان حاصل کنید که برق و زمین درایور موتور به درستی به بسته باتری و زمین آردوینو متصل شده‌اند. (در ویدیو در ۰۲:۲۴)

توضیح شِفر (کود)

شِفر (کود) این پروژه رفتار خودرو را بر اساس خوانش فاصله از حساس(حس کننده) اولتراسونیک کنترل می‌کند. منطق ساده و آسان برای سفارشی‌سازی است. بیایید به بخش‌های کلیدی و قابل تنظیم توسط کاربر نگاه کنیم.

۱. تعریف پایه‌ها

در بالای اسکچ، پایه‌های موتورها و حساس(حس کننده) اولتراسونیک تعریف شده‌اند. اگر قطعات خود را به پایه‌های مختلف آردوینو متصل کرده‌اید، می‌توانید اینها را تغییر دهید.

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;

در اینجا، A_1A، A_1B، B_1A و B_1B موتورهای چپ و راست را از طریق درایور L298N کنترل می‌کنند. trigPin و echoPin برای حساس(حس کننده) اولتراسونیک هستند.

۲. متغیرهای رفتار و منطق

رفتار اصلی در داخل تابع loop() کنترل می‌شود. این جایی است که می‌توانید «شخصیت» خودرو را تنظیم کنید.

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

در اینجا نحوه سفارشی‌سازی آن آمده است:

  • آستانه‌های فاصله: اعداد 25 و 10 مناطق «ایمن» و «خطر» را بر حسب سانتی‌متر تعریف می‌کنند. 25 را افزایش دهید تا خودرو زودتر متوقف شود، یا آن را کاهش دهید تا به موانع نزدیک‌تر شود. عدد 2 یک حاشیه ایمنی برای نادیده گرفتن خوانش‌های اشتباه از اشیاء بیش از حد نزدیک است.
  • سرعت موتور: مقدار 200 که به moveForward() و moveBackward() ارسال می‌شود، سرعت خودرو را تنظیم می‌کند. این مقدار می‌تواند از 0 تا 255 باشد. مقدار کمتر، مانند 150، باعث می‌شود خودرو آهسته‌تر و محتاطانه‌تر حرکت کند.

بقیه شِفر (کود) شامل تابع readSensorData() است که زمان‌بندی حساس(حس کننده) اولتراسونیک را برای محاسبه فاصله مدیریت می‌کند، و توابع moveForward()، moveBackward() و stopMove() که درایور موتور را برای اجرای عمل مورد نظر کنترل می‌کنند.

رفع یک خطای رایج

ممکن است با خطایی مانند 'moveForward' was not declared in this scope مواجه شوید. این اتفاق می‌افتد زیرا Arduino IDE شِفر (کود) را از بالا به پایین می‌خواند. وقتی به تابع loop() می‌رسد، هنوز توابع تعریف‌شده در پایین آن را نمی‌شناسد. برای رفع این مشکل، باید «پروتوتایپ‌های تابع» را قبل از تابع setup() اضافه کنید. این‌ها صرفاً اعلان‌هایی از نام تابع و نوع بازگشتی هستند که با یک سمی‌کالن پایان می‌یابند.

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

اضافه کردن این خطوط به کامپایلر می‌گوید: «این توابع وجود دارند و بعداً تعریف خواهند شد»، که خطا را برطرف می‌کند. (در ویدیو در 09:21)

بهبود پایداری حساس(حس کننده)

در طول آزمایش، ممکن است متوجه شوید خودرو حتی زمانی که مسیر باز است توقف یا لرزش می‌کند. این اغلب به این دلیل است که حلقه خیلی سریع اجرا می‌شود و حساس(حس کننده) اولتراسونیک زمان کافی برای دریافت سیگنال پژواک ندارد و در نتیجه خوانش 0 سانتی‌متر می‌دهد. برای رفع این مشکل، یک تأخیر کوچک در انتهای تابع loop() اضافه کنید تا به حساس(حس کننده) زمان کار بدهید.

void loop() {
    float distance = readSensorData();
    if (distance > 25) {
      moveForward(200);
    }
    else if (distance < 10 && distance > 2) {
      moveBackward(200);
    } else {
      stopMove();
    }
    delay(100); // یک تأخیر 100 میلی‌ثانیه‌ای برای خوانش‌های پایدار اضافه کنید
  }

یک تأخیر 100 میلی‌ثانیه‌ای معمولاً برای دریافت خوانش‌های فاصله پایدار و سازگار کافی است. (در ویدیو در 10:56)

نمایش زنده پروژه

پس از آپلود شِفر (کود)، Serial Monitor را باز کنید. متنی را مشاهده خواهید کرد که وضعیت خودرو را نشان می‌دهد، مانند «Forward»، «Reverse» یا «Stop».

در نمایش، خودرو رو به یک مانع قرار گرفته است. وقتی مانع بیش از 25 سانتی‌متر فاصله دارد، خودرو به جلو حرکت می‌کند. همان‌طور که دست خود را نزدیک‌تر می‌کنید، خودرو وقتی فاصله به زیر 25 سانتی‌متر می‌رسد متوقف می‌شود. اگر دست خود را خیلی نزدیک، در محدوده 10 سانتی‌متر، بیاورید، خودرو به عقب حرکت می‌کند. این رفتار به وضوح در ویدیو قابل مشاهده است و تأیید می‌کند که منطق اجتناب از مانع به درستی کار می‌کند. (در ویدیو در 11:53)

نتیجه‌گیری

تبریک! شما با موفقیت یک خودروی هوشمند ساخته‌اید که می‌تواند در محیط خود حرکت کند و از موانع اجتناب کند. این پروژه ورودی حساس(حس کننده)، منطق تصمیم‌گیری و کنترل موتور را در یک سیستم واحد و کاربردی ترکیب می‌کند. شما نه تنها نحوه استفاده از حساس(حس کننده) اولتراسونیک را یاد گرفته‌اید، بلکه یک الگوریتم کنترل ساده را نیز پیاده‌سازی کرده‌اید که پایه‌ای برای ربات‌های خودمختار بسیار پیچیده‌تر است.

فصل‌ها

  • [00:00] مقدمه‌ای بر اجتناب از مانع
  • [01:16] نمای کلی پروژه و پیش‌نیازها
  • [02:24] سیم‌کشی حساس(حس کننده) اولتراسونیک و درایور موتور
  • [04:56] باز کردن شِفر (کود) پروژه
  • [05:12] توضیح شِفر (کود): منطق و توابع
  • [08:34] آپلود شِفر (کود) و امتحان اولیه
  • [09:21] عیب‌یابی: پروتوتایپ‌های تابع
  • [10:56] عیب‌یابی: افزودن تأخیر برای پایداری
  • [11:53] نمایش زنده اجتناب از مانع

تصاویر

27 SunFounder Car 5 follow hand
27 SunFounder Car 5 follow hand
26 SunFounder Car 4 ultrasonic video snapshot 00.09.009
26 SunFounder Car 4 ultrasonic video snapshot 00.09.009
26 SunFounder Car 4 ultrasonic video snapshot 02.26.146
26 SunFounder Car 4 ultrasonic video snapshot 02.26.146
26 SunFounder Car 4 ultrasonic video snapshot 00.00.000
26 SunFounder Car 4 ultrasonic video snapshot 00.00.000
899-Lesson 26/31: Avoiding Obstacle Using Ultrasonic Sensor
زبان: 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);
}

مواردی که ممکن است به آن‌ها نیاز داشته باشید

فایل‌ها📁

کتابخانه‌های آردوینو (zip)