Lab.Vatli365
← Cấp độ 2 · Tín hiệu tương tự và PWM

Bài 10 · Vật lí · Công nghệ · Toán

Phát âm bằng buzzer
tần số quyết định độ cao của âm

Bài nhập môn nối được ba thứ: một chân PWM của ESP32, khái niệm tần số trong Vật lí, và cấp số nhân trong Toán. Chỉ cần một con buzzer giá tám nghìn đồng.

Thời lượng
1 tiết (45 phút)
Chi phí một nhóm
≈ 15 nghìn đồng
Cấp độ
2 / 12
Trạng thái
Đã chạy thật với học sinh
01

Mục tiêu và yêu cầu cần đạt

Bài này dùng một con buzzer để trả lời một câu hỏi mà học sinh nào cũng từng thắc mắc: vì sao tiếng này cao, tiếng kia thấp? Và trả lời bằng cách cho các em tự tạo ra từng nốt một.

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

  • Giải thích được độ cao của âm do tần số quyết định, không phải do độ to.
  • Dùng chân PWM của ESP32 để phát ra một tần số cho trước.
  • Đo lại tần số thật bằng điện thoại và so với tần số đặt.
  • Nhận ra thang âm 12 nửa cung là một cấp số nhân, công bội 2^(1/12).
  • Xác định được vùng tần số mà tai mình nghe được, và vùng buzzer kêu to nhất.
Gắn với chương trình
  • Vật lí 11 — mạch nội dung Sóng: đặc trưng vật lí của âm (tần số, cường độ) và đặc trưng sinh lí (độ cao, độ to).
  • Công nghệ 12 — mạch nội dung Vi điều khiển: xuất tín hiệu điều khiển thiết bị.
  • Toán 11 — cấp số nhân, và hàm mũ cơ số 2.

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

Tần số quyết định độ cao

Màng buzzer rung, nén rồi giãn lớp không khí trước mặt, chuỗi nén–giãn lan tới màng nhĩ. Số lần nén–giãn trong một giây là tần số, đơn vị héc. Rung 440 lần/giây ra nốt La; 880 lần vẫn là La nhưng cao hơn một quãng tám.

Độ cao và độ to là hai chuyện khác nhau

Hỏi cả lớp: vặn to loa lên thì bài hát có cao giọng hơn không? Không. Vặn to là đổi biên độ; đổi nốt là đổi tần số. Trong bài: tần số đặt bằng buzzer.freq(), độ to bằng buzzer.duty_u16() — cho học sinh đổi từng cái một.

ESP32 tạo tần số bằng PWM

Chân GPIO chỉ có 0 V và 3,3 V, không tạo được sóng sin. Nhưng nó bật tắt rất nhanh và rất đều — với màng buzzer thế là đủ. Khai báo hai thứ:

  • freq — số lần bật tắt mỗi giây, chính là tần số âm.
  • duty_u16 — phần thời gian bật trong mỗi chu kì, từ 0 (im) đến 65535 (bật suốt). Với buzzer, 32768 tức một nửa cho âm to nhất.
Đặt duty = 65535 lại không kêu

Bật suốt nghĩa là chân giữ nguyên 3,3 V — màng bị đẩy ra rồi đứng yên. Không rung thì không có âm. Màng chỉ rung khi điện áp đổi qua đổi lại, và nửa bật nửa tắt là lúc đổi mạnh nhất.

Thang âm 12 nửa cung — chỗ Toán bước vào

Hai nốt cách một quãng tám thì tần số gấp đôi: La4 440 Hz, La5 880 Hz. Giữa chúng chia 12 nửa cung bằng nhau.

"Bằng nhau" không phải bằng về hiệu số. Tai người cảm nhận độ cao theo tỉ lệ, nên mỗi nửa cung phải nhân với cùng một số. Nhân 12 lần ra gấp đôi:

r¹² = 2   →   r = 2^(1/12) ≈ 1,059463

Thang âm là một cấp số nhân công bội 2^(1/12) — thứ học sinh lớp 11 vừa học, xuất hiện ở chỗ không ai ngờ.

Công thức tổng quát

Nốt cách La4 đúng n nửa cung (lên dương, xuống âm):

f = 440 × 2^(n/12)

Thử: Đô4 nằm dưới La4 chín nửa cung → f = 440 × 2^(−9/12) = 261,63 Hz, đúng bằng con số in trong mọi bảng nhạc lí.

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
Buzzer thụ độngLoại KHÔNG có mạch dao động bên trong. Xem hộp cạm bẫy bên dưới1 · 5–10k
Điện trở 100 ΩHạn dòng cho chân GPIO1 · 200đ
Breadboard và dây cắmLoại 400 lỗ là đủ1 bộ · 30k
Điện thoại có app đo tần sốPhys Toolbox, Spectroid… đều miễn phímỗ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
Buzzer thụ độngChân (+) → điện trở 100 Ω → GPIO25 · chân (−) → GNDLấy từ chính chân GPIO
B5.1 Ảnh thực

Mạch đã cắm trên breadboard: ESP32, buzzer, điện trở 100 Ω. Chụp chếch 45°, đủ gần để đếm được lỗ breadboard, dây đỏ và đen đúng quy ước.

Khung giữ chỗ — thay bằng ảnh chụp thật khi có
B5.2 Ảnh thực

Cận cảnh hai loại buzzer đặt cạnh nhau, lật mặt đáy: loại chủ động có mạch điện tử bên trong, loại thụ động chỉ thấy màng và hai chân. Đây là ảnh chống mua nhầm.

Khung giữ chỗ — thay bằng ảnh chụp thật khi có
B5.3 Ảnh thực

Học sinh cầm điện thoại chạy app đo tần số hướng vào buzzer, màn hình hiện đỉnh phổ ở 440 Hz. Chụp thấy cả buzzer lẫn màn hình.

Khung giữ chỗ — thay bằng ảnh chụp thật khi có

Ba bước lắp

  1. Cắm buzzer lên breadboard, chú ý dấu + in trên thân.
  2. Nối chân + qua điện trở 100 Ω sang GPIO25.
  3. Nối chân còn lại xuống GND.
Mua nhầm buzzer là hỏng cả bài

Ngoài chợ có hai loại nhìn gần giống hệt nhau:

  • Buzzer chủ động — bên trong đã có sẵn mạch dao động. Cấp điện là nó kêu, nhưng chỉ kêu đúng một tần số cố định. Với bài này thì vô dụng.
  • Buzzer thụ động — chỉ có màng và cuộn dây. Nó kêu theo đúng tần số ta cấp. Đây là loại cần mua.

Cách phân biệt tại chỗ: lật mặt đáy lên. Loại chủ động thường bịt kín bằng miếng nhựa hoặc keo đen; loại thụ động hở, nhìn thấy bảng mạch xanh và cuộn dây. Cách chắc hơn: chấm nhẹ hai chân vào pin 3 V — kêu một tiếng "tít" liên tục là chủ động, chỉ kêu "tách" một cái rồi im là thụ động.

Khi đặt hàng, hãy tìm đúng chữ passive buzzer. Tôi từng mua nhầm cả chục con và chỉ phát hiện ra vào tối trước buổi dạy.

Điện trở 100 Ω không phải để cho vui

Buzzer có điện trở rất thấp. Nối thẳng vào GPIO thì dòng có thể vượt quá 12 mA mà chân ESP32 chịu được, làm hỏng chân — kiểu hỏng khó chịu vì bo vẫn chạy, chỉ mỗi chân đó chết.

Con điện trở 100 Ω giữ dòng ở mức an toàn. Âm nhỏ đi một chút, nhưng trong phòng học thì vẫn thừa to.

05

Mã nguồn

Toàn bộ mã trong bài có sẵn tại kho GitHub, thư mục cap-1/bai-05-buzzer/. Chép tệp vào bo mạch rồi đổi tên thành main.py là chạy.

Chương trình chính — chạy hết một quãng tám
# ------------------------------------------------------------
#  Bai 10 - Phat am bang buzzer: thang am 12 nua cung
#  Phan cung: buzzer thu dong noi GPIO25 qua dien tro 100 ohm
# ------------------------------------------------------------
from machine import Pin, PWM
import time

CHAN_BUZZER = 25
F_LA4 = 440.0          # not La quang tam 4, moc chuan quoc te

buzzer = PWM(Pin(CHAN_BUZZER))
buzzer.duty_u16(0)     # im lang khi khoi dong

TEN_NOT = ["Do", "Do#", "Re", "Re#", "Mi", "Fa",
           "Fa#", "Sol", "Sol#", "La", "La#", "Si"]

def tan_so_cua(nua_cung_so_voi_la):
    """Moi nua cung nhan them 2^(1/12) lan."""
    return F_LA4 * (2 ** (nua_cung_so_voi_la / 12))

def keu(f_hz, thoi_gian_ms=400):
    buzzer.freq(int(f_hz))
    buzzer.duty_u16(32768)     # 50% - to nhat
    time.sleep_ms(thoi_gian_ms)
    buzzer.duty_u16(0)         # tat han giua hai not
    time.sleep_ms(60)

# Do quang tam 4 nam duoi La 9 nua cung
for i in range(13):
    f = tan_so_cua(i - 9)
    ten = TEN_NOT[i % 12]
    print("{:5s}  {:7.2f} Hz".format(ten, f))
    keu(f)

buzzer.deinit()

Màn hình in ra bảng tần số của từng nốt trong lúc buzzer kêu:

Do      261.63 Hz
Do#     277.18 Hz
Re      293.66 Hz
Re#     311.13 Hz
Mi      329.63 Hz
Fa      349.23 Hz
Fa#     369.99 Hz
Sol     392.00 Hz
Sol#    415.30 Hz
La      440.00 Hz
La#     466.16 Hz
Si      493.88 Hz
Do      523.25 Hz

Chú ý dòng cuối bảng: nốt Đô ở cuối đúng bằng gấp đôi nốt Đô ở đầu — 523,25 so với 261,63. Đây là chỗ để dừng lại và hỏi cả lớp.

Chương trình phụ — quét tìm vùng buzzer kêu to nhất
# Quet tan so tu 100 Hz den 5000 Hz de tim vung buzzer keu to nhat
from machine import Pin, PWM
import time

buzzer = PWM(Pin(25))
buzzer.duty_u16(32768)

f = 100
while f <= 5000:
    buzzer.freq(f)
    print(f, "Hz")
    time.sleep_ms(300)
    f = int(f * 1.15)      # tang 15% moi buoc - tai nghe deu hon la tang deu

buzzer.duty_u16(0)
buzzer.deinit()

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ử

Đo lại xem máy có nói thật không

Đây là bước biến một trò chơi thành một phép đo, và nó chỉ mất năm phút.

  1. Cho học sinh cài một app đo tần số miễn phí trên điện thoại (Phyphox, Physics Toolbox, hay Spectroid đều được).
  2. Chạy chương trình, dừng lại ở nốt La (440 Hz).
  3. Hướng micro điện thoại vào buzzer, đọc đỉnh phổ.
  4. Ghi lại: máy đặt bao nhiêu, điện thoại đo được bao nhiêu.

Kết quả thường lệch dưới 1%. Nếu lệch nhiều hơn thì gần như chắc chắn là phòng quá ồn hoặc app đang bắt một hài bậc cao chứ không phải tần số cơ bản.

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

  • Buzzer kêu rõ ràng khác nhau ở nốt Đô và nốt Đô cao.
  • Điện thoại đo được 440 ± 5 Hz khi máy đặt 440 Hz.
  • Đặt duty_u16(65535) thì buzzer im — học sinh giải thích được vì sao.
  • Chương trình kết thúc bằng deinit() và buzzer không rít nữa.
Buzzer rít mãi không tắt

Nếu chương trình dừng giữa chừng (bấm Stop, hoặc lỗi), chân PWM vẫn giữ nguyên trạng thái cuối và buzzer rít liên tục — rất khó chịu khi có tám nhóm cùng lúc.

Cách chữa: luôn gọi buzzer.duty_u16(0) rồi buzzer.deinit() ở cuối. Và trong lúc thử nghiệm, hãy nhớ tổ hợp cứu hộ: gõ PWM(Pin(25)).deinit() thẳng trong REPL là im ngay.

07

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

Tám nhóm cùng kêu là không ai nghe được gì

Buổi đầu tiên tôi cho cả tám nhóm chạy cùng lúc. Kết quả là một mớ âm thanh hỗn độn, không nhóm nào phân biệt nổi nốt của mình, và lớp bên cạnh sang gõ cửa.

Từ đó tôi làm ba việc: đặt thời lượng mỗi nốt xuống 250 ms cho nhanh gọn; cho các nhóm chạy lệch nhau — nhóm 1–4 chạy trước, nhóm 5–8 quan sát rồi đổi vai; và dán một mẩu băng dính lên miệng buzzer để giảm bớt độ to mà không ảnh hưởng tần số. Mẩu băng dính ấy hóa ra lại là một thí nghiệm phụ rất hay: nó đổi độ to mà không đổi độ cao — đúng thứ ta muốn dạy.

Câu hỏi làm cả lớp im lặng

Sau khi chạy hết thang âm, tôi hỏi: "Từ Đô lên Rê tăng 32 Hz. Vậy từ Đô cao lên Rê cao tăng bao nhiêu?"

Gần như cả lớp trả lời "32 Hz". Rồi các em nhìn bảng số liệu do chính máy in ra: 523,25 lên 587,33, tức là tăng 64 Hz. Gấp đôi.

Khoảnh khắc "ơ, sao lại thế" đó đáng giá hơn cả buổi giảng về cấp số nhân. Và nó chỉ xảy ra được khi các em có bảng số liệu thật trước mặt.

Ba lỗi hay gặp
  • Buzzer kêu nhưng mọi nốt nghe như nhau. Đang dùng buzzer chủ động. Xem lại mục lắp mạch.
  • Nốt cao nghe to hơn hẳn nốt thấp. Bình thường — buzzer nhỏ có tần số cộng hưởng riêng, thường quanh 2–4 kHz. Đây là cơ hội nói về cộng hưởng, và là lí do có chương trình quét ở trên.
  • Số hiện ra nhưng không có tiếng. Kiểm tra duty_u16 có bằng 0 không, và kiểm tra chân cắm đúng GPIO25 chưa.
08

Ứng dụng trong dạy học

Vật lí 11Công nghệ 12Toán 11Âm nhạc

Vật lí — đặc trưng vật lí và đặc trưng sinh lí của âm

Đây là bài lí tưởng để tách hai khái niệm mà sách giáo khoa đặt cạnh nhau nhưng học sinh vẫn lẫn. Cho các em thay đổi một đại lượng và giữ nguyên đại lượng kia:

Thay đổiGiữ nguyênTai nghe thấy gì
freq()duty_u16()Đổi độ cao, độ to gần như không đổi
duty_u16()freq()Đổi độ to, độ cao không đổi

Hai dòng bảng này thay được cả một trang lí thuyết.

Toán — cấp số nhân có thật ngoài đời

Cho học sinh lập bảng tần số 13 nốt, rồi tính tỉ số giữa hai nốt liên tiếp. Tỉ số ấy luôn bằng 1,0595 — chính là công bội. Sau đó hỏi ngược: nếu muốn chia quãng tám thành 24 phần đều nhau (nhạc Ả Rập có làm thế) thì công bội là bao nhiêu?

Công nghệ — điều khiển bằng vi điều khiển

Bài này là ví dụ nhỏ nhất và rõ nhất của mạch nội dung "Vi điều khiển": một chân ra, một tín hiệu số, một thiết bị chấp hành. Từ đây mở sang điều khiển đèn, quạt, động cơ đều cùng một nguyên lí.

Bài học STEM 5 hoạt động — "Chuông báo tiết học riêng của lớp"

Hoạt động 1 — Xác định vấn đề. Trường dùng chung một tiếng chuông cho mọi việc. Lớp cần một chuông riêng để báo ba tình huống khác nhau: hết giờ làm bài, đến lượt nhóm báo cáo, và cảnh báo im lặng.

Tiêu chí sản phẩm: ba giai điệu phân biệt được khi nghe ở cuối lớp; mỗi giai điệu dài dưới 3 giây; dùng đúng một buzzer; và một bạn lớp khác nghe ba lần phải đoán đúng cả ba.

Hoạt động 2 — Kiến thức nền. Tần số và độ cao; PWM; cấp số nhân trong thang âm.

Hoạt động 3 — Đề xuất và chọn phương án. Mỗi nhóm thiết kế ba giai điệu trên giấy trước khi lập trình, và giải thích vì sao chọn tần số đó cho tình huống đó.

Hoạt động 4 — Chế tạo và thử. Lập trình, chạy thử ở cuối lớp, đo mức âm bằng điện thoại nếu có.

Hoạt động 5 — Báo cáo và điều chỉnh. Mời lớp khác nghe và đoán. Nhóm nào bị đoán sai thì phân tích vì sao rồi sửa.

Hướng mở rộng
  • Ghép thêm nút nhấn của Bài 2 để chọn giai điệu.
  • Ghép với cảm biến khoảng cách (Bài 24) làm nhạc cụ Theremin đơn giản: đưa tay lại gần thì âm cao lên.
  • Dùng micro của Bài 31 để đo lại chính tần số mình phát ra — khép kín vòng phát và thu.
  • Hướng thi Khoa học kĩ thuật: thiết bị hỗ trợ luyện tai nghe nhạc cho học sinh khiếm thị, phát nốt và chấm câu trả lời.