ช่วงนี้ก็เรียกได้ว่าเข้าสู่สิ้นปีแล้ว พอนึกถึงคริสต์มาส ปีใหม่ ก็ต้องนึกถึงการเฉลิมฉลอง จะว่ากันเรื่องแสงสี Arduino ทำไฟกระพริบทุกท่านก็คงทำกันได้อยู่แล้ว งั้นผู้เขียนขอพูดถึงเสียงเพลงดีกว่า วันนี้เราจะมาลองให้ Arduino ร้องเพลงกันครับ

Special Thanks : โค้ดในบทความนี้ได้ดัดแปลงมาจากโค้ดของคุณ Joshi ซึ่งได้ทำการดัดแปลงจากต้นฉบับของคุณ Dipto Pratyaksa ผู้เขียนขอขอบคุณไว้ตรงนี้ด้วยครับ
All codeing in this article adapted from the project of Joshi, that modified from Dipto Pratyaksa's project [Aviable Here]
อุปกรณ์ที่ใช้ในโปรเจคนี้ : Arduino UNO R3 (หรือบอร์ด Arduino อื่น ๆ ก็ได้) Piezo Buzzer (หรือลำโพงอื่น ๆ เช่น ลำโพง 0.25W 8Ohm ลำโพง 0.5W 8Ohm ลำโพงแท็ปเล็ต 1W 8Ohm)
ตัวต้านทาน 10k Ohm (สำหรับ Pull-down สวิตช์)
ตัวต้านทาน 330 Ohm (สำหรับจำกัดกระแสที่เข้าสู่ Buzzer)
ก่อนอื่นเราต้องทำความเข้าใจกันว่า Arduino ร้องเพลงนั้นไม่ใช่ร้องเป็นเสียงพูดเหมือนคนร้องเพลงนะครับ แต่จะร้องเป็นเมโลดี้โน๊ตต่าง ๆ เหมือนกล่องดนตรี หรือใครมีอายุพอ ๆ กับผู้เขียนก็อาจจะผ่านเสียงยุคเกมบอยขาวดำ มันจะเป็นลักษณะเพลง 8bit แบบนั้นแหละครับ
ในตอนที่เราเล่นดนตรีจริง ๆ นั้น โน๊ตแต่ละตัวก็คือคลื่นเสียงที่มีความถี่ต่างกัน หลักการนี้ก็จะนำมาใช้หล่ะครับ เราจะให้ Arduino ผลิตความถี่ออกมาเป็นโน๊ตแต่ละตัว เรียบเรียงเป็นจังหวะและทำนองกลายเป็นเพลงนั่นเอง ซึ่งเราจะใช้คำสั่ง tone() ซึ่งเป็นคำสั่งให้ Arduino ผลิต Square wave ที่มี duty cycle 50% ตามความถี่ที่เรากำหนด ซึ่งเจ้าคำสั่ง tone() จะมีรูปแบบดังนี้
tone(pin, frequency)
และเราสามารถเพิ่มความยาวของโน๊ตแต่ละตัวลงไปได้เป็นรูปแบบนี้
tone(pin, frequency, duration)
โดยที่ pin คือขาของ Arduino ที่ต้องการให้ผลิตความถี่ออกมา frequency คือความถี่ของแต่ละตัวโน๊ต และ duration คือความยาวของโน๊ตนั้นในหน่วยมิลลิวินาที เอาหล่ะ pin ใน Arduino เรามีเหลือเฟือ ใช้ digital ขาไหนก็ได้หยิบมาซักขา ส่วน duration นั้นก็รู้อยู่แล้วว่าต้องการให้ยาวกี่จังหวะ ใครพอเล่นดนตรีได้ก็นับห้องนับอะไรไป แล้ว frequency ความถี่ของตัวโน๊ตต่าง ๆ เราจะรู้ได้ไงหว่า ก็ตามตารางนี้เลยครับ(ความถี่ของโน๊ตจริง ๆ จะมีทศนิยม แต่ด้วยความสามารถของอุปกรณ์ดิจิตอลก็ปัดขึ้นปัดลงให้มันลงตัวไปครับ)
|
Notes |
C |
C# |
D |
D# |
E |
F |
F# |
G |
G# |
A |
A# |
B |
Octave |
0 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
25 |
26 |
28 |
29 |
31 |
1 |
33 |
35 |
37 |
39 |
41 |
44 |
46 |
49 |
52 |
55 |
58 |
62 |
2 |
65 |
69 |
73 |
78 |
82 |
87 |
93 |
68 |
104 |
110 |
117 |
124 |
3 |
131 |
139 |
147 |
156 |
165 |
175 |
185 |
196 |
208 |
220 |
233 |
247 |
4 |
262 |
277 |
294 |
311 |
330 |
349 |
370 |
392 |
415 |
440 |
466 |
494 |
5 |
523 |
554 |
587 |
622 |
622 |
699 |
740 |
784 |
831 |
880 |
932 |
988 |
6 |
1047 |
1109 |
1175 |
1245 |
1319 |
1397 |
7480 |
7568 |
1661 |
1760 |
1865 |
1976 |
7 |
2093 |
2217 |
2349 |
2489 |
2637 |
2794 |
2960 |
3136 |
3322 |
3520 |
3729 |
3951 |
8 |
4186 |
4435 |
4699 |
4978 |
5274 |
5588 |
5920 |
6272 |
6645 |
7040 |
7459 |
7902 |
โอเค เรารู้ทุกอย่างแล้ว ไปเริ่มกันเลยดีกว่าครับ อธิบายโค้ดก่อนเลย ในโค้ดนี้หากเราใช้คำสั่งแบบง่ายที่สุด ก็เรียงไปเลย เช่น จะให้ขา 8 ส่งเสียง "ดี่ ดี๊ ดี" เสียงละ 1 วินาที ก็เขียน tone(8, ดี่, 1000); tone(8, ดี๊, 1000); tone(8, ดี, 1000); แต่หากเราทำแบบนี้กับทั้งเพลง อย่างเพลงหนูมาลีมีลูกแมวเหมียว มันมี 26 โน๊ต เราต้องเขียน 26 บรรทัด แล้วถ้าเราจะทำเพลงคุ๊กกี้เสี่ยงทาย โอ้โห เป็นร้อยเป็นพันโน๊ต เขียนเหนื่อยมากครับ เราจะสร้างทั้งเพลงขึ้นมาเป็น array ของโน๊ตเพลง และอีก array เป็น duration ของโน๊ตแต่ละตัว จากนั้นจึงใช้คำสั่ง for มา สมมติทำเพลงหนูมาลี มีโน๊ต 26 ตัว ก็ for 0 ถึง 25 รอบที่ 0 ก็เรียก array ที่ 0 จากทั้งโน๊ตเพลงและ duration มาแทนในคำสั่ง tone() ซึ่งเราใส่ไว้ภายใน for เท่านี้ก็จบครับ ทีนี้เพลงจะยาวเป็นชั่วโมงก็เขียนโค้ดแค่ไม่เกิน 10 บรรทัดนี้ เราจะไปแต่งเพลงตรงตัวแปรโน๊ตเพลงกับตัวแปร duration ที่เป็น array เอา (ใครยังงงเดี๋ยวลองดูในโค้ดตัวอย่างค่อย ๆ ทำความเข้าใจอีกทีนะครับ)
ในส่วนของ frequency ที่เราจะใส่ในคำสั่ง tone() หากใครแต่ง array เป็น {44, 740, 1397, 1661} อะไรแบบนี้ได้ก็ไม่มีปัญหา แต่ผู้เขียนจะแนะนำว่าเลขเยอะมันตาลายครับ เราจะแทนเป็นตัวโน๊ตไปเลย และจะอ้างอิงโน๊ตมาโดยคำสั่ง define เราจะสร้างไฟล์ขึ้นมาอีกไฟล์หนึ่งชื่อ pitches.h จากนั้นจึง #define NOTE_C4 262 อะไรแบบนี้ลงไปทุกตัว แล้ว include pitches.h ในไฟล์หลักของเราเพื่อนำมาใช้งาน (เหมือนกับการ include library เข้ามาใช้งานนั่นแหละครับ)
ทั้งนี้เจ้า pitches.h บางท่านไม่อยากสร้างก็ไม่จำเป็นนะครับ สามารถ #define NOTE ต่าง ๆ ในตัวโค้ดหลักเลยก็ได้เช่นกัน ก็ไม่ต้องไป include pitch.h แต่ก็จะทำให้โค้ดยาวมาก ๆ ฉะนั้นยังไงก็แนะนำให้สร้างแยกแล้ว include เข้ามาดีกว่า
ตอนที่เขียนบทความนี้ก็กลางเดือนพฤศจิกายน ผู้เขียนอยากจะใช้เพลงคริสต์มาสมาเป็นตัวอย่าง ซึ่งก็บังเอิญไปเจอโปรเจคของคุณ Joshi เขาทำไว้ตั้ง 3 เพลงแน่ะ เลยขอคัดลอกมาทำการดัดแปลง ใส่คำอธิบายภาษาไทยลงไปเลยก็แล้วกันครับ
วิธีการเพิ่ม pitches.h ด้วยการเพิ่ม tab ใหม่ ทำได้ด้วยการคลิกที่ลูกศรมุมขวาบน เลือก New tab หรือกดคีย์ลัด Ctrl+Shift+N
ที่แถบด้านล่างจะเป็นสีเหลือง และมีช่องให้ใส่ชื่อ ก็ใส่ "pitches.h" ลงไปแล้วกด OK (สำคัญ !! เราต้องใส่นามสกุลไฟล์ .h ลงไปด้วย หากใส่เฉพาะชื่อไฟล์ ไม่ได้ใส่นามสกุล .h tab นี้จะถูกเซฟเป็นนามสกุล .ino ทำให้ไม่สามารถ include "pitches.h" ได้เนื่องจากไม่มีไฟล์นั่นเอง)
ก็จะมี tab ชื่อ pitches.h ขึ้นมา เป็นอันจบการสร้าง tab ใหม่
ส่วน pitches.h ก็จะทำการ define ความถี่ของโน๊ตแต่ละตัวลงไปดังนี้เลย
หากเราไปทำโปรเจคอื่นก็สามารถก็อปปี้ไฟล์ pitches.h ไปใส่ในโฟลเดอร์ของโปรเจคใหม่ได้เลย

ต่อวงจรสวิตช์และ Buzzer กับบอร์ด Arduino อัพโหลดโค้ดลงไปในบอร์ดเป็นอันเสร็จพิธี

เพียงเท่านี้ก็จะได้ Arduino ที่ส่งเสียงเพลงเพราะ ๆ ให้เราได้ฟังกันแล้วหล่ะครับ กดปุ่มไหนก็ร้องเพลงนั้น ใครจะดัดแปลงให้ปุ่มเดียวกดวน หรือให้ร้องเพลงเดียววนไปเรื่อย ๆ ก็ลองดัดแปลงดู หรือจะเอาโน๊ตและจังหวะของเพลงอื่นมาแทนก็ได้ไม่ผิดกติกา จะเพลงวันเกิด เพลงลูกทุ่งลูกกรุง หรือจะทำไฟกระพริบไปด้วยก็ตามสบายเลยจ้าาาาาาาาา
Reference : Arduino Reference : tone() Arduino - ToneMelody Frequencies of Musical Notes