
مستشعر المسافة بالموجات فوق الصوتية إتش سي إس آر ٠٤ مع لوحة أردوينو أونو آر٣
يُعدّ مستشعر المسافة بالموجات فوق الصوتية HC-SR04 جهازاً غير مكلف ومفيداً جداً لمشاريع الروبوتات ومعدّات الاختبار. هذا المستشعر الصغير قادر على قياس المسافة بينه وبين أقرب جسمٍ صلب، وهي معلومة مفيدة حقاً إذا كنت تحاول تجنّب الاصطدام بجدار!
يمكن توصيل HC-SR04 مباشرةً بلوحة أردوينو أو بأي متحكم دقيق آخر، وهو يعمل على جهد 5 فولت. كما يمكن استخدامه مع راسبيري باي، لكن بما أن HC-SR04 يتطلب منطق 5 فولت، فستحتاج إلى مقاومتَين لتوصيله بمنفذ GPIO ذي الـ3.3 فولت في الراسبيري باي.
يستطيع مستشعر المسافة هذا قياس مسافاتٍ تتراوح بين 2 سم و400 سم (أي ما يقارب بوصة واحدة إلى 13 قدماً لمن لا "يتحدثون" بالنظام المتري). وهو جهاز منخفض استهلاك التيار، ما يجعله مناسباً للأجهزة التي تعمل بالبطاريات. وكميزة إضافية، فإنه يبدو رائع الشكل، أشبه بعينَي روبوت "وول-إي" لاختراعك الروبوتي الجديد!
فتابع القراءة وسأريك كيفية توصيل مستشعر المسافة بالموجات فوق الصوتية HC-SR04 واستخدامه. كما سنُخضعه لبعض الاختبارات
ما هي الموجات فوق الصوتية؟
تشير عبارة "فوق صوتية" إلى الموجات الصوتية التي تتجاوز تردّداتها النطاق الذي تستطيع الأذن البشرية سماعه.

يستطيع البشر سماع الموجات الصوتية التي تهتزّ بين نحو 20 مرة في الثانية (نسمعها كصوتٍ عميقٍ هادر) و20,000 مرة في الثانية (تبدو كصفيرٍ عالي النبرة جداً). أما الموجات فوق الصوتية فتتجاوز تردّداتها 20,000 هرتز، ما يجعلها صامتةً تماماً بالنسبة للأذن البشرية.
ومع أننا لا نستطيع سماع الأصوات فوق الصوتية، فإن كثيراً من الحيوانات تستطيع ذلك! تسمع الكلاب أصواتاً تصل إلى نحو 45,000 هرتز، ولهذا تعمل صفّارات الكلاب — فهي تُصدر أصواتاً أعلى من أن يسمعها الإنسان لكنها مثاليةٌ لتلتقطها الكلاب. أما الخفافيش فتستخدم تردّداتٍ فوق صوتية أعلى (تصل إلى 200,000 هرتز) للتنقّل والصيد في الظلام عبر تحديد الموقع بالصدى.
كيف يعمل مستشعر HC-SR04
تستخدم مستشعرات المسافة بالموجات فوق الصوتية نبضاتٍ من الصوت فوق الصوتي (صوت أعلى من نطاق سمع الإنسان) لاكتشاف المسافة بينها وبين الأجسام الصلبة القريبة. تتكوّن هذه المستشعرات من مكوّنَين رئيسيَّين:
مُرسِل فوق صوتي – يُرسِل نبضات الصوت فوق الصوتي، ويعمل عند تردّد 40 كيلوهرتز.
مُستقبِل فوق صوتي – يستمع المستقبِل للنبضات المُرسَلة. وإذا التقطها، فإنه يُنتج نبضة خرجٍ يمكن استخدام عرضها لتحديد المسافة التي قطعتها النبضة.
يحتوي مستشعر HC-SR04 على التوصيلات الأربع التالية:
VCC – مصدر الطاقة الموجب بجهد 5 فولت.
Trig – طرف "التشغيل" (Trigger)، وهو الطرف الذي يُفعَّل لإرسال النبضات فوق الصوتية.
Echo – الطرف الذي يُنتج نبضةً عند استقبال الإشارة المرتدّة. ويتناسب طول هذه النبضة مع الزمن الذي استغرقته الإشارة المُرسَلة حتى تُكتشَف.
GND – طرف الأرضي (Ground).

يعمل الجهاز على النحو التالي:
تُطبَّق نبضة بجهد 5 فولت ومدّتها 10 ميكروثانية على الأقل على طرف التشغيل (Trigger).
يستجيب مستشعر HC-SR04 بإرسال دفقةٍ من ثماني نبضات بتردّد 40 كيلوهرتز. هذا النمط المكوّن من 8 نبضات يجعل "البصمة فوق الصوتية" للجهاز فريدة، ما يتيح للمستقبِل التمييز بين النمط المُرسَل والضوضاء فوق الصوتية في الخلفية.
تنتقل النبضات فوق الصوتية الثماني عبر الهواء مبتعدةً عن المُرسِل. وفي الوقت نفسه، يرتفع طرف Echo إلى الحالة العالية ليبدأ بتكوين بداية إشارة الصدى المرتدّ.
إذا لم ترتدّ النبضة، فإن إشارة Echo تنتهي مهلتها بعد 38 مللي ثانية وتعود إلى الحالة المنخفضة. وهذا يُنتج نبضة مدّتها 38 مللي ثانية تشير إلى عدم وجود أي عائقٍ ضمن مدى المستشعر.
أما إذا ارتدّت النبضة، فإن طرف Echo ينخفض إلى الحالة المنخفضة عند استقبال الإشارة. وهذا يُنتج نبضةً يتراوح عرضها بين 150 ميكروثانية و25 مللي ثانية، تبعاً للزمن الذي استغرقه استقبال الإشارة.
يُستخدَم عرض النبضة المستقبَلة لحساب المسافة إلى الجسم العاكس. وتذكّر أن النبضة تمثّل الزمن الذي استغرقته الإشارة في الذهاب والارتداد، لذا فلحساب المسافة عليك قسمة الناتج على النصف.


يوضّح الشكل أدناه أبعاد مستشعر المسافة بالموجات فوق الصوتية HC-SR04، إضافةً إلى زاوية التشغيل الفعّالة. وكما ترى، يكون المستشعر أكثر دقّةً عندما يكون الجسم المراد اكتشافه أمامه مباشرةً، لكنك تحصل مع ذلك على استجابةٍ من الأجسام الواقعة ضمن "نافذة" قدرها 45 درجة. وتوصي الوثائق بحصر هذه النافذة في 30 درجة (15 درجة على كل جانب) للحصول على قراءاتٍ دقيقة.
توصيل مستشعر HC-SR04
توصيل مستشعر HC-SR04 بلوحة الأردوينو سهلٌ إلى حدٍّ كبير. ستحتاج إلى طرفَي دخل/خرج رقميَّين (I/O)، إضافةً إلى توصيلةٍ بطرفَي الـ5 فولت والأرضي في الأردوينو.

في الواقع، إذا كانت أطراف الأردوينو لديك قليلة، فيمكنك حتى توصيل طرفَي Trigger وEcho في مستشعر HC-SR04 بطرف دخل/خرج رقمي واحد فقط في الأردوينو، واستخدام الكود لتبديل الطرف بين وضع الخرج (لإرسال نبضة الـ10 ميكروثانية) ووضع الدخل (لاستقبال نبضة Echo). في الواقع، بعض المستشعرات فوق الصوتية تحتوي على طرفٍ واحد فقط يقوم بمهمّتَي Trigger وEcho معاً. سأناقش هذا الأمر وأقدّم مثالاً عليه لاحقاً، فتابع القراءة.
معظم الأمثلة التي سأعرضها هنا تستخدم طريقة الطرفَين الأكثر شيوعاً. ويمكن استخدام أي لوحة أردوينو وأي أطراف دخل/خرج رقمية متاحة، فإذا رغبت في توصيله بمجموعةٍ مختلفة من الأطراف، فما عليك سوى تعديل الأكواد لتعكس تلك التغييرات. وفي عرضنا التوضيحي سأستخدم لوحة أردوينو أونو، والطرف 10 لِـ Trigger، والطرف 13 لِـ Echo.
تؤكّد ملاحظات التطبيق الخاصة بمستشعر HC-SR04 على ضرورة توصيل طرف الأرضي قبل توصيل طرف VCC (5 فولت)، لذا إذا كنت تجرّب "مباشرةً" على لوحة تجارب دون لحام، فقد يكون من المفيد أن تضع ذلك في بالك.
والآن بعد أن وصّلنا مستشعر المسافة بالموجات فوق الصوتية، حان وقت كتابة بعض الكود واختباره.
عرض توضيحي أساسي باستخدام الأردوينو
في عرضنا التوضيحي الأول سنكتفي باختبار المستشعر لنرى ما إذا كان يعمل. الكود بسيطٌ إلى حدٍّ كبير، وهو يستخدم الـ Serial Monitor لعرض المسافة التي يكتشفها مقيسةً بالسنتيمتر. لنُلقِ نظرةً تفصيلية عليه.
لاختبار دقّة مستشعر المسافة بالموجات فوق الصوتية، جهّزتُ لوحة اختبار مع مستشعرٍ مثبّتٍ على أحد طرفَيها (استخدمتُ لاصق الفيلكرو لتثبيته). ووضعتُ مسطرةً بطول متر واحد على اللوحة كي أتمكّن من اختبار المستشعر في المدى من 2 إلى 100 سم. ويمكنك مشاهدة الفيديو المرافق لهذا المقال إذا أردت رؤية نتائج هذا العرض والعروض الأخرى.
إذا أردت عرض نتائجك بالبوصة بدلاً من السنتيمتر، فهناك طريقتان للقيام بذلك:
استخدام قيمة سرعة الصوت بالنظام الإمبراطوري بدلاً من النظام المتري. فعند مستوى سطح البحر وبدرجة حرارة 20 مئوية (68 فهرنهايت)، ينتقل الصوت بسرعة 343 متراً في الثانية، أي ما يعادل 1,125 قدماً في الثانية أو 13,500 بوصة في الثانية.
إبقاء الكود كما هو مع التحويل إلى البوصة في النهاية. فالبوصة الواحدة تساوي 2.54 سنتيمتر. وشخصياً هذه هي الطريقة التي سأتّبعها، لأنها تتيح لي عرض النتائج بالنظامَين الإمبراطوري والمتري معاً.
وإلّا فاكتفِ باستخدام النظام المتري، فهو مستخدَمٌ في جميع أنحاء العالم، والأهمّ من ذلك أنه استُخدِم في مسلسل "ستار تريك: الجيل التالي". فإذا كان مناسباً للكابتن بيكارد، فهو مناسبٌ لي!
ولننتقل الآن إلى الكود. هذا هو الكود الأساسي لمستشعر HC-SR04، وللحصول على شرحٍ تفصيلي لكيفية عمله، شاهد الفيديو أو.
/* HC-SR04 Basic Demonstration HC-SR04-Basic-Demo.ino Demonstrates functions of HC-SR04 Ultrasonic Range Finder Displays results on Serial Monitor
DroneBot Workshop 2017 */
// This uses Serial Monitor to display Range Finder distance readings
// Hook up HC-SR04 with Trig to Arduino Pin 10, Echo to Arduino pin 13
#define trigPin 10 #define echoPin 13
float duration, distance;
void setup() { Serial.begin (9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); }
void loop() {
// Write a pulse to the HC-SR04 Trigger Pin
digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);
// Measure the response from the HC-SR04 Echo Pin duration = pulseIn(echoPin, HIGH);
// Determine distance from duration // Use 343 metres per second as speed of sound
distance = (duration / 2) * 0.0343;
// Send results to Serial Monitor
Serial.print("Distance = "); if (distance >= 400 || distance <= 2) { Serial.println("Out of range"); } else { Serial.print(distance); Serial.println(" cm"); delay(500); } delay(500); } |
مكتبات الكود في الأردوينو
في الكود الأول لم نستخدم أي مكتبات، بل اكتفينا باستخدام أمر delayMicroseconds في الأردوينو لتوليد نبضة الـ10 ميكروثانية اللازمة للتشغيل، وأمر pulseIn لقياس عرض نبضة الإشارة المستقبَلة. لكن هناك طرقاً أخرى للقيام بذلك باستخدام مكتباتٍ برمجية خاصة. ويتوفّر عددٌ لا بأس به منها، وأكثرها مرونةً واحدةٌ تُسمّى "NewPing".
إذا لم تكن لديك أي خبرة في استخدام المكتبات في أكواد الأردوينو، فهذه مهارةٌ تحتاج فعلاً إلى تعلّمها. توفّر المكتبات دوالّ برمجية لمهامّ محدّدة، وهناك حرفياً مئات المكتبات المتاحة للأردوينو لأداء المهامّ ولدعم مختلف أنواع العتاد الخارجي.
يحتوي موقع الأردوينو على تعليمات لتثبيت المكتبات الجديدة في بيئة الأردوينو (IDE).
كتب مكتبة NewPing تيم إيكل (Tim Eckel)، وهي تحلّ محلّ مكتبة Ping الأقدم التي كتبها كاليب زولاوسكي (Caleb Zulawski) وصُمّمت أساساً لمستشعر Parallax Ping فوق الصوتي (رغم أنها تعمل مع HC-SR04 إذا استُخدمت في وضع الثلاثة أطراف).
مكتبة NewPing متقدّمة إلى حدٍّ كبير، وهي تُحسّن دقّة الكود الأصلي بشكلٍ ملحوظ. كما تدعم ما يصل إلى 15 مستشعراً فوق صوتياً في آنٍ واحد، ويمكنها إخراج النتائج مباشرةً بالسنتيمتر أو البوصة أو بوحدة الزمن.
وفيما يلي الكود بعد إعادة كتابته لاستخدام مكتبة :
/* HC-SR04 NewPing Library Demonstration HC-SR04-NewPing.ino Demonstrates functions of NewPing Library for HC-SR04 Ultrasonic Range Finder Displays results on Serial Monitor
DroneBot Workshop 2017 */
// This uses Serial Monitor to display Range Finder distance readings
// Include NewPing Library #include "NewPing.h"
// Hook up HC-SR04 with Trig to Arduino Pin 10, Echo to Arduino pin 13 // Maximum Distance is 400 cm
#define TRIGGER_PIN 10 #define ECHO_PIN 13 #define MAX_DISTANCE 400 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
float distance;
void setup() { Serial.begin (9600); }
void loop() {
distance = sonar.ping_cm();
// Send results to Serial Monitor Serial.print("Distance = "); if (distance >= 400 || distance <= 2) { Serial.println("Out of range"); } else { Serial.print(distance); Serial.println(" cm"); delay(500); } delay(500); } |
الكود أعلاه بسيطٌ ويعمل جيداً، لكن دقّته لا تتجاوز السنتيمتر الواحد. وإذا أردت استعادة القيم العشرية (بعد الفاصلة)، فيمكنك استخدام NewPing في وضع المدّة الزمنية (duration) بدلاً من وضع المسافة (distance). عندئذٍ يمكننا استخدام المدّة الزمنية لحساب المسافة كما فعلنا في الكود الأول الذي اطّلعنا عليه.
وفيما يلي كود NewPing بعد إعادة كتابته لاستخدام المدّة الزمنية بدلاً من المسافة.
/* HC-SR04 NewPing Duration Demonstration HC-SR04-NewPing-Duration.ino Demonstrates using Duration function of NewPing Library for HC-SR04 Ultrasonic Range Finder Displays results on Serial Monitor
DroneBot Workshop 2017 */
// This uses Serial Monitor to display Range Finder distance readings
// Include NewPing Library #include "NewPing.h"
// Hook up HC-SR04 with Trig to Arduino Pin 10, Echo to Arduino pin 13 // Maximum Distance is 400 cm
#define TRIGGER_PIN 10 #define ECHO_PIN 13 #define MAX_DISTANCE 400 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
float duration, distance;
void setup() { Serial.begin (9600); }
void loop() {
duration = sonar.ping();
// Determine distance from duration // Use 343 metres per second as speed of sound
distance = (duration / 2) * 0.0343;
// Send results to Serial Monitor Serial.print("Distance = "); if (distance >= 400 || distance <= 2) { Serial.println("Out of range"); } else { Serial.print(distance); Serial.println(" cm"); delay(500); } delay(500); } |
من وظائف مكتبة NewPing الأخرى وظيفة "التكرارات" (iterations). والتكرار يعني المرور على شيءٍ ما أكثر من مرة، وهذا بالضبط ما يفعله وضع التكرار. فهو يأخذ عدّة قياساتٍ للمدّة الزمنية بدلاً من قياسٍ واحد، ويتجاهل أي قراءاتٍ غير صالحة، ثم يحسب متوسّط القراءات المتبقّية. وهو يأخذ 5 قراءاتٍ بشكلٍ افتراضي، لكن يمكنك في الواقع تحديد أي عددٍ تشاء.
وها نحن مرةً أخرى مع كود NewPing مكتوبٍ لاستخدام التكرارات. وكما ترى، فهو مطابقٌ تقريباً للكود السابق، وكلّ ما أُضيف إليه هو متغيّرٌ لتحديد عدد التكرارات..
/* HC-SR04 NewPing Iteration Demonstration HC-SR04-NewPing-Iteration.ino Demonstrates using Iteration function of NewPing Library for HC-SR04 Ultrasonic Range Finder Displays results on Serial Monitor
DroneBot Workshop 2017 */
// This uses Serial Monitor to display Range Finder distance readings
// Include NewPing Library #include "NewPing.h"
// Hook up HC-SR04 with Trig to Arduino Pin 10, Echo to Arduino pin 13 // Maximum Distance is 400 cm
#define TRIGGER_PIN 10 #define ECHO_PIN 13 #define MAX_DISTANCE 400 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
float duration, distance;
int iterations = 5;
void setup() { Serial.begin (9600); }
void loop() {
duration = sonar.ping_median(iterations);
// Determine distance from duration // Use 343 metres per second as speed of sound
distance = (duration / 2) * 0.0343;
// Send results to Serial Monitor Serial.print("Distance = "); if (distance >= 400 || distance <= 2) { Serial.println("Out of range"); } else { Serial.print(distance); Serial.println(" cm"); delay(500); } delay(500); } |