3.2. Định thời¶
Mô-đun time nhóm các hàm dùng để ngủ (tạm dừng tập lệnh trong một khoảng thời gian xác định) và đo thời gian thực hiện của một đoạn code. Trên vi điều khiển, đây không phải là tính năng tùy chọn; chúng là cách tập lệnh điều phối các tương tác với thế giới bên ngoài -- bao lâu để giữ một chân (pin) ở mức cao, bao lâu chờ giữa các lần lấy mẫu, bao lâu kể từ lần nhấn nút cuối cùng.
3.2.1. Ngủ¶
Ba hàm ngủ chặn tập lệnh trong khoảng thời gian yêu cầu:
time.sleep(s)-- tạm dừng trongsgiây. Chấp nhận số thực, vì vậytime.sleep(0.5)chờ nửa giây.time.sleep_ms(ms)-- tạm dừng trongmsmili giây. Đối số phải là số nguyên.time.sleep_us(us)-- tạm dừng trongusmicro giây.
import time
print("now")
time.sleep_ms(500)
print("half a second later")
Sử dụng time.sleep_ms() cho các nhu cầu "chờ một chút" thông thường và time.sleep_us() chỉ khi định thời phải chính xác. time.sleep() thông thường cũng được, nhưng các biến thể đối số nguyên tránh chuyển đổi dấu phẩy động và đọc tự nhiên hơn cho các khoảng thời gian ngắn.
Ngủ là lệnh gọi chặn. Trong khi tập lệnh đang ngủ, nó không làm gì khác -- không đọc chân (pin), không phục vụ UART, không cập nhật LED. Dùng sleep khi chặn là điều bạn muốn; dùng mẫu không chặn bên dưới khi không muốn.
3.2.2. Đọc đồng hồ¶
Để đo thời gian một đoạn code mất bao lâu, đọc đồng hồ trước và sau:
time.ticks_ms()-- giá trị tick hiện tại tính bằng mili giây.time.ticks_us()-- giá trị tương tự tính bằng micro giây.
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")
Điều này thường hoạt động đúng. Bộ đếm tick quay vòng (trở về không) sau một số lượng tick lớn nhưng hữu hạn, và phép trừ đơn giản qua điểm quay vòng đó tạo ra một số âm hoặc dương sai hoàn toàn.
Bộ đếm tick quay trở lại không khi đạt đến giới hạn số nguyên. Phép trừ đơn giản qua điểm quay vòng đó là sai.¶
3.2.3. ticks_diff¶
Để lấy các tick đã trôi qua chính xác, ngay cả qua điểm quay vòng, hãy sử dụng time.ticks_diff():
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")
Thứ tự đối số là ticks_diff(later, earlier) -- biểu thức đọc là "later cách earlier bao xa". Kết quả là một số nguyên có dấu; dương có nghĩa là later thực sự là sau, âm có nghĩa là nó ở trong quá khứ. Hàm xử lý quay vòng nội bộ.
Mẹo
Luôn ghép time.ticks_ms() / time.ticks_us() với time.ticks_diff(). Phép trừ thô là đúng hầu hết thời gian; thời điểm nó sai là khi tập lệnh đã chạy trong thời gian dài -- thường là thời điểm tồi tệ nhất để gỡ lỗi sự cố định thời.
3.2.4. Định thời không chặn¶
Một tập lệnh vi điều khiển thường có nhiều thứ phải làm "cùng một lúc": đọc nút nhấn, nhấp nháy LED, thăm dò cảm biến, phục vụ UART. sleep không phù hợp cho điều đó -- trong khi một sleep đang chạy, các tác vụ khác bị dừng lại.
Mẫu chuẩn là giữ một thời hạn cho mỗi tác vụ và kiểm tra mỗi vòng lặp xem thời hạn đã qua chưa. Quyết định hành động được xây dựng trên time.ticks_diff(), không bao giờ dựa trên 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 chuyển đổi mỗi 500 ms, cảm biến được thăm dò mỗi 100 ms và không tác vụ nào chặn tác vụ kia. time.ticks_add() tăng thời hạn thêm một lượng tăng đã biết mà không mắc phải vấn đề quay vòng.
Cấu trúc này -- một vòng lặp đơn, nhiều tác vụ có định thời, không có sleep trong thân -- xuất hiện ở khắp nơi trong code phần cứng: khử rung phần mềm cho công tắc, điều phối động cơ, thời gian chờ đọc UART. Ba hàm tương tự (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) bao phủ mọi trường hợp.