Bài 7 · Công nghệ · Tin học
Bàn phím ma trận 4×4
mười sáu phím chỉ tốn tám sợi dây, nhờ một mẹo rất cũ
Mỗi phím một dây thì mười sáu phím cần mười sáu chân — ESP32 không đủ, mà có đủ cũng lãng phí. Bài này dạy cách người ta giải bài toán ấy từ nửa thế kỉ trước, và cách nghĩ đó vẫn nằm trong bàn phím máy tính đang gõ.
01 Mục tiêu và yêu cầu cần đạt
Bài 2 đọc một nút bằng một chân. Cách đó không mở rộng được: mười sáu phím thì cần mười sáu chân, và ESP32 không còn đủ chân cho việc gì khác. Bài này giải bài toán ấy bằng một ý tưởng gọn đến mức đáng ngạc nhiên — và nó vẫn đang chạy trong mọi bàn phím máy tính.
Sau bài này học sinh làm được
- Giải thích vì sao mười sáu phím chỉ cần tám dây.
- Chỉ ra hàng và cột của một phím bất kì trên bàn phím trước mặt.
- Đọc hiểu vòng lặp lồng nhau quét bốn hàng × bốn cột.
- Dùng danh sách hai chiều để đổi cặp (hàng, cột) thành kí tự.
- Ghép các phím đã nhấn thành một chuỗi và so sánh với mật khẩu.
- Tin học 10 — kiểu dữ liệu danh sách, danh sách lồng nhau, vòng lặp lồng nhau, chuỗi kí tự.
- Công nghệ 10 — thiết bị nhập và nguyên lí ghép nối thiết bị ngoại vi.
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
Bên trong bàn phím không có chip nào
Chỉ là mười sáu công tắc đặt ở mười sáu giao điểm của bốn đường ngang và bốn đường dọc. Nhấn một phím tức là nối hàng i với cột j. Toàn bộ phần thông minh nằm ở chương trình.
Vì sao không đọc được cả mười sáu phím cùng lúc
Để cả bốn hàng ở mức 0 rồi đọc cột: cột 2 báo 0 thì biết có phím ở cột 2 đang nhấn — nhưng không biết hàng nào, vì bốn phím của cột 2 cho kết quả giống hệt nhau.
Gỡ nút thắt: mỗi lúc chỉ hạ một hàng xuống 0, ba hàng kia giữ mức 1. Giờ cột 2 báo 0 thì chỉ có thể do phím ở giao điểm của hàng đang hạ với cột 2 — vừa biết hàng, vừa biết cột.
Bốn hàng quét lần lượt, một vòng tốn chưa tới một phần nghìn giây, còn ngón tay giữ phím ít nhất vài chục phần nghìn giây. Nên dù chỉ nhìn từng hàng, chương trình không bỏ sót phím nào.
Ý tưởng rất chung trong kĩ thuật: thay vì làm mọi việc cùng lúc, hãy làm lần lượt nhưng nhanh hơn mức người dùng nhận ra. Màn hình LED ma trận, đèn bảy đoạn nhiều số, và cả màn hình đang đọc đều dùng mẹo này.
Điện trở kéo lên, một lần nữa
Bốn chân cột khai báo Pin.PULL_UP giống nút nhấn ở Bài 2. Không
phím nào nối thì cột được kéo lên 1; có phím nối cột với hàng đang ở 0 thì cột
tụt xuống 0. Vẫn quy tắc cũ: nhấn thì đọc ra 0.
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 |
| Bàn phím ma trận 4×4 | Loại màng mỏng dán hoặc loại nút bấm rời | 1 · 10–15k |
| Dây nối cái–đực | Bàn phím màng có sẵn 8 chân cắm | 8 · 5k |
| Breadboard | Chỉ cần nếu dùng loại nút bấm rời | 1 · dùng lại |
04 Lắp mạch và sơ đồ nối dây
| Khối | Nối dây | Nguồn |
|---|---|---|
| Hàng R1–R4 | GPIO13, 14, 26, 27 | Đặt là chân RA, chủ động kéo xuống |
| Cột C1–C4 | GPIO16, 17, 21, 22 | Đặt là chân VÀO, có điện trở kéo lên trong chip |
| Nguồn | Không cần | Bàn phím ma trận thuần tuý là các công tắc, không có mạch điện tử |
Bàn phím màng 4×4 cắm 8 dây vào ESP32 trên breadboard. Nhìn rõ thứ tự tám chân trên dải cắm của bàn phím.
Khung giữ chỗ — thay bằng ảnh chụp thật khi cóLưới 4×4: bốn đường ngang là hàng, bốn đường dọc là cột, mỗi giao điểm vẽ một công tắc. Tô đậm một giao điểm để minh hoạ phím đang nhấn nối hàng với cột.
Khung giữ chỗ — thay bằng ảnh chụp thật khi cóBốn khung nhỏ xếp ngang mô tả bốn bước quét: mỗi khung một hàng đang ở mức 0 còn ba hàng kia ở mức 1, kèm mũi tên chỉ chiều đọc bốn cột.
Khung giữ chỗ — thay bằng ảnh chụp thật khi cóTám dây, không cần nguồn
- Đặt bàn phím sao cho mặt in số hướng lên, dải chân quay về phía mình.
- Bốn chân bên trái là hàng R1–R4 →
GPIO13,14,26,27. - Bốn chân bên phải là cột C1–C4 →
GPIO16,17,21,22. - Không nối
VCChayGND— bàn phím không cần nguồn.
Có lô đánh chân từ trái sang phải là R1…R4 rồi C1…C4, có lô ngược lại, và có lô
không in gì cả. Đừng đoán. Chạy Bước 0, nhấn thử phím 1:
nếu in ra "hàng 1, cột 1" thì cách cắm đang đúng. Nếu không in gì, đảo nhóm bốn
dây bên trái với nhóm bốn dây bên phải rồi thử lại.
Đây là cách kiểm tra tốt hơn hẳn việc dò datasheet, vì nó cho học sinh một quy trình chẩn đoán dùng được với mọi linh kiện lạ về sau.
Nếu vô ý khai báo hàng là Pin.IN, chương trình chạy không báo lỗi
nhưng không phím nào nhận. Lí do: chân vào không kéo được đường hàng xuống 0,
nên cột chẳng bao giờ đổi mức.
05 Mã nguồn
Toàn bộ mã trong bài chạy trên MicroPython 1.28 cho ESP32. Thứ tự tám chân trên dải cắm của bàn phím có thể khác giữa các lô hàng — luôn kiểm bằng Bước 0 trước khi kết luận mạch sai.
Bước 0 — chỉ quét một hàng# ------------------------------------------------------------
# Bai 7 - Buoc 0: chi quet MOT hang de hieu nguyen li
# ------------------------------------------------------------
from machine import Pin
import time
hang1 = Pin(13, Pin.OUT, value=1) # R1
cot = [Pin(p, Pin.IN, Pin.PULL_UP) for p in (16, 17, 21, 22)]
hang1.off() # keo rieng hang 1 xuong 0, ba hang kia bo mac
while True:
for i, c in enumerate(cot):
if c.value() == 0:
print("Nhan phim hang 1, cot", i + 1)
time.sleep_ms(200)
Chương trình này chỉ nhận được bốn phím 1, 2,
3, A. Đó chính là điều cần cho học sinh thấy: khi chỉ hạ
một hàng, chỉ hàng ấy đọc được. Bước tiếp theo — hạ lần lượt bốn hàng — trở thành
một kết luận tự nhiên chứ không phải một quy tắc được đưa xuống.
# ------------------------------------------------------------
# Bai 7 - Quet du bon hang, doi giao diem thanh ki tu
# ------------------------------------------------------------
from machine import Pin
import time
# ===== CẤU HÌNH =====
CHAN_HANG = (13, 14, 26, 27) # R1 R2 R3 R4
CHAN_COT = (16, 17, 21, 22) # C1 C2 C3 C4
NGHI = 200 # ms - nghi giua hai lan quet
# ====================
hang = [Pin(p, Pin.OUT, value=1) for p in CHAN_HANG]
cot = [Pin(p, Pin.IN, Pin.PULL_UP) for p in CHAN_COT]
BAN_PHIM = (
("1", "2", "3", "A"),
("4", "5", "6", "B"),
("7", "8", "9", "C"),
("*", "0", "#", "D"),
)
def doc_phim():
for i, h in enumerate(hang):
h.off() # chi hang nay xuong 0
time.sleep_us(20) # cho muc dien on dinh
for j, c in enumerate(cot):
if c.value() == 0:
h.on()
return BAN_PHIM[i][j]
h.on() # tra hang ve 1 truoc khi sang hang sau
return ""
while True:
phim = doc_phim()
if phim != "":
print("Phim:", phim)
time.sleep_ms(NGHI)
Hai chi tiết đáng dừng lại. Thứ nhất, time.sleep_us(20) sau khi hạ
hàng: đường dây có điện dung nhỏ nên mức điện cần một khoảnh khắc để ổn định, đọc
sớm quá thì kết quả bấp bênh. Thứ hai, h.on() xuất hiện hai lần —
một lần trước khi trả về phím, một lần khi quét hết cột mà không thấy gì. Bỏ sót
lần nào thì hàng ấy kẹt ở mức 0 và các hàng sau đọc sai.
# Bien the: go dung mat khau thi in "Mo khoa"
MAT_KHAU = "1234"
da_go = ""
while True:
phim = doc_phim()
if phim != "":
if phim == "#":
if da_go == MAT_KHAU:
print("Mo khoa")
else:
print("Sai mat khau")
da_go = ""
elif phim == "*":
da_go = ""
print("Da xoa")
else:
da_go = da_go + phim
print("Da go", len(da_go), "ki tu")
time.sleep_ms(200)
Dùng chung hàm doc_phim() ở trên. Phím # đóng vai "Enter",
phím * đóng vai "xoá". Chuỗi da_go lớn dần theo từng phím —
đây là lần đầu học sinh dùng biến để tích luỹ chuỗi kí tự chứ không phải số.
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ử
Lập bản đồ mười sáu phím
Nạp chương trình chính rồi nhấn lần lượt từng phím theo đúng thứ tự in trên bàn phím, ghi lại kí tự máy in ra. Bảng phải trùng khít với mặt in. Nếu lệch, nghĩa là thứ tự dây chưa đúng chứ không phải chương trình sai.
| Nhấn phím | Máy in ra | Khớp? | Nhấn phím | Máy in ra | Khớp? |
|---|---|---|---|---|---|
| 1 | … | … | 9 | … | … |
| 2 | … | … | A | … | … |
| 3 | … | … | B | … | … |
| 4 | … | … | C | … | … |
| 5 | … | … | D | … | … |
| 6 | … | … | * | … | … |
| 7 | … | … | 0 | … | … |
| 8 | … | … | # | … | … |
Đo ảnh hưởng của thời gian nghỉ
Giữ một phím đúng ba giây rồi đếm số dòng in ra. Làm với NGHI bằng
100, 200 và 500 mi-li-giây. Số dòng tỉ lệ nghịch với thời gian nghỉ — đây là một
bảng số liệu nhỏ nhưng cho thấy rõ mối liên hệ giữa nhịp lặp và số lần lặp.
| NGHI (ms) | Số dòng in trong 3 giây | Số dòng dự đoán |
|---|---|---|
| 100 | … | ≈ 30 |
| 200 | … | ≈ 15 |
| 500 | … | ≈ 6 |
Danh sách kiểm trước khi coi là xong
- Cả mười sáu phím in ra đúng kí tự in trên mặt bàn phím.
- Không nhấn phím nào thì không có dòng nào được in.
- Bảng đo thời gian nghỉ đã điền đủ ba dòng.
- Học sinh chỉ đúng hàng và cột của phím
5mà không cần nhìn mã. - Biến thể khoá số nhận đúng mật khẩu và từ chối mật khẩu sai.
07 Kinh nghiệm và cạm bẫy
Xếp bốn em làm bốn hàng, bốn em làm bốn cột. Mỗi lượt chỉ một "hàng" giơ tay, các "cột" nào bị chạm thì hô. Cả lớp lập tức thấy vì sao phải hạ từng hàng một — nhanh hơn nhiều so với giảng bằng lời, và học sinh nhớ rất lâu.
- Không phím nào nhận. Nhóm dây hàng và cột bị đảo, hoặc bốn
chân hàng khai báo nhầm thành
Pin.IN. - Nhận đúng hàng 1 nhưng các hàng sau loạn. Thiếu một lệnh
h.on(), khiến hàng trước còn kẹt ở mức 0. - Giữ phím thì in ra hàng chục dòng. Không phải lỗi — đó là đặc điểm của cách đọc theo trạng thái. Muốn mỗi lần nhấn chỉ in một dòng thì cần phát hiện sườn như Bài 4.
Các 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 — danh sách lồng nhau có ý nghĩa vật lí
Học sinh thường gặp mảng hai chiều như một khái niệm trừu tượng. Ở đây,
BAN_PHIM[i][j] có nghĩa rất cụ thể: hàng thứ i, cột thứ
j, và ngón tay đang đặt đúng chỗ đó. Chỉ số không còn là con số suông.
Toán — vì sao 4 + 4 lại quản được 4 × 4
Tám dây quản mười sáu phím. Mở rộng: m + n dây quản được m × n phím. Hãy để học sinh tính thử với bàn phím máy tính khoảng 100 phím — cần bao nhiêu dây nếu xếp thành lưới 10 × 10? Con số 20 so với 100 làm cho ý tưởng ma trận trở nên thuyết phục ngay lập tức.
Hoạt động 1 — Xác định vấn đề. Tủ dụng cụ phòng thực hành cần hạn chế người mở, nhưng phát chìa cho cả lớp thì mất kiểm soát.
Tiêu chí sản phẩm: mật khẩu ít nhất bốn chữ số; có phím xoá khi gõ nhầm; gõ sai ba lần liên tiếp thì khoá tạm 30 giây; báo kết quả rõ ràng.
Hoạt động 2 — Kiến thức nền. Quét ma trận; chuỗi kí tự; so sánh chuỗi; đếm số lần sai; đếm thời gian đã học ở Bài 5.
Hoạt động 3 — Đề xuất và chọn phương án. Tiêu chí "khoá tạm sau ba lần sai" buộc các nhóm phải giữ thêm một biến đếm và một mốc thời gian — chính là hai kĩ thuật của Bài 4 và Bài 5 gặp lại nhau.
Hoạt động 4 — Chế tạo và thử. Lập trình, thử mọi tình huống kể cả gõ thừa kí tự và nhấn Enter khi chưa gõ gì.
Hoạt động 5 — Báo cáo và điều chỉnh. Các nhóm đổi máy cho nhau và cố tình phá; nhóm chủ phải vá lỗi bị tìm ra.
- Ghép rơ le của Bài 6 để khoá số thật sự mở được một chốt điện 12 V.
- Ghép màn hình LCD của Bài 34 để hiện dấu sao thay vì in ra máy tính.
- Dùng bàn phím làm bộ nhập số liệu cho các bài đo ở cấp độ 9.
- Hướng thi Khoa học kĩ thuật: hộp phiếu bầu điện tử cho hoạt động của lớp.