Bài 5 · Toán · Vật lí · Tin học
Đồng hồ đếm thời gian
vì sao đồng hồ tự làm luôn chạy sai, và sai bao nhiêu
Bài duy nhất trong cả cấp độ mà sản phẩm làm ra chắc chắn có lỗi. Đó là chủ ý: học sinh phải tự đo được lỗi ấy, tìm ra nguyên nhân, rồi tự sửa.
01 Mục tiêu và yêu cầu cần đạt
Bốn bài trước, sản phẩm chạy đúng là xong. Bài này khác: chương trình sẽ chạy gần đúng, và phần thú vị nằm ở chữ "gần". Học sinh sẽ đo được sai lệch, chỉ ra nguyên nhân, ước lượng độ lớn của nó, rồi sửa. Đó là toàn bộ chu trình làm việc của một người đo đạc.
Sau bài này học sinh làm được
- Làm được một đồng hồ đếm giây và đặt lại về 0 bằng nút nhấn.
- Đo được sai lệch tích luỹ so với đồng hồ chuẩn.
- Giải thích vì sao đồng hồ đếm bằng
sleepluôn chạy chậm. - Ước lượng thời gian các lệnh khác chiếm trong mỗi vòng lặp.
- Dùng
ticks_ms()để làm đồng hồ không tích luỹ sai lệch.
- Toán 10 — sai số tuyệt đối, sai số tương đối, sai số tích luỹ.
- Vật lí 10 — phép đo thời gian, dụng cụ đo và sai số dụng cụ.
- Tin học 10 — biến, vòng lặp, và chi phí thời gian của câu lệnh.
Trích nguyên văn yêu cầu cần đạt từ Phụ lục Thông tư 32/2018 trước khi đưa vào kế hoạch bài dạy.
02 Lí thuyết
Cách nghĩ đầu tiên ai cũng nghĩ ra
Chờ một giây rồi cộng một, lặp lại. Hợp lí, và đó là chương trình ở Bước 0.
Chỗ ít ai nghĩ tới: ngoài lệnh chờ, mỗi vòng còn phải chạy những lệnh
khác — cộng biến, gọi print, đọc nút, nháy đèn. Mỗi việc
tốn một chút thời gian.
Sai lệch tích luỹ
Gọi thời gian các lệnh khác là t. Mỗi vòng thực tế dài 1000 + t ms. Sau n vòng, đồng hồ chỉ n giây trong khi thời gian thật đã trôi n × (1000 + t) ms.
Đáng sợ ở chỗ nó cộng dồn: t chỉ 3 ms thì sau 1000 giây đồng hồ đã chậm 3 giây, sau một giờ chậm ~11 giây.
Bù trừ: đo được t ≈ 3 ms thì chờ 997 ms. Hiệu quả
ngay nhưng mong manh — thêm một dòng print là lại sai.
Dựa mốc: không đếm số vòng, mà hỏi thẳng đồng hồ nội của chip đã trôi bao nhiêu ms kể từ lúc khởi động. Sai lệch không tích luỹ vì mỗi lần đều tính lại từ mốc gốc.
Cách thứ hai là cách người ta dùng thật, và dạy một ý sâu hơn: đừng đo bằng cách cộng dồn các khoảng, hãy đo bằng hiệu của hai mốc.
ticks_ms và ticks_diff
time.ticks_ms() trả về số ms kể từ lúc bo khởi động. Con số này
chạy đến một mức rồi quay vòng về 0, nên phải lấy hiệu bằng
time.ticks_diff(sau, truoc) chứ không trừ trực tiếp —
ticks_diff xử lí đúng cả trường hợp quay vòng.
03 Linh kiện
| Linh kiện | Mô tả, lưu ý khi mua | Số lượng · giá |
|---|---|---|
| ESP32 DevKit V1 | Bo 30 chân, cổng micro-USB hoặc Type-C | 1 · 90–150k |
| Nút nhấn 4 chân | Dùng lại nút của Bài 2 và Bài 4 | 1 · 1k |
| LED 5 mm và điện trở 220 Ω | Nháy mỗi giây cho dễ theo dõi | 1 · 700đ |
| Đồng hồ bấm giờ | Điện thoại là đủ. Đây là dụng cụ đo chuẩn của bài | mỗi nhóm 1 |
04 Lắp mạch và sơ đồ nối dây
| Khối | Nối dây | Nguồn |
|---|---|---|
| Nút nhấn | GPIO4 → một chân nút · chân chéo góc → GND | Không cần nguồn riêng |
| LED | GPIO23 → điện trở 220 Ω → chân dài · chân ngắn → GND | Lấy từ chính chân GPIO |
Mạch giống Bài 4: ESP32, nút nhấn, LED và điện trở trên breadboard.
Điện thoại bấm giờ đặt cạnh màn hình máy tính đang in số giây, hai con số chênh nhau thấy rõ sau vài phút chạy. Đây là ảnh chứng minh sai lệch.
Khung giữ chỗ — thay bằng ảnh chụp thật khi cóSơ đồ một vòng lặp chia thành hai phần: phần sleep_ms đúng 1000 ms và phần các lệnh khác chiếm thêm vài mili giây, minh hoạ vì sao chu kì luôn dài hơn 1 giây.
Khung giữ chỗ — thay bằng ảnh chụp thật khi cóKhông có gì mới
Mạch của bài này giống hệt Bài 4. Nếu lớp vừa học Bài 4 xong thì không phải rút một sợi dây nào — chỉ đổi chương trình.
- Nút nhấn: một chân →
GPIO4, chân chéo góc →GND. - LED:
GPIO23→ điện trở 220 Ω → chân dài, chân ngắn →GND.
LED nháy mỗi giây không tham gia vào phép đếm. Nó chỉ giúp cả nhóm cùng theo dõi nhịp mà không phải chăm chăm nhìn màn hình. Nhưng nó có góp vào sai lệch, vì lệnh nháy đèn cũng tốn thời gian — và đó là một chi tiết hay để chỉ ra ở mục Hiệu chuẩn.
05 Mã nguồn
Toàn bộ mã trong bài chạy trên MicroPython 1.28 cho ESP32. Chép vào bo rồi đổi tên thành main.py là chạy mỗi lần cấp nguồn.
Bước 0 — đồng hồ ngây thơ, cố tình để nó lệch# ------------------------------------------------------------
# Bai 5 - Buoc 0: dong ho dem bang cach cho. Co tinh de no LECH.
# ------------------------------------------------------------
import time
so_giay = 0
while True:
time.sleep_ms(1000)
so_giay = so_giay + 1
print("So giay:", so_giay) Bốn dòng, không dùng linh kiện nào. Cho chạy song song với đồng hồ bấm giờ và để yên đó suốt cả tiết học. Đến cuối tiết, hai con số sẽ lệch nhau rõ rệt — và cả lớp sẽ có một câu hỏi thật sự để trả lời.
Chương trình chính — thêm nút đặt lại và đèn nháy# ------------------------------------------------------------
# Bai 5 - Dong ho dem thoi gian
# Phan cung: GPIO4 -> nut nhan -> GND
# GPIO23 -> dien tro 220 ohm -> LED -> GND
# ------------------------------------------------------------
from machine import Pin
import time
# ===== CẤU HÌNH =====
CHAN_NUT = 4
CHAN_LED = 23
NHIP = 1000 # ms - bao lau thi cong them mot giay
CHONG_DOI = 200 # ms
# ====================
nut = Pin(CHAN_NUT, Pin.IN, Pin.PULL_UP)
led = Pin(CHAN_LED, Pin.OUT)
so_giay = 0
truoc_do = False
while True:
time.sleep_ms(NHIP)
so_giay = so_giay + 1
print("So giay:", so_giay)
# nhay den mot cai moi giay cho de theo doi
led.on()
time.sleep_ms(30)
led.off()
# nhan nut thi dat lai ve 0
dang_nhan = nut.value() == 0
if dang_nhan and not truoc_do:
so_giay = 0
print("Da dat lai ve 0")
time.sleep_ms(CHONG_DOI)
truoc_do = dang_nhan Phần phát hiện sườn nhấn ở cuối là bản sao nguyên xi từ Bài 4. Đây là lần đầu học sinh dùng lại một kĩ thuật đã học ở bài trước, trong một hoàn cảnh hoàn toàn khác. Hãy chỉ rõ điều đó.
Chú ý bản này lệch nhiều hơn Bước 0, vì có thêm lệnh nháy đèn và lệnh đọc nút trong mỗi vòng. Đó không phải bước lùi — đó là số liệu cho mục Hiệu chuẩn.
Biến thể — đồng hồ dựa mốc, không tích luỹ sai lệch# Bien the: dong ho KHONG lech, dua vao dong ho noi cua chip
import time
# ticks_ms() dem so mili giay tu luc bo khoi dong
moc = time.ticks_ms()
da_bao = 0
while True:
troi_qua = time.ticks_diff(time.ticks_ms(), moc)
giay = troi_qua // 1000
if giay > da_bao:
da_bao = giay
print("So giay:", giay)
time.sleep_ms(10) Bản này không cộng dồn gì cả. Mỗi vòng nó hỏi lại "từ mốc gốc tới giờ trôi bao lâu rồi" và chia cho 1000. Dù các lệnh khác có tốn bao nhiêu thời gian, số giây in ra vẫn bám đúng đồng hồ thật.
Em mô tả bằng tiếng Việt, hệ thống dựng thuật toán và chương trình, rồi nạp thẳng xuống ESP32 qua Wi-Fi.
06 Hiệu chuẩn và kiểm thử
Phép đo chính của bài
- Nạp chương trình chính, bấm đồng hồ điện thoại cùng lúc bo khởi động.
- Để chạy đúng 5 phút theo đồng hồ điện thoại.
- Đọc số giây chương trình in ra ngay khoảnh khắc đó.
- Sai lệch = 300 − số máy đếm được.
| Chương trình | Thời gian thật | Máy đếm | Sai lệch | Sai số tương đối |
|---|---|---|---|---|
| Bước 0 (ngây thơ) | 300 s | … | … | … |
| Chính (có đèn và nút) | 300 s | … | … | … |
| Biến thể (dựa mốc) | 300 s | … | … | … |
Từ sai lệch suy ngược ra thời gian mỗi vòng
Nếu sau 300 giây thật mà máy chỉ đếm được 299, nghĩa là 299 vòng đã chiếm hết 300 giây. Mỗi vòng dài 300 000 / 299 ≈ 1003,3 ms, tức các lệnh khác chiếm khoảng 3,3 ms. Đây là một phép đo gián tiếp rất đẹp: học sinh đo được thời gian chạy của vài câu lệnh mà không cần dụng cụ nào ngoài đồng hồ bấm giờ.
Danh sách kiểm trước khi coi là xong
- Đồng hồ đếm đều, đèn nháy đúng mỗi giây một cái.
- Nhấn nút thì số về 0 và đếm lại từ đầu.
- Bảng ba dòng ở trên đã điền đủ số liệu đo thật.
- Bản dựa mốc sai lệch nhỏ hơn hẳn hai bản kia.
- Học sinh tính được thời gian một vòng lặp từ sai lệch đo được.
07 Kinh nghiệm và cạm bẫy
Sai lệch của bài này là loại tích luỹ, nên chạy 20 giây thì không thấy gì cả — lệch chưa tới một phần mười giây, nằm trong sai số bấm tay. Học sinh sẽ kết luận "đồng hồ chạy chuẩn" và cả bài coi như hỏng.
Cách làm hiệu quả nhất là bật Bước 0 ngay đầu tiết rồi để đó, học các phần khác, đến cuối tiết mới quay lại đọc số. Sau 40 phút, sai lệch thường tới cả chục giây và không ai cãi được nữa.
- Số đếm luôn bằng 1. Dòng tạo biến bị đưa vào trong vòng lặp — lỗi giống hệt Bài 4.
- Nhấn nút không đặt lại được. Thiếu phần phát hiện sườn,
hoặc đặt lệnh gán
truoc_dosai vị trí. - Bản dựa mốc in ra số nhảy cóc. Thiếu biến
da_bao, nên mỗi vòng lại in lại cùng một giây nhiều lần.
Hai hộp trên viết từ quá trình dựng và chạy thử bài. Sau buổi dạy đầu tiên, xin thầy cô thay bằng tình huống đã thực sự xảy ra ở lớp mình.
08 Ứng dụng trong dạy học
Toán — sai số tuyệt đối và sai số tương đối có số liệu thật
Bảng ba dòng ở mục Hiệu chuẩn là một bộ số liệu thật do chính học sinh đo được. Từ đó tính sai số tuyệt đối (mấy giây) và sai số tương đối (bao nhiêu phần trăm), rồi ngoại suy: sau một ngày thì lệch bao nhiêu? Sau một tháng?
Vật lí — mọi dụng cụ đo đều có sai số
Đây là bài dạy khái niệm sai số dụng cụ mà không cần giảng lí thuyết. Học sinh vừa làm ra một dụng cụ đo, vừa phát hiện nó sai, vừa định lượng được cái sai đó. Đồng hồ điện thoại đóng vai chuẩn — và cũng nên hỏi: cái chuẩn ấy lấy độ chính xác từ đâu?
Tin học — câu lệnh cũng tốn thời gian
Học sinh thường nghĩ máy chạy tức thì. Bài này cho thấy mỗi câu lệnh đều có giá
của nó, và một câu print tưởng vô hại lại là thứ tốn nhất trong vòng
lặp. Đó là bước đầu của tư duy về hiệu năng chương trình.
Hoạt động 1 — Xác định vấn đề. Giờ thể dục cần bấm giờ chạy 60 m cho cả lớp. Đồng hồ bấm tay phụ thuộc phản xạ người bấm.
Tiêu chí sản phẩm: sai lệch dưới 0,5 giây trên quãng 5 phút; đặt lại về 0 bằng một nút; và có đèn báo để người ở xa cũng biết máy đang chạy.
Hoạt động 2 — Kiến thức nền. Sai số tích luỹ; hai cách đo thời gian; phát hiện sườn nhấn.
Hoạt động 3 — Đề xuất và chọn phương án. Tiêu chí 0,5 giây trên
5 phút loại thẳng cách đếm bằng sleep. Các nhóm phải tự nhận ra và
chuyển sang cách dựa mốc — đây là chỗ tiêu chí thiết kế dẫn dắt lựa chọn kĩ thuật.
Hoạt động 4 — Chế tạo và thử. Lập trình, chạy đối chứng 5 phút với đồng hồ chuẩn, ghi số liệu.
Hoạt động 5 — Báo cáo và điều chỉnh. Các nhóm công bố bảng sai lệch. Nhóm nào vượt 0,5 giây thì phân tích nguyên nhân rồi sửa, không được đổ cho phần cứng.
- Ghép hai cổng quang thay nút bấm để đo thời gian chạy tự động.
- Ghép với Bài 35 để hiện số giây lên màn hình OLED, bỏ hẳn máy tính.
- Đồng bộ giờ qua Wi-Fi để có đồng hồ chính xác tuyệt đối — mở sang cấp độ 7.
- Hướng thi Khoa học kĩ thuật: bộ bấm giờ thi đấu cho hội khoẻ Phù Đổng cấp trường.