3.17. تيارات البتات وقياس النبضات

تحتاج بعض الأجهزة إلى أنماط نبضات موقوتة بدقة بدلًا من إشارة PWM بتردد ثابت. فمصباح WS2812 RGB LED يرمّز كل بت كنبضة بعرض محدد؛ ومقياس المدى فوق الصوتي HC-SR04 يجيب بنبضة صدى يكون عرضها هو زمن الرحلة ذهابًا وإيابًا؛ وجهاز تحكم عن بُعد بالأشعة تحت الحمراء يرسل ترويسة تتبعها بتات بيانات على هيئة تسلسلات تشغيل-إيقاف.

تملك وحدة machine دالتين لهذا النوع من دخل/خرج GPIO الدقيق التوقيت:

  • bitstream() ترسل سلسلة نبضات بتوقيت منفصل لبتات 0 و 1.

  • time_pulse_us() تقيس عرض نبضة واردة بالميكروثانية.

3.17.1. إرسال تيار بتات

تأخذ machine.bitstream() دبوسًا، وترميزًا، ومواصفات توقيت، والبايتات المراد إرسالها. أكثر الترميزات شيوعًا (0) هو تعديل عرض النبضة من نوع مرتفع-منخفض: كل بت هو نبضة مرتفعة بعرض معين تتبعها نبضة منخفضة بعرض آخر، مع توقيتات مميزة لبتات 0 و 1.

Two stacked waveforms. The top one shows a 0 bit: a brief high pulse (high_0) followed by a longer low period (low_0). The bottom one shows a 1 bit: a longer high pulse (high_1) followed by a shorter low period (low_1).

ترميز عرض النبضة مرتفع-منخفض: يتكون كل من 0 و 1 من طور مرتفع يتبعه طور منخفض، بعرضين مميزين.

المثال النموذجي هو مصباح WS2812 (NeoPixel) RGB LED، الذي يتوقع البتات عند 800 kHz بهذه التوقيتات:

  • 0: 400 ns مرتفع، ثم 850 ns منخفض.

  • 1: 800 ns مرتفع، ثم 450 ns منخفض.

from machine import Pin, bitstream

pin = Pin("P7", Pin.OUT)

# (high_0, low_0, high_1, low_1) in nanoseconds
timing = (400, 850, 800, 450)

# one LED: GRB order, three bytes per LED (red shown here)
bitstream(pin, 0, timing, b"\x00\xff\x00")

تولّد وحدة المعالجة الدقيقة (MCU) النبضات بطريقة bit-bang بالعروض المطلوبة؛ وعلى الكاميرات السريعة بما يكفي يكون التوقيت دقيقًا في حدود عشرات النانوثواني.

تحذير

تُعطّل bitstream() جميع المقاطعات طوال مدة الإرسال بأكمله لتحتفظ بتحكم دقيق في توقيت النبضات. وتتناسب مدة الاستدعاء خطيًا مع عدد البايتات -- فبتوقيت WS2812 (نحو 10 µs لكل بايت)، يُوقف إرسال 100 بايت وحدة المعالجة المركزية لنحو 1 ms، و1000 بايت لمدة 10 ms، و10000 بايت لمدة 100 ms كاملة. وأي شيء يتجاوز بضع مئات من البايتات لكل استدعاء يخاطر بحالات تجمّد ملحوظة -- جزّئ التحديثات الطويلة إلى قطع أصغر، بحيث يعود الاستدعاء بين كل قطعة وأخرى ليتمكن بقية البرنامج النصي من العمل.

ملاحظة

ولتشغيل شرائط WS2812 / NeoPixel على وجه الخصوص، تغلّف وحدة neopixel الدالة bitstream() ضمن واجهة أعلى مستوى تتولى ترتيب اللون وتحديثات الشريط بالجملة. والجأ إلى bitstream() مباشرة عندما لا يكون البروتوكول WS2812 لكنه لا يزال يلائم شكل تعديل عرض النبضة مرتفع-منخفض.

3.17.2. قياس نبضة واردة

تقيس machine.time_pulse_us() عرض نبضة واحدة على دبوس. تنتظر حتى يبلغ الخط المستوى المحدد (بداية النبضة)، ثم تقيس المدة التي يبقى فيها الخط عند ذلك المستوى (نهاية النبضة)، وتُعيد المدة بالميكروثانية.

الاستخدام الكلاسيكي هو مستشعر المسافة فوق الصوتي HC-SR04. ترسل الكاميرا نبضة تحفيز مدتها 10 µs، ثم تنتظر أن يُعيد دبوس الصدى نبضة يكون عرضها هو زمن ذهاب الصوت وإيابه:

import time
from machine import Pin, time_pulse_us

trigger = Pin("P7", Pin.OUT, value=0)
echo    = Pin("P8", Pin.IN)

while True:
    trigger.value(1)
    time.sleep_us(10)
    trigger.value(0)

    width = time_pulse_us(echo, 1, timeout_us=30_000)
    if width > 0:
        # sound at ~343 m/s; round trip / 2 / 343 = distance (m)
        distance_cm = (width * 343) / 2 / 10_000
        print(distance_cm, "cm")

    time.sleep_ms(100)

الوسيط الثالث هو المهلة بالميكروثانية، وتُطبَّق منفصلة على "انتظار بدء النبضة" و"انتظار انتهاء النبضة". وعند انقضاء المهلة تُعيد الدالة قيمة سالبة تحدد الطور الذي أخفق: -2 إذا لم تبدأ النبضة أبدًا، و -1 إذا بدأت لكنها لم تنتهِ أبدًا ضمن النافذة.

كلا نصفي المهلة مهمان للمستشعرات الحقيقية. فمستشعر HC-SR04 قد يستغرق من واحد إلى اثنين ميلي ثانية لبدء صداه، وقد يكون الصدى نفسه بطول عشرات الميلي ثواني للأجسام البعيدة. وضبط حجم timeout_us على أقصى مدى مطلوب يُبقي القياس محدودًا.