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

Bài 4 · Toán · Công nghệ · Tin học

Đếm số lần nhấn nút
máy chỉ thấy trạng thái, người mới thấy sự kiện

Bài này nhìn qua tưởng dễ hơn Bài 2, nhưng thật ra khó hơn hẳn. Đếm số lần nhấn buộc chương trình phải nhớ được quá khứ — và đó là khái niệm mới quan trọng nhất của cả cấp độ 1.

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ài 2, chương trình chỉ cần biết ngay lúc này nút có đang bị nhấn không. Bài này cần biết thêm một thứ hoàn toàn khác: vừa nãy nút có bị nhấn không. Chỉ thêm một chữ "vừa nãy" thôi, nhưng nó buộc chương trình phải có trí nhớ.

Sau bài này học sinh làm được

  • Dùng biến để đếm và giải thích vì sao biến phải khai báo ngoài vòng lặp.
  • Phân biệt trạng thái (đang nhấn) và sự kiện (vừa nhấn xuống).
  • Viết được điều kiện phát hiện sườn: đang nhấn và chưa nhấn ở vòng trước.
  • Mô tả được hiện tượng dội tiếp điểm và cách xử lí bằng khoảng chờ.
  • Dự đoán được số đếm sai khi bỏ phần nhớ trạng thái.
Gắn với chương trình
  • Tin học 10 — biến, phép gán, biểu thức lôgic có phép "và" và "không".
  • Toán 10 — đại lượng rời rạc, phép đếm.
  • Công nghệ 12 — xử lí tín hiệu đầu vào từ nút nhấn.

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

Máy không thấy sự kiện, chỉ thấy trạng thái

Ta nghĩ mình vừa tạo ra một cú bấm. Máy thì chạy vòng lặp rất nhanh và mỗi vòng chỉ đọc được một trạng thái: nhấn, hoặc không nhấn.

Ngón tay giữ nút chừng 0,2 giây. Vòng lặp nghỉ 20 ms thì máy đọc được khoảng mười vòng liên tiếp đều thấy "đang nhấn" — cứ thấy là cộng một thì một cú bấm bị đếm thành mười.

Sự kiện là chỗ trạng thái thay đổi

Đừng hỏi "nút có đang được nhấn không", hãy hỏi "nút có VỪA MỚI bị nhấn xuống không". Câu sau cần hai thông tin — bây giờ và vòng trước:

if dang_nhan and not truoc_do:

Điều kiện này chỉ đúng ở một vòng duy nhất trong cả quãng ngón tay còn đè lên nút — đúng vòng mà trạng thái vừa lật. Gọi là phát hiện sườn.

Dội tiếp điểm — kẻ phá bĩnh còn lại

Hai lá kim loại không chạm nhau dứt khoát một lần. Chúng nảy vài lần trong dưới 10 ms đầu, tín hiệu là 0-1-0-1 rồi mới yên — máy thấy vài sườn cho một cú bấm.

Chữa rẻ nhất: ghi nhận xong một lần nhấn thì nghỉ hẳn 200 ms mới đọc tiếp. Lúc đó tiếp điểm đã ổn định, mà ngón tay người cũng không bấm nổi hai cái trong 200 ms nên không mất cú nào.

Biến đếm phải sống lâu hơn một vòng lặp

so_lan = 0 nằm trước while True:. Chuyển vào trong vòng lặp thì mỗi vòng biến lại bị đặt về 0 và số đếm mãi mãi bằng 1. Lỗi kinh điển, cũng là thử thách ở cuối bài.

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 21 · 1k
LED 5 mm và điện trở 220 ΩĐèn báo mỗi lần ghi nhận được một cú bấm1 · 700đ
Breadboard và dây cắmLoại 400 lỗ là đủ1 bộ · 30k
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
B4.1 Sơ đồ nối dây
Sơ đồ ESP32 DevKit: GPIO23 qua điện trở 220 Ω tới LED rồi về GND; GPIO4 nối một chân nút nhấn, chân chéo góc của nút về GND.

Mạch giống hệt Bài 2 — GPIO4 đọc nút, GPIO23 điều khiển LED. Nếu lớp vừa học Bài 2 xong thì không phải rút một sợi dây nào, chỉ đổi chương trình.

B4.2 Ảnh thực
Ảnh chụp mạch thật: bo ESP32 DevKit cắm cáp USB, breadboard có LED vàng, điện trở và một nút nhấn vàng cỡ lớn.

Chính mạch ấy khi đã cắm xong: nút nhấn vắt qua rãnh giữa breadboard, LED và điện trở ở hàng bên. Số lần nhấn hiện ở khung Màn hình của bo phía dưới.

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ị.

Giữ nguyên mạch Bài 2

Bài này dùng đúng mạch của Bài 2, không thêm bớt gì: nút nhấn ở GPIO4 và LED ở GPIO23. Nếu lớp vừa học Bài 2 xong thì không phải rút một sợi dây nào.

  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.
Vẫn là cặp chân chéo góc

Nhắc lại vì đây là lỗi tốn thời gian nhất của cả hai bài: nút 4 chân có hai cặp đã thông sẵn bên trong. Dùng nhầm một cặp thì máy sẽ thấy nút luôn luôn được nhấn, và số đếm nhảy loạn ngay khi cấp nguồ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 — bản SAI, cho học sinh chạy trước
# ------------------------------------------------------------
#  Bai 4 - Ban DEM SAI, co tinh de hoc sinh tu tim ra loi
# ------------------------------------------------------------
from machine import Pin
import time

nut = Pin(4, Pin.IN, Pin.PULL_UP)
so_lan = 0

while True:
    if nut.value() == 0:
        so_lan = so_lan + 1
        print("So lan nhan:", so_lan)
    time.sleep_ms(20)

Bấm đúng một cái, màn hình in ra:

So lan nhan: 1
So lan nhan: 2
So lan nhan: 3
...
So lan nhan: 47     <-- moi bam MOT cai

Đây là bản cố tình sai, và nó đáng giá hơn bản đúng. Hãy để học sinh chạy bản này trước, tự thấy con số nhảy vọt, rồi mới hỏi vì sao. Câu trả lời chính là toàn bộ nội dung của bài.

Chương trình chính — đếm đúng
# ------------------------------------------------------------
#  Bai 4 - Dem so lan nhan nut
#  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              # nut nhan
CHAN_LED = 23             # den bao da ghi nhan
CHONG_DOI = 200           # ms - bo qua nhieu tiep diem sau moi lan nhan
# ====================

nut = Pin(CHAN_NUT, Pin.IN, Pin.PULL_UP)
led = Pin(CHAN_LED, Pin.OUT)

so_lan = 0
truoc_do = False          # nut co dang duoc nhan o VONG TRUOC khong

while True:
    dang_nhan = nut.value() == 0

    # Chi lam viec o dung KHOANH KHAC nut chuyen tu nha sang nhan
    if dang_nhan and not truoc_do:
        so_lan = so_lan + 1
        print("So lan nhan:", so_lan)
        led.on()
        time.sleep_ms(120)
        led.off()
        time.sleep_ms(CHONG_DOI)

    truoc_do = dang_nhan
    time.sleep_ms(10)

Bấm ba cái, màn hình in ra đúng ba dòng:

So lan nhan: 1
So lan nhan: 2
So lan nhan: 3

So hai bản cạnh nhau, khác biệt chỉ nằm ở hai chỗ: biến truoc_do và điều kiện and not truoc_do. Hai chỗ đó biến một chương trình sai thành một chương trình đúng.

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 thử đếm đúng

  1. Nạp chương trình chính, để số đếm về 0 bằng cách cấp nguồn lại.
  2. Bấm chậm rãi đúng 10 lần, mỗi lần cách nhau khoảng một giây.
  3. Số cuối cùng in ra phải đúng bằng 10.
  4. Lặp lại nhưng bấm nhanh hết mức có thể trong 5 giây, rồi đếm lại bằng mắt xem có khớp không.

Phép thử phá chống dội

Hạ CHONG_DOI từ 200 xuống 5 ms rồi bấm nhanh. Số đếm sẽ nhảy hơn số lần bấm thật. Đó không phải lỗi mới — đó chính là dội tiếp điểm lộ ra khi ta gỡ bỏ tấm chắn.

Danh sách kiểm trước khi coi là xong

  • Bản sai ở Bước 0 cho ra số nhảy vọt, học sinh giải thích được vì sao.
  • Bản đúng đếm khớp 10 lần bấm chậm.
  • Giữ nút thật lâu vẫn chỉ tính là một lần.
  • Hạ CHONG_DOI xuống 5 ms thì số đếm bắt đầu sai.
  • Học sinh chỉ ra được vì sao so_lan = 0 phải nằm ngoài vòng lặp.
07

Kinh nghiệm và cạm bẫy

Dạy bản sai trước là cách tiết kiệm thời gian nhất

Cám dỗ lớn nhất của bài này là đưa thẳng bản đúng rồi giảng về phát hiện sườn. Làm thế thì học sinh chép được chương trình nhưng không hiểu vì sao lại cần biến truoc_do — với các em nó chỉ là một dòng thừa khó hiểu.

Chạy bản sai trước mất thêm năm phút, nhưng sau đó cả lớp muốn biết cách chữa. Từ chỗ đó, dòng and not truoc_do không còn là phép thuật mà là câu trả lời cho một câu hỏi các em vừa tự đặt ra.

Ba lỗi hay gặp
  • Số đếm luôn bằng 1. Dòng tạo biến đếm bị đưa vào trong vòng lặp. Mỗi vòng nó lại về 0.
  • Số đếm tự nhảy khi không ai chạm vào. Nút cắm nhầm cặp chân, hoặc dây nút bị lỏng làm chân GPIO thả nổi.
  • Bấm nhanh thì mất cú bấm. CHONG_DOI đặt quá lớn, ví dụ 1000 ms. Trong một giây đó mọi cú bấm đều bị bỏ qua.
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

Tin học 10Toán 10Công nghệ 12STEM

Tin học — biến, phép gán và biểu thức lôgic gặp nhau

Ba khái niệm rời rạc trong sách bỗng phải làm việc cùng nhau ở đây: biến để nhớ, phép gán để cập nhật, biểu thức lôgic để quyết định. Và có một dòng rất đáng dừng lại: truoc_do = dang_nhan nằm ở cuối vòng lặp. Hỏi cả lớp xem chuyện gì xảy ra nếu chuyển dòng đó lên đầu.

Toán — đếm và sai số của phép đếm

Cho học sinh bấm 50 lần rồi so số máy đếm với số các em tự đếm. Thảo luận: nếu hai con số lệch nhau, ai sai? Máy đếm thừa vì dội tiếp điểm, hay người đếm sót vì mất tập trung? Đây là cửa vào rất tự nhiên cho khái niệm sai số của phép đo.

Bài học STEM 5 hoạt động — "Máy đếm người vào thư viện"

Hoạt động 1 — Xác định vấn đề. Thư viện trường muốn biết mỗi buổi có bao nhiêu lượt người vào, mà không phải cử người ngồi đếm.

Tiêu chí sản phẩm: đếm đúng ít nhất 19 trên 20 lượt thử; có đèn báo mỗi lượt để người dùng biết máy đã ghi nhận; và số đếm không bị nhảy khi không có ai đi qua.

Hoạt động 2 — Kiến thức nền. Trạng thái và sự kiện; phát hiện sườn; dội tiếp điểm; biến đếm.

Hoạt động 3 — Đề xuất và chọn phương án. Nút nhấn ở đây thay cho cảm biến thật. Cho các nhóm bàn xem sau này thay bằng cảm biến gì, và cảm biến đó có bị "dội" như nút không.

Hoạt động 4 — Chế tạo và thử. Lập trình, chạy thử 20 lượt, ghi lại số máy đếm được.

Hoạt động 5 — Báo cáo và điều chỉnh. Nhóm khác thử phá: bấm thật nhanh, giữ thật lâu, bấm nửa vời. Nhóm nào bị phá thành công thì chỉnh lại con số chống dội.

Hướng mở rộng
  • Thêm nút thứ hai để đếm lượt ra, rồi tính số người đang ở trong phòng.
  • Ghép với Bài 35 để hiện số đếm lên màn hình OLED thay vì in ra máy tính.
  • Bài 5 dùng lại đúng ý phát hiện sườn này để làm nút đặt lại đồng hồ.
  • Hướng thi Khoa học kĩ thuật: máy đếm lượt mượn sách, gửi số liệu về máy chủ cuối ngày.