Lab.Vatli365
← Cấp độ 1 · Điều khiển và tín hiệu số

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.

Thời lượng
1 tiết (45 phút)
Chi phí một nhóm
≈ 5 nghìn đồng (chưa tính bo)
Cấp độ
1 / 12
Trạng thái
Đã có phần cứng, đang hoàn thiện
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 sleep luô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.
Gắn với chương trình
  • 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.

Hai cách chữa, khác nhau về chất

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ệnMô tả, lưu ý khi muaSố lượng · giá
ESP32 DevKit V1Bo 30 chân, cổng micro-USB hoặc Type-C1 · 90–150k
Nút nhấn 4 chânDùng lại nút của Bài 2 và Bài 41 · 1k
LED 5 mm và điện trở 220 ΩNháy mỗi giây cho dễ theo dõi1 · 700đ
Đồng hồ bấm giờĐiện thoại là đủ. Đây là dụng cụ đo chuẩn của bàimỗi nhóm 1
04

Lắp mạch và sơ đồ nối dây

Đỏ · nguồn dương Đen · GND Vàng · SCL Xanh dương · SDA Trắng · tín hiệu Xanh lá · 1-Wire
KhốiNối dâyNguồn
Nút nhấnGPIO4 → một chân nút · chân chéo góc → GNDKhông cần nguồn riêng
LEDGPIO23 → điện trở 220 Ω → chân dài · chân ngắn → GNDLấy từ chính chân GPIO
B10.1 Ảnh thực
Mạch giống Bài 4: ESP32, nút nhấn, LED và điện trở trên breadboard.

Mạch giống Bài 4: ESP32, nút nhấn, LED và điện trở trên breadboard.

B10.2 Ảnh thực

Đ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ó
B10.3 Hình vẽ

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ó
Mở sơ đồ này trên Wokwi Mô phỏng ngay trên trình duyệt, chưa cần bo mạch — hợp cho lúc chuẩn bị bài hoặc khi lớp thiếu thiết bị.

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.

  1. Nút nhấn: một chân → GPIO4, chân chéo góc → GND.
  2. LED: GPIO23 → điện trở 220 Ω → chân dài, chân ngắn → GND.
Đèn ở đây chỉ để nhìn cho tiện

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

  1. Nạp chương trình chính, bấm đồng hồ điện thoại cùng lúc bo khởi động.
  2. Để chạy đúng 5 phút theo đồng hồ điện thoại.
  3. Đọc số giây chương trình in ra ngay khoảnh khắc đó.
  4. Sai lệch = 300 − số máy đếm được.
Chương trìnhThời gian thậtMáy đếmSai lệchSai 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

Phải cho chạy đủ lâu, nếu không cả bài mất ý nghĩa

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.

Ba lỗi hay gặp
  • 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_do sai 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.
Chỗ này cần một chuyện thật của chính thầy cô

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 10Vật lí 10Tin học 10STEM

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.

Bài học STEM 5 hoạt động — "Đồng hồ bấm giờ cho tiết thể dục"

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.

Hướng mở rộ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.