مبدأ الاستشعار بالموجات فوق الصوتية
في هذأ المدونة، سنلقي نظرة على بناء نظام رادار ذاتي باستخدام Arduino Uno، ومحرك سيرفو ومستشعر فوق صوتي HC-SR04. لا يتضمن هذا الإعداد الإلكترونيات الأساسية والبرمجة فحسب، بل يتضمن أيضًا حوامل مطبوعة ثلاثية الأبعاد مخصصة لكل من السيرفو والمستشعر، مما يزيد من المتانة الميكانيكية والوظائف الوظيفية للمشروع. سيقوم نظام الرادار هذا بمسح البيئة المحيطة وعرض الأجسام المكتشفة على واجهة مرئية، لمحاكاة شاشة الرادار.
يعمل جهاز الاستشعار بالموجات فوق الصوتية عن طريق إرسال موجة صوتية فوق صوتية (بتردد أعلى مما يمكن للإنسان سماعه) إلى جسم ما ثم الاستماع لصدى تلك الموجة. من خلال حساب الوقت بين إرسال الإشارة واستقبال الصدى، يمكن للمستشعر تحديد المسافة إلى الجسم. هذه الطريقة مشابهة لكيفية تنقل الخفافيش في الظلام.
عادةً ما يتكون جهاز الاستشعار بالموجات فوق الصوتية من مكونين رئيسيين: مرسل ومستقبل. يصدر المرسل موجات صوتية عالية التردد، التي تنتشر عبر الهواء حتى تصطدم بجسم ما. عندما تصل هذه الموجات الصوتية إلى الجسم، تنعكس مرة أخرى نحو الجهاز، حيث يستشعرها المستقبل على شكل صدى.
- انتقال الموجات الصوتية: يصدر الجانب المرسل من الجهاز نبضة صوتية، وهي موجة صوتية بتردد يكون عمومًا فوق نطاق السمع البشري، عادةً حوالي 40 كيلوهرتز.
- انعكاس الموجات الصوتية: عندما تصطدم الموجة الصوتية المُصدرة بجسم، ترتد مرة أخرى نحو الجهاز. يُشار غالبًا إلى هذه الإشارة المُعادة بالصدى. يمكن أن تتأثر طبيعة الموجة الصوتية المنعكسة بشكل وحجم ومادة الجسم الذي تصطدم به.
- استقبال الصدى: يقوم جزء المستقبل في الجهاز بكشف هذا الصدى. من خلال تحديد الوقت بدقة الذي يستغرقه الصدى للعودة، يمكن للجهاز حساب المسافة إلى الجسم. يعتمد هذا الحساب على سرعة الصوت في الهواء، والتي تبلغ تقريبًا 340 مترًا في الثانية في الظروف القياسية.
- حساب المسافة: تُحسب المسافة إلى الجسم عادةً بقياس الفترة الزمنية بين لحظة إصدار الموجة الصوتية ولحظة استقبال الصدى. باستخدام الصيغة
المسافة = 1/2 × الزمن × سرعة الصوت، يحسب الجهاز المسافة. يُستخدم معامل 1/2 لأن الموجة الصوتية تسافر إلى الجسم ثم تعود إلى الجهاز، وبالتالي تغطي المسافة مرتين.
أكثر أجهزة الاستشعار بالموجات فوق الصوتية شيوعًا المستخدمة في مشاريع الـ DIY هو HC-SR04. يقدم هذا الجهاز استشعار ممتاز للمسافات، بتكلفة منخفضة ومتوفر بشكل واسع. يمكن لجهاز HC-SR04 قياس المسافات من 2 سم إلى 400 سم بدقة تصل إلى 3 مم، مما يجعله مناسبًا لمجموعة واسعة من التطبيقات.
المواد والأدوات اللازمة لبناء رادار اردوينو
- أردوينو أونو
- مستشعر الموجات فوق الصوتية HC-SR04
- محرك سيرفو
- أسلاك التوصيل
- لوحة التجارب (Breadboard)
- طابعة ثلاثية الأبعاد مع خيوط طباعة ثلاثية الأبعاد (Filament)
- جهاز كمبيوتر مثبت عليه Arduino IDE و Processing IDE
تصميم حوامل ثلاثية الأبعاد
قبل تجميع الإلكترونيات، ابدأ بتصميم حوامل مخصصة للمستشعر فوق الصوتي والمحرك المؤازر. يمكن إنشاء هذه الحوامل باستخدام برنامج CAD مثل Autodesk Fusion 360.
حامل المستشعر: صمم ركيزة تتناسب مع HC-SR04 وتحتوي على ميزات تسمح بتوصيلها بسهولة بمحرك السيرفو. تأكد من وجود فتحات لأجهزة الإرسال والاستقبال بالموجات فوق الصوتية الخاصة بالمستشعر.
حامل محرك السيرفو: قم بإنشاء قاعدة تحمل محرك السيرفو بإحكام ويمكن وضعها على منصة ثابتة. يجب أن يسمح الجزء العلوي من حامل السيرفو بتركيب حامل المستشعر بسلاسة وتدويره بحرية.
بمجرد الانتهاء من التصميمات الخاصة بك، استخدم طابعة ثلاثية الأبعاد لطباعة الحوامل باستخدام خيوط قوية مثل PLA أو ABS.
تجميع الأجهزة
بعد طباعة الحوامل الخاصة بك:
- قم بتركيب المستشعر فوق الصوتي: قم بتثبيت HC-SR04 في حامله المطبوع ثلاثي الأبعاد. تأكد من عدم إعاقة أي جزء من الحامل للإشارات فوق الصوتية.
- ثبِّت محرك السيرفو في الحامل الخاص به: ضع السيرفو في المقبس الخاص به، مع التأكد من أنه مثبت بإحكام وأن الأسلاك يمكن أن تمتد إلى الأردوينو دون إجهاد.
- قم بتجميع المكونات: ثبت حامل الجهاز على محرك السيرفو، عادةً على قرن السيرفو، باستخدام مسامير صغيرة أو تصميم يُثبت بالضغط يسمح للجهاز بالدوران مع حركات السيرفو.
التكوين الإلكتروني والتوصيلات الكهربائية
- توصيلات محركات السيرفو:
دبوس الإشارة: قم بالتوصيل إلى الدبوس 8 على الأردوينو.
الطاقة (VCC) والأرضي (GND): قم بالتوصيل إلى 5V وGND على الأردوينو. - توصيلات مستشعر الموجات فوق الصوتية:
VCC: أيضاً لـ Arduino 5 فولت.
GND: إلى أحد دبابيس GND في Arduino.
TRIG: إلى السن 9 في الأردوينو.
ECHO: إلى الدبوس 10 في الأردوينو.
استخدم اللوح لتسهيل التوصيلات وإدارة أي مكونات إضافية أو توسعات مستقبلية.
التكوين الإلكتروني مع الجرس buzzer
برمجة الأردوينو
بمجرد توصيل كل شيء، ستحتاج إلى برمجة الأردوينو لقراءة الإشارات من جهاز الاستشعار بالموجات فوق الصوتية:
/** * Author: Omar Draidrya * Date: 2024/05/09 * This code controls a servo motor and measures distance using an ultrasonic sensor. */ #include <Servo.h> Servo myServo; // Create a servo object const int trigPin = 9; // Trigger pin of the ultrasonic sensor const int echoPin = 10; // Echo pin of the ultrasonic sensor long duration; // Variable to store the duration of the pulse int distance; // Variable to store the distance calculated void setup() { pinMode(trigPin, OUTPUT); // Set the trigger pin as an output pinMode(echoPin, INPUT); // Set the echo pin as an input Serial.begin(9600); // Initialize serial communication myServo.attach(8); // Attach the servo on pin 8 to the servo object } void loop() { for (int i = 15; i <= 165; i++) { // Sweep the servo from 15 to 165 degrees myServo.write(i); // Move the servo to position 'i' delay(30); // Wait for 30 milliseconds distance = calculateDistance();// Calculate the distance Serial.print(i); // Print the servo position Serial.print(","); // Print a comma Serial.print(distance); // Print the distance Serial.print("."); // Print a period } for (int i = 165; i > 15; i--) { // Sweep the servo from 165 to 15 degrees myServo.write(i); // Move the servo to position 'i' delay(30); // Wait for 30 milliseconds distance = calculateDistance();// Calculate the distance Serial.print(i); // Print the servo position Serial.print(","); // Print a comma Serial.print(distance); // Print the distance Serial.print("."); // Print a period } } int calculateDistance() { digitalWrite(trigPin, LOW); // Clear the trigger pin delayMicroseconds(2); // Wait for 2 microseconds digitalWrite(trigPin, HIGH); // Set the trigger pin high delayMicroseconds(10); // Wait for 10 microseconds digitalWrite(trigPin, LOW); // Set the trigger pin low duration = pulseIn(echoPin, HIGH); // Read the echo pin and return the duration of the pulse distance = duration * 0.034 / 2; // Calculate the distance return distance; // Return the distance }
برمجة الأردوينو buzzer
/** * Author: Omar Draidrya * Date: 2024/05/09 * This code controls a servo motor, measures distance using an ultrasonic sensor, and activates a buzzer when an obstacle is close. */ #include <Servo.h> Servo myServo; // Create a servo object const int trigPin = 9; // Trigger pin of the ultrasonic sensor const int echoPin = 10; // Echo pin of the ultrasonic sensor const int buzzerPin = 12; // Pin for the buzzer long duration; // Variable to store the duration of the pulse int distance; // Variable to store the distance calculated void setup() { pinMode(trigPin, OUTPUT); // Set the trigger pin as an output pinMode(echoPin, INPUT); // Set the echo pin as an input pinMode(buzzerPin, OUTPUT); // Set the buzzer pin as an output Serial.begin(9600); // Initialize serial communication myServo.attach(8); // Attach the servo on pin 8 to the servo object } void loop() { for (int i = 15; i <= 165; i++) { // Sweep the servo from 15 to 165 degrees myServo.write(i); // Move the servo to position 'i' delay(30); // Wait for 30 milliseconds distance = calculateDistance();// Calculate the distance Serial.print(i); // Print the servo position Serial.print(","); // Print a comma Serial.print(distance); // Print the distance Serial.print("."); // Print a period if (distance <= 10) { // If the distance is less than or equal to 10 cm tone(buzzerPin, 2000); // Activate the buzzer with a frequency of 2000 Hz } else { noTone(buzzerPin); // Deactivate the buzzer } } for (int i = 165; i > 15; i--) { // Sweep the servo from 165 to 15 degrees myServo.write(i); // Move the servo to position 'i' delay(30); // Wait for 30 milliseconds distance = calculateDistance();// Calculate the distance Serial.print(i); // Print the servo position Serial.print(","); // Print a comma Serial.print(distance); // Print the distance Serial.print("."); // Print a period if (distance <= 10) { // If the distance is less than or equal to 10 cm tone(buzzerPin, 2000); // Activate the buzzer with a frequency of 2000 Hz } else { noTone(buzzerPin); // Deactivate the buzzer } } } int calculateDistance() { digitalWrite(trigPin, LOW); // Clear the trigger pin delayMicroseconds(2); // Wait for 2 microseconds digitalWrite(trigPin, HIGH); // Set the trigger pin high delayMicroseconds(10); // Wait for 10 microseconds digitalWrite(trigPin, LOW); // Set the trigger pin low duration = pulseIn(echoPin, HIGH); // Read the echo pin and return the duration of the pulse distance = duration * 0.034 / 2; // Calculate the distance return distance; // Return the distance }
التصور باستخدام برنامج Processing:
برنامج Processing IDE هو دفتر رسم برمجي مرن ولغة لتعلم البرمجة في سياق الفنون البصرية. إنه مفتوح المصدر وتم تطويره بواسطة الفنانين والمصممين كبديل سهل الاستخدام لبيئات البرمجة المعقدة. يناسب البرنامج بشكل خاص إنشاء مشاريع بصرية وتفاعلية. يوفر Processing طريقة مباشرة لدمج الإدخالات الواقعية أو الرقمية والتصور أو التفاعل معها بطرق متنوعة. يُستخدم غالبًا في الإعدادات التعليمية لتقديم البرمجة لأنه يوفر تغذية راجعة بصرية فورية ويشجع على فهم أعمق لكيفية تأثير الكود على الناتج. يجعل ذلك من Processing أداة ممتازة لتصور البيانات من أجهزة الاستشعار في مشاريع الأردوينو، مثل واجهة الرادار، حيث يكون فهم العلاقات المكانية والحركة أمرًا حاسمًا.
لتصور واجهة الرادار، سنستخدم برنامج Processing IDE، الذي يمكنه تفسير وعرض البيانات المرسلة عبر مخرج السيريال (التسلسلي) للأردوينو. إليك كود Processing لعرض شاشة الرادار:
/** * Date: 2024/05/09 * This code creates a radar-like display using Processing, receiving data from a serial port. */ import processing.serial.*; Serial communicationPort; // Serial communication port String serialData = ""; // Variable to store serial data float scanAngle = 0; // Variable to store scan angle float scanDistance = 0; // Variable to store scan distance int radarRadius = 800; // Radar radius int maxDistance = 40; // Maximum display distance in cm void setup() { size(1920, 1080); // Set the size of the window smooth(); // Enable anti-aliasing String portName = Serial.list()[0]; // Get the first serial port (adjust index as needed) communicationPort = new Serial(this, portName, 9600); // Initialize serial communication communicationPort.bufferUntil('.'); // Set the buffer until '.' character background(0); // Set the background to black } void draw() { drawRadarBackground(); // Draw the radar background if (serialData.length() > 0) { parseSerialData(); // Parse the incoming serial data drawDetection(); // Draw the detected object } displayInfo(scanDistance, scanAngle); // Update display information } void drawRadarBackground() { pushMatrix(); translate(width / 2, height - 200); // Position the radar noFill(); stroke(80); // Gray grid lines strokeWeight(1); for (int i = 0; i < 5; i++) { float r = radarRadius * (i + 1) / 5.0; arc(0, 0, r * 2, r * 2, PI, TWO_PI); // Draw radar arcs } for (int i = 0; i < 180; i += 10) { float x = radarRadius * cos(radians(i)); float y = radarRadius * sin(radians(i)); line(0, 0, x, -y); // Draw radar lines if (i % 30 == 0) { fill(255); textSize(16); text(i + "°", x + 5, -y + 5); // Display angle labels } } popMatrix(); } void parseSerialData() { String[] tokens = serialData.split(","); if (tokens.length >= 2) { scanAngle = float(tokens[0]); // Parse the scan angle scanDistance = float(tokens[1]);// Parse the scan distance } } void drawDetection() { float angle = radians(scanAngle); float distance = scanDistance; float x = distance * 20; // Scale distance for display float fullX = radarRadius * cos(angle); float fullY = radarRadius * sin(angle); pushMatrix(); translate(width / 2, height - 200); strokeWeight(4); // Fade effect noStroke(); fill(0, 20); // Semi-transparent black overlay rect(-radarRadius, -radarRadius, radarRadius * 2, radarRadius); // Detection line if (distance > 0 && distance <= maxDistance) { stroke(0, 0, 255); // Blue for detected area line(0, 0, x * cos(angle), -x * sin(angle)); stroke(255, 165, 0); // Orange for the remaining area line(x * cos(angle), -x * sin(angle), fullX, -fullY); } else { stroke(0, 0, 255); // Blue if no detection line(0, 0, fullX, -fullY); } popMatrix(); serialData = ""; // Clear data after drawing } void displayInfo(float distance, float angle) { fill(0); // Black background for text area noStroke(); rect(10, 10, 260, 80); // Area for text fill(255); textSize(20); text("Angle: " + nf(angle, 1, 2) + "°", 30, 30); // Display angle information text("Distance: " + nf(distance, 1, 2) + " cm", 30, 60); // Display distance information } void serialEvent(Serial p) { serialData = p.readStringUntil('.'); // Read serial data until '.' character serialData = serialData.substring(0, serialData.length() - 1); // Remove the '.' character }
المعايرة والاختبار
بمجرد إعداد البرنامج، حان وقت معايرة واختبار نظام الرادار الخاص بك. قم بتشغيل الأردوينو وألق نظرة على برنامج Processing لترى مدى جودة الرادار في اكتشاف الأجسام. قم بضبط المدى والحساسية حسب الحاجة عن طريق تغيير البارامترات في برنامج الأردوينو.
الخاتمة
يوضح هذا المشروع كيفية دمج محرك سيرفو وجهاز استشعار بالموجات فوق الصوتية لإنشاء نظام رادار بسيط باستخدام الأردوينو. يقوم هذا الإعداد بمسح البيئة وتصور البيانات في الوقت الفعلي، مما يجعله مثاليًا للأغراض التعليمية، مشاريع الهوايات، وحتى التطبيقات العملية في مجال الروبوتات والاستشعار.