Có một điều quan trọng mà bạn cần nhớ khi làm việc với thời gian trên Arudino dưới mọi hình thức:
- Mọi hoạt động đều cần có thời gian.
Hàm foo () của bạn sẽ mất một khoảng thời gian. Thời gian đó là gì, chúng ta không thể nói.
Cách đáng tin cậy nhất để đối phó với thời gian là chỉ dựa vào thời gian để kích hoạt, chứ không phải làm việc khi cần kích hoạt tiếp theo.
Ví dụ, lấy như sau:
if (millis() - last > interval) {
doSomething();
last = millis();
}
Biến last
sẽ là thời gian quy trình được kích hoạt * cộng với thời gian doSomething
cần để chạy. Vì vậy, giả sử interval
là 100 và doSomething
mất 10ms để chạy, bạn sẽ nhận được kích hoạt ở 101ms, 212ms, 323ms, v.v. Không phải 100ms bạn mong đợi.
Vì vậy, một điều bạn có thể làm là luôn luôn sử dụng cùng một lúc bất kể bằng cách nhớ nó tại một thời điểm cụ thể (như Juraj gợi ý):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Bây giờ thời gian đó doSomething()
sẽ không có hiệu lực trên bất cứ điều gì. Vì vậy, bạn sẽ nhận được kích hoạt ở 101ms, 202ms, 303ms, v.v. Vẫn không hoàn toàn 100ms bạn muốn - bởi vì bạn đang tìm kiếm thêm 100ms đã qua - và điều đó có nghĩa là 101ms trở lên. Thay vào đó bạn nên sử dụng >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Bây giờ, giả sử rằng không có gì khác xảy ra trong vòng lặp của bạn, bạn sẽ có các kích hoạt ở 100ms, 200ms, 300ms, v.v. Nhưng lưu ý rằng bit: "miễn là không có gì khác xảy ra trong vòng lặp của bạn" ...
Điều gì xảy ra nếu một hoạt động mất 5ms xảy ra ở 99ms ...? Kích hoạt tiếp theo của bạn sẽ bị trì hoãn cho đến 104ms. Đó là một sự trôi dạt. Nhưng nó dễ chiến đấu. Thay vì nói "Thời gian đã ghi là bây giờ", bạn nói "Thời gian ghi được trễ hơn 100ms so với trước đây". Điều đó có nghĩa là bất kể sự chậm trễ nào bạn nhận được trong mã của mình, kích hoạt của bạn sẽ luôn ở các khoảng 100ms hoặc trôi trong tích tắc 100ms.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Bây giờ bạn sẽ nhận được kích hoạt ở 100ms, 200ms, 300ms, v.v. Hoặc nếu có sự chậm trễ trong các bit mã khác, bạn có thể nhận được 100ms, 204ms, 300ms, 408ms, 503ms, 600ms, v.v. Nó luôn cố gắng chạy gần khoảng thời gian có thể bất kể sự chậm trễ. Và nếu bạn có độ trễ lớn hơn khoảng thời gian, nó sẽ tự động chạy thói quen của bạn đủ thời gian để bắt kịp với thời gian hiện tại.
Trước khi bạn đã trôi dạt . Bây giờ bạn có jitter .