Ada satu hal penting yang perlu Anda ingat ketika bekerja dengan waktu pada Arudino dalam bentuk apa pun:
- Setiap operasi membutuhkan waktu.
Fungsi foo () Anda akan membutuhkan waktu. Apa waktu itu, kita tidak bisa mengatakan.
Cara yang paling dapat diandalkan untuk menangani waktu adalah dengan hanya mengandalkan waktu untuk memicu, bukan untuk berolahraga ketika pemicu berikutnya seharusnya.
Misalnya, ambil yang berikut ini:
if (millis() - last > interval) {
doSomething();
last = millis();
}
Variabelnya last
adalah waktu yang dipicu oleh rutin * ditambah waktu yang doSomething
diperlukan untuk menjalankan. Jadi katakanlah interval
100, dan doSomething
butuh 10ms untuk dijalankan, Anda akan mendapatkan pemicu pada 101ms, 212ms, 323ms, dll. Bukan 100ms yang Anda harapkan.
Jadi satu hal yang dapat Anda lakukan adalah selalu menggunakan waktu yang sama tanpa menghiraukannya pada saat yang sama (seperti yang Juraj sarankan):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Sekarang waktu yang doSomething()
diperlukan tidak akan berpengaruh apa pun. Jadi Anda akan mendapatkan pemicu pada 101ms, 202ms, 303ms, dll. Masih tidak cukup 100ms yang Anda inginkan - karena Anda mencari lebih dari 100ms yang telah berlalu - dan itu berarti 101ms atau lebih. Sebaliknya, Anda harus menggunakan >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Sekarang, dengan asumsi bahwa tidak ada hal lain yang terjadi di loop Anda, Anda mendapatkan pemicu pada 100ms, 200ms, 300ms, dll. Tetapi perhatikan bahwa bit: "selama tidak ada yang lain terjadi di loop Anda" ...
Apa yang terjadi jika operasi yang membutuhkan waktu 5 ms terjadi pada 99ms ...? Pemicuan Anda berikutnya akan ditunda hingga 104 ms. Itu sebuah penyimpangan. Tapi mudah untuk bertarung. Alih-alih mengatakan "Waktu yang direkam sekarang" Anda mengatakan "Waktu yang direkam 100ms lebih lambat dari itu". Itu berarti bahwa tidak peduli apa pun keterlambatan yang Anda dapatkan dalam kode Anda, pemicu Anda akan selalu berada pada interval 100 ms, atau melayang dalam centang 100 ms.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Sekarang Anda akan mendapatkan pemicu pada 100ms, 200ms, 300ms, dll. Atau jika ada keterlambatan dalam bit kode lain Anda mungkin mendapatkan 100ms, 204ms, 300ms, 408ms, 503ms, 600ms, dll. Selalu mencoba untuk menjalankannya sedekat mungkin dengan Interval mungkin terlepas dari penundaan. Dan jika Anda memiliki penundaan yang lebih besar dari interval itu, maka secara otomatis akan menjalankan rutinitas Anda cukup untuk mengejar waktu saat ini.
Sebelum Anda tertidur . Sekarang Anda memiliki jitter .