3.2. التوقيت¶
تجمع وحدة time معاً دوال للنوم (إيقاف البرنامج النصي مؤقتاً لمدة معروفة) ولقياس المدة التي يستغرقها شيء ما. على المتحكم الدقيق ليست هذه أموراً اختيارية للراحة؛ بل هي الطريقة التي يضبط بها البرنامج النصي إيقاع التفاعلات مع العالم الخارجي -- كم من الوقت يبقي دبوساً مرتفعاً، وكم من الوقت ينتظر بين العينات، وكم مضى منذ آخر ضغط على زر.
3.2.1. النوم¶
تحجب ثلاث دوال نوم البرنامج النصي للمدة المطلوبة:
time.sleep(s)-- توقّف لمدةsثانية. تقبل عدداً عشرياً، لذا تنتظرtime.sleep(0.5)نصف ثانية.time.sleep_ms(ms)-- توقّف لمدةmsمللي ثانية. يجب أن يكون الوسيط عدداً صحيحاً.time.sleep_us(us)-- توقّف لمدةusميكروثانية.
import time
print("now")
time.sleep_ms(500)
print("half a second later")
استخدم time.sleep_ms() للاحتياجات المعتادة من نوع "انتظر قليلاً"، واستخدم time.sleep_us() فقط عندما يجب أن يكون التوقيت محكماً. الدالة العادية time.sleep() جيدة أيضاً، لكن المتغيرات ذات الوسيط الصحيح تتجنب تحويل الفاصلة العائمة وتُقرأ بشكل أكثر طبيعية للفترات القصيرة.
النوم استدعاء حاجب. أثناء نوم البرنامج النصي، لا يفعل أي شيء آخر -- لا يقرأ دبوساً، ولا يخدم UART، ولا يحدّث LED. اللجوء إلى sleep عندما يكون الحجب هو ما تريده؛ واستخدم النمط غير الحاجب أدناه عندما لا يكون كذلك.
3.2.2. قراءة الساعة¶
لقياس المدة التي تستغرقها قطعة من الشيفرة، اقرأ الساعة قبلها وبعدها:
time.ticks_ms()-- قيمة النبضة الحالية بالمللي ثانية.time.ticks_us()-- نفسها بالميكروثانية.
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")
يعمل هذا في معظم الأوقات. يلتف عدّاد النبضات (يعود إلى الصفر) بعد عدد كبير لكنه محدود من النبضات، والطرح الساذج عبر ذلك الالتفاف يُنتج رقماً سالباً أو موجباً خاطئاً بشكل جامح.
يلتف عدّاد النبضات عائداً إلى الصفر عندما يبلغ الحد الأقصى للعدد الصحيح. الطرح البسيط عبر ذلك الالتفاف خاطئ.¶
3.2.3. ticks_diff¶
للحصول على النبضات المنقضية بشكل صحيح، حتى عبر الالتفاف، استخدم time.ticks_diff():
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")
ترتيب الوسائط هو ticks_diff(later, earlier) -- ويُقرأ التعبير "كم يبعد later بعد earlier". النتيجة عدد صحيح بإشارة؛ الموجب يعني أن later هو فعلاً لاحق، والسالب يعني أنه في الماضي. تعالج الدالة الالتفاف داخلياً.
نصيحة
اقرن دائماً time.ticks_ms() / time.ticks_us() مع time.ticks_diff(). الطرح الخام صحيح في معظم الأوقات؛ والوقت الذي يكون فيه خاطئاً هو عندما يكون البرنامج النصي قيد التشغيل لمدة طويلة -- وهو عادةً أسوأ وقت لتصحيح خلل في التوقيت.
3.2.4. التوقيت غير الحاجب¶
عادةً ما يكون لدى برنامج المتحكم الدقيق أكثر من شيء يقوم به "في الوقت نفسه": قراءة زر، وإيماض LED، واستطلاع مستشعر، وخدمة UART. الدالة sleep غير صالحة لذلك -- فبينما تعمل إحدى دوال sleep، تتوقف المهام الأخرى.
النمط القياسي هو الاحتفاظ بـ موعد نهائي لكل مهمة، والتحقق في كل حلقة مما إذا كان الموعد النهائي قد انقضى. ويُبنى قرار التصرف على time.ticks_diff()، وليس أبداً على sleep:
import time
next_blink = time.ticks_ms()
next_poll = time.ticks_ms()
state = False
while True:
now = time.ticks_ms()
if time.ticks_diff(now, next_blink) >= 0:
state = not state
# update LED here
next_blink = time.ticks_add(next_blink, 500)
if time.ticks_diff(now, next_poll) >= 0:
# read sensor here
next_poll = time.ticks_add(next_poll, 100)
يتبدّل LED كل 500 مللي ثانية، ويُستطلع المستشعر كل 100 مللي ثانية، ولا تحجب أي من المهمتين الأخرى. تقدّم time.ticks_add() موعداً نهائياً بمقدار معلوم دون الوقوع في فخ الالتفاف.
هذا الشكل -- حلقة واحدة، وعدة مهام موقّتة، ودون sleep في المتن -- يظهر في كل مكان تذهب إليه شيفرة الأجهزة: إزالة الارتداد البرمجية للمفاتيح، وتتابع المحركات، ومهلات قراءة UART. تغطي الدوال الثلاث نفسها (time.ticks_ms()، time.ticks_diff()، time.ticks_add()) كل حالة.