Menu
CoddyTech

Saat millis() Berputar Kembali

Termasuk bagian Pengaturan Waktu Tanpa Delay dalam perjalanan Arduino di Coddy. Pelajaran 17 dari 18.

unsigned long berhenti pada 4,294,967,295. Setelah sekitar 49.7 hari, millis() mencapainya lalu mulai lagi dari 0. Ini disebut berputar ulang.

Tipe yang lebih kecil menunjukkan hal yang sama. unsigned int berhenti pada 65535:

unsigned int a = 65530;
a = a + 10;   // 65540 tidak muat: a sekarang bernilai 4

Pengurangan berputar dengan cara yang sama, dan itu membuatnya aman: jam yang dimulai dari 65530 dan kini menunjukkan 4 telah menghitung 10 langkah, dan 4 dikurangi 65530, yang disimpan dalam unsigned int, hasilnya tepat 10. Dengan cara yang sama, millis() - start selalu menunjukkan waktu sejak start, bahkan saat melewati putaran ulang.

Penjumlahan tidak aman. Dalam now >= start + interval, hasil penjumlahan dapat melewati batas atas dan berputar ke angka kecil, sehingga timer langsung selesai. Dan ketika now sudah berputar ulang tetapi hasil penjumlahannya belum, timer tidak pernah selesai. Selalu gunakan pengurangan:

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

Tantangan

Sedang

Tidak ada yang bisa menunggu 49 hari untuk sebuah pengujian, jadi sketch ini memberikan nilai waktu yang mendekati saat rollover kepada isDone() dan mencetak jawabannya. Hasilnya menyatakan "done" terlalu cepat dan "waiting" selamanya. Perbaiki satu baris di isDone() agar fungsi itu membandingkan waktu yang berlalu sejak start dengan interval.

Tekan Run, baca keempat jawabannya, perbaiki baris tersebut, lalu tekan Check.

Coba sendiri

const unsigned long interval = 2000;

// Apakah timer yang dimulai pada start sudah selesai pada waktu now?
bool isDone(unsigned long start, unsigned long now) {
  return now >= start + interval;   // perbaiki baris ini
}

// Menampilkan waktu yang telah berlalu dan hasil dari 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() berhenti di 4294967295, lalu mulai lagi dari 0
  test(4294966000, 4294966500);   // tepat sebelum kembali ke 0
  test(4294966000, 4294967200);   // masih sebelum kembali ke 0
  test(4294966000, 900);          // jam sudah melewati 0
  test(4294964000, 500);          // timer yang dimulai lebih awal
}

void loop() {
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pengaturan Waktu Tanpa Delay

Latihan sendiri: Playground Arduino