Dự án 14: Đàn piano thu nhỏ - MakerEdu Inventor Kit for Micro:bit

From MakerLab Wiki
Jump to navigation Jump to search

Mức độ: Khó ★★★★★★★★★

Danh sách thiết bị

Sơ đồ kết nối

MakerEDU Shield Thiết bị
Port P0 [MKE-M02] - Nút nhấn (1)
Port P1 [MKE-M02] - Nút nhấn (2)
Port P2 [MKE-M02] - Nút nhấn (3)

Mô tả dự án

Trong dự án này, các bạn sẽ làm một chiếc đàn piano mini.

Dù chỉ với 3 nút nhấn, nhưng bạn hoàn toàn có thể mở rộng thành dãy 7 phím note nhạc cơ bản Đô (C) - Rê (D) - Mi (E) - Fa (F) - Sol (G) - La (A) - Si (B) đấy.

Giải thích

Icon-Attention-White.png Lưu ý:
Bài này mình sử dụng mô-đun Nút nhấn, cho nên code chương trình cũng được phân tích dựa trên nguyên lý hoạt động của thiết bị này.

Với mô-đun Nút nhấn:

  • Khi nhấn nút → chân SIG sẽ xuất ra mức LOW.
  • Khi nhả nút → chân SIG sẽ xuất ra mức HIGH.

Có thể thấy một nút nhấn luôn có 2 trạng thái "nhấn""nhả". Với 1 nút nhấn bạn có thể tạo ra 2 trường hợp.

Vậy với 3 nút nhấn bạn sẽ tạo ra được mấy trường hợp? Mình sẽ phân tích tiếp để tìm câu trả lời!

Dựa theo thông số kỹ thuật trên, mình quy ước:

  • "nhấn" = LOW = 0
  • "nhả" = HIGH = 1

Bây giờ mình đặt tên cho các nút nhấn như sau:

  • Nút nhấn (1) là "line0"
  • Nút nhấn (2) là "line1"
  • Nút nhấn (3) là "line2"

Sau đó lập bảng liệt kê ra tất cả các trường hợp:

line2 line1 line0 Thao tác Nốt nhạc
1 1 1 không nhấn nút nào
1 1 0 nhấn nút 1 Đô (C)
1 0 1 nhấn nút 2 Rê (D)
1 0 0 nhấn nút 1 và 2 Mi (E)
0 1 1 nhấn nút 3 Fa (F)
0 1 0 nhấn nút 1 và 3 Sol (G)
0 0 1 nhấn nút 2 và 3 La (A)
0 0 0 nhấn cả 3 nút Si (B)

Cuối cùng mình gắn cho mỗi "thao tác" tương ứng với một note nhạc mình muốn như hình.

7 note Piano

Các bước thực hiện (Giai đoạn 1)

Tạo code

  1. Tạo 3 biến có với tên "line0, line1, line2".
    → 3 biến này lưu giá trị trạng thái hiện tại của mỗi nút nhấn tương ứng.
  2. Tạo 1 hàm có tên "function play_music_notes", xong bấm nút Done.
  3. Trong vùng code, bạn tạo chức năng cho khối function play_music_notes như hình dưới.
    → Khối này dựa theo giá trị hiện tại của 3 biến "line0", "line1", "line2" để ra quyết định sẽ phát nhạc như thế nào.
Icon-Done-White.png Giải thích:
Mỗi biểu thức dưới đây của lệnh ifelse if chỉ được thực hiện khi phép toán Logic AND trả về kết quả "true", như vậy tất cả toán hạng đều phải là giá trị 1.

Vậy nên để biểu thức đó được thực hiện, mình dùng phép toán Logic NOT giúp đảo giá trị 0 thành 1.

Vd: để micro:bit phát nốt Đô (C), theo bảng trên ta nhấn nút 1, nghĩa là khi đó:

  • Nút 3 không nhấn → line2 = 1.
  • Nút 2 không nhấn → line1 = 1.
  • Nút 1 đang nhấn → line0 = 0 → NOT(line0) = 1.

Biểu thức (line2) AND (line1) AND (NOT(line0))"true", nên khối play tone Middle C for 1/2 beat được thực hiện.

Blocks

MakeCode Kit 15a.png

Javascript

let line0 = 0
let line1 = 0
let line2 = 0

function play_music_notes() {
  if (line2 && (line1 && !(line0))) {
    music.playTone(262, music.beat(BeatFraction.Half))
  } else if (line2 && (!(line1) && line0)) {
    music.playTone(294, music.beat(BeatFraction.Half))
  } else if (line2 && (!(line1) && !(line0))) {
    music.playTone(330, music.beat(BeatFraction.Half))
  } else if (!(line2) && (line1 && line0)) {
    music.playTone(349, music.beat(BeatFraction.Half))
  } else if (!(line2) && (line1 && !(line0))) {
    music.playTone(392, music.beat(BeatFraction.Half))
  } else if (!(line2) && (!(line1) && line0)) {
    music.playTone(440, music.beat(BeatFraction.Half))
  } else if (!(line2) && (!(line1) && !(line0))) {
    music.playTone(494, music.beat(BeatFraction.Half))
  }
}

Các bước thực hiện (Giai đoạn 2)

Tạo code

  1. Tạo 1 khối on start như hình dưới.
    → Khối này thực hiện 1 lần mỗi khi micro:bit khởi động, để cài đặt mức âm lượng lớn nhất cho còi.
  2. Tạo 1 khối forever như hình dưới.
    → Khối này đọc liên tục giá trị của cả 3 nút nhấn và ra quyết định có phát nhạc hay không, nếu có thì là phát note nhạc nào?
Icon-Done-White.png Giải thích:
Micro:bit đọc liên tục giá trị của cả 3 nút nhấn và cho lưu vào các biến "line0", "line1", "line2".

Nếu phát hiện có bất kì thao tác nào lên một trong ba nút nhấn, sẽ cho đợi 30ms. Bước này để đảm bảo đó là thao tác từ người dùng, không phải do nhiễu gây ra (nếu có). Xong rồi đọc lại giá trị của cả 3 nút lần nữa và gọi hàm call play_music_notes để xử lý sẽ phát note nhạc nào.

Với phép toán Logic OR chỉ cần một trong các toán hạng có giá trị 1, kết quả trả về là "true". Vậy nên để biểu thức (NOT(line2)) OR (NOT(line1)) OR (NOT(line0)) chỉ được thực hiện khi có thao tác nhấn nút, mình cũng dùng phép toán Logic NOT để đảo giá trị.

Blocks

MakeCode Kit 15b.png

Javascript

music.setVolume(255)

basic.forever(function () {
  line0 = pins.digitalReadPin(DigitalPin.P0)
  line1 = pins.digitalReadPin(DigitalPin.P1)
  line2 = pins.digitalReadPin(DigitalPin.P2)
  if (!(line2) || (!(line1) || !(line0))) {
    basic.pause(30)
    line0 = pins.digitalReadPin(DigitalPin.P0)
    line1 = pins.digitalReadPin(DigitalPin.P1)
    line2 = pins.digitalReadPin(DigitalPin.P2)
    play_music_notes()
  }
})

Nạp code

  1. Kết nối [MKE-M02] - Nút nhấn (1) đến Port P0 của MakerEdu Shield.
  2. Kết nối [MKE-M02] - Nút nhấn (2) đến Port P1 của MakerEdu Shield.
  3. Kết nối [MKE-M02] - Nút nhấn (3) đến Port P2 của MakerEdu Shield.
  4. Nhấp vào Download để nạp code của bạn sang micro:bit.
  5. Bấm các nút và nghe xem micro:bit có phát đúng các note nhạc như mong đợi không.

Kết quả

... hình dự án

Bài tập thêm

  • Dựa theo nguyên lý trên, các bạn hãy sử dụng các vật dụng khác quanh mình làm thành bộ piano với 7 phím đàn hoàn chỉnh thử xem.