Menu
CoddyTech
flag Ar iconالعربيةdown icon

عندما تلتف قيمة millis()

جزء من قسم التوقيت دون delay في رحلة Arduino على Coddy. الدرس 17 من 18.

يتوقف unsigned long عند 4,294,967,295. بعد نحو 49.7 يومًا، تصل إليه millis() وتبدأ من جديد عند 0. يُسمّى هذا الالتفاف.

يوضح نوع أصغر الأمر نفسه. يتوقف unsigned int عند 65535:

unsigned int a = 65530;
a = a + 10;   // 65540 لا يمكن تمثيله: قيمة a الآن 4

يلتف الطرح بالطريقة نفسها، وهذا ما يجعله آمنًا: فالساعة التي بدأت عند 65530 وتقرأ الآن 4 تكون قد عدّت 10 خطوات، و4 ناقص 65530، عند تخزين الناتج في unsigned int، يساوي 10 تمامًا. وبالطريقة نفسها، تكون millis() - start دائمًا هي المدة المنقضية منذ start، حتى عند حدوث التفاف.

أما الجمع فليس آمنًا. في now >= start + interval، قد يتجاوز المجموع الحد الأعلى ويلتف إلى رقم صغير، فينتهي المؤقت فورًا. وإذا التفّت قيمة now ولم يلتف المجموع بعد، فلن ينتهي المؤقت أبدًا. اطرح دائمًا:

if (now - start >= interval) {
  // تم
}
challenge icon

التحدي

متوسط

لا أحد يستطيع الانتظار 49 يومًا لإجراء اختبار، لذا يمرّر هذا البرنامج إلى isDone() أوقاتًا قريبة من الالتفاف ويطبع إجاباتها. فهو يقول "done" مبكرًا جدًا و"waiting" إلى الأبد. أصلح السطر في isDone() بحيث يقارن الوقت المنقضي منذ start مع interval.

اضغط على تشغيل، واقرأ الإجابات الأربع، وأصلح السطر، ثم اضغط على تحقّق.

جرّب بنفسك

const unsigned long interval = 2000;

// هل انتهى المؤقّت الذي بدأ عند start بحلول الوقت now؟
bool isDone(unsigned long start, unsigned long now) {
  return now >= start + interval;   // أصلح هذا السطر
}

// يطبع المدة المنقضية وما تُرجعه isDone().
void test(unsigned long start, unsigned long now) {
  Serial.print(now - start);
  Serial.print(" ms: ");
  if (isDone(start, now)) {
    Serial.println("done");
  } else {
    Serial.println("waiting");
  }
}

void setup() {
  Serial.begin(9600);
  // تتوقف millis() عند 4294967295، ثم تبدأ مجددًا من 0
  test(4294966000, 4294966500);   // قبل الالتفاف مباشرةً
  test(4294966000, 4294967200);   // لا يزال قبل الالتفاف
  test(4294966000, 900);          // تجاوزت الساعة 0
  test(4294964000, 500);          // مؤقّت بدأ في وقت أسبق
}

void loop() {
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس التوقيت دون delay

تدرّب بنفسك: Playground لـ Arduino