กลับไปหน้ารวมไฟล์
diy-arduino-based-continuous-touch-piano-b0b8e3.md

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

อยากเห็นขั้นตอนการทำแบบจบในคลิปเดียวมั้ย? ดูวิดีโอนี้เลย (สปีดแรงไปหน่อย)!

Making and demonstration of Touch Piano

ฟีเจอร์เด็ด:

  • เปียโนที่รับอินพุตจากการสัมผัส
  • เล่นความถี่ระหว่างคีย์สองปุ่มได้
  • ปรับช่วงความถี่ได้ตามชอบ
  • การตอบสนองต้องเร็วพอ (ห้ามช้าเป็นเต่า!)

มันทำงานยังไง?

ก่อนอื่น เราแยกปัญหาออกเป็นส่วนๆ แล้วค่อยแก้ทีละจุด สำหรับการทำเปียโนของเรา งานหลักๆ มีดังนี้:

  • วัด/ประมาณตำแหน่งที่สัมผัส: ตรงนี้เราไม่ได้ต้องการแค่ค่าสัมผัสเดียว แต่ต้องวัดตำแหน่งการสัมผัสหลายจุดที่เป็นค่าแบบอนาล็อกด้วย จะได้จัดการกับความถี่ระหว่างคีย์ได้ การทำงานนี้รวมถึงการรับข้อมูลจากคีย์และประมวลผลข้อมูลนั้น
  • คำนวณคีย์และความถี่: หลังจากได้ข้อมูลจากคีย์ทั้งหมดแล้ว เราต้องแมปค่าเหล่านั้นให้เป็นความถี่เฉพาะ เรารู้กันดีว่าความถี่ของเปียโนเพิ่มขึ้นแบบเรขาคณิต (Geometric progression) หมายความว่าต้องคูณด้วยตัวประกอบบางตัวเพื่อให้ได้ความถี่ของคีย์ถัดไป
  • สร้างเสียงและกำจัดสัญญาณรบกวน (ในข้อมูล): หลังจากคำนวณความถี่แล้ว เราต้องสร้างสัญญาณรูปคลื่นประมาณของความถี่นั้น นอกจากนี้ยังมีสัญญาณรบกวนที่อาจเกิดขึ้นเมื่อไม่ได้สัมผัส ซึ่งต้องกำจัดออกไป

หลักการทำงาน 1: การวัดตำแหน่งสัมผัส

เราจะใช้ capacitive touch สำหรับงานนี้ โดยจะใช้อาร์เรย์ของแผ่นโลหะหลายแผ่น แต่ละแผ่นจะทำหน้าที่เป็นเซ็นเซอร์สัมผัส

เซ็นเซอร์สัมผัสก็คือเซ็นเซอร์วัดความจุไฟฟ้า (capacitor sensor) นั่นแหละ เราจะวัดการเปลี่ยนแปลงของความจุไฟฟ้า (ซึ่งเกิดจากการสัมผัส) โดยใช้ Arduino เราใช้พินสองขา โดยต่อกับตัวต้านทาน (Resistor) ค่าสูง เราจะสั่งให้พินหนึ่งเป็นสถานะสูง (HIGH) และเริ่มจับเวลา เพื่อดูว่าอีกพินหนึ่งใช้เวลานานแค่ไหนถึงจะเปลี่ยนเป็นสถานะสูง เวลานี้ที่เราเรียกว่า "rise time" ขึ้นอยู่กับความจุไฟฟ้าและความต้านทาน ตรงนี้ความต้านทานคงที่ แต่ความจุไฟฟ้าจะแปรผันตามการสัมผัส

ข้อมูลเทคนิคเพิ่มเติม: โครงสร้างของ CapacitiveSensor.h

น้องจะเอาแผ่นฟอยล์อะลูมิเนียมไปเสียบตรงๆ เข้าขา Digital Input ของ Arduino ไม่ได้เด็ดขาด! มันจะ "ลอย" (float) สุดๆ แล้วอ่านค่าแบบมั่วๆ เอาได้ โปรเจคนี้ต้องใช้ขา Arduino 2 ขาสำหรับแต่ละ "คีย์" (Key) นะ: ขาส่ง (Sender Pin) และขารับ (Receiver Pin) จากนั้นก็ต่อตัวต้านทานค่าสูงๆ (เช่น 1 เมกะโอห์ม) ระหว่างสองขานั้น แล้วค่อยเอาแผ่นเทปทองแดงหรือฟอยล์อะลูมิเนียมไปต่อตรงๆ กับขารับ

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

long fleshReading = cs_4_2.capacitiveSensor(30); // ยิงพัลส์ความเร็วสูง 30 ลูก!
if (fleshReading > 500) {
  // ตรวจจับเนื้อหนังมนุษย์ได้! พัลส์ถูกทำให้ช้าลงโดยมวลชีวภาพ
  tone(8, 261); // เล่นโน้ต 'C4'
}

ในรูปตัวอย่าง เราทำคีย์ไว้ประมาณ 12 คีย์ และมีการสัมผัสที่บริเวณระหว่างแผ่นที่ 6 กับ 7 เนื่องจากเราต้องการข้อมูลแบบต่อเนื่อง และไม่สนใจแค่ว่ามันอยู่ที่คีย์ที่ 6 หรือ 7 แบบตายตัว แต่เราอยากรู้ตำแหน่งที่แน่นอนของการสัมผัสระหว่าง 6-7 มากกว่า ขั้นแรกคือหาคีย์ที่ตรวจจับการสัมผัสได้สูงสุดก่อน จากนั้นก็คำนวณตำแหน่งการสัมผัสระหว่างคีย์โดยใช้คณิตศาสตร์พื้นฐาน

หลักการทำงานส่วนที่ 2: การกำหนดความถี่และการสร้างเสียงโทน

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

สมการคำนวณความถี่ของโน้ต

ในฟังก์ชันด้านบน "n" คือเลขคีย์ ดังนั้นเมื่อใส่เลขคีย์เข้าไป เราก็จะคำนวณความถี่ได้

ตรงนี้เราจะแมปคีย์ที่ 1-18 (สมมติว่าบอร์ดเรามีแผ่นสัมผัส 18 แผ่น) ไปยังคีย์เป้าหมายใดๆ ก็ได้ที่เราต้องการ และเพราะอุปกรณ์เราเป็นแบบอนาล็อก เราไม่จำเป็นต้องจำกัดช่วงไว้แค่ 18 คีย์ แต่สามารถใช้ช่วงไหนก็ได้ ตัวอย่างเช่น ถ้าน้องอยากเล่นเสียงคีย์ที่ 40 ถึง 70 บนคีย์บอร์ดเป้าหมาย โดยแมปมันลงบนแผ่นสัมผัส 1-18 ของเรา แผ่นซ้ายสุดก็จะเล่นเสียงความถี่ของคีย์ที่ 40 และแผ่นขวาสุดจะเล่นเสียงความถี่ของคีย์ที่ 70

เราจะใช้ฟังก์ชัน tone() โดยตรงสำหรับสร้างความถี่ มันจะสร้างคลื่นสี่เหลี่ยม (square wave) ของความถี่ที่กำหนด เพื่อประสบการณ์ที่ดีขึ้น เราสามารถตั้งค่า duty cycle สำหรับควบคุมระดับเสียงตามแรงกดของการสัมผัสได้ด้วย

รายละเอียดเทคนิคเพิ่มเติม: การสร้าง Linear Synthesizer

เพราะว่าแผ่นเซ็นเซอร์ (sensing plates) เราตัดเป็นรูปร่างอะไรก็ได้ น้องเลยไม่ต้องยึดติดกับปุ่มกดแบบเดิมๆ เลย สร้างเป็นคีย์แบบสไลด์ต่อเนื่องไปเลยก็ได้โคตรเท่ โค้ดของเราก็จะถูกปรับให้แมปค่าจากแต่ละเซ็นเซอร์ไปเป็นโน้ตดนตรีเฉพาะ เช่น CapSensor1 จะเล่นความถี่ 261Hz (โน้ต C), CapSensor2 เล่น 293Hz (โน้ต D) ไปเรื่อยๆ แบบนี้เลย ผลลัพธ์ที่ได้คือซินธิไซเซอร์สุดล้ำ ที่เล่นเสียงเพลงได้ทันทีที่น้องลูบมือไปบนพื้นผิวเรียบๆ ที่มีลายวงจรโลหะซ่อนอยู่ข้างใต้!

ขั้นตอนที่ 1: เตรียมบอร์ด

เริ่มจากเอาไม้บล็อกมา แล้วติดฟอยล์อลูมิเนียมลงไป ไม่มีข้อจำกัดเรื่องขนาดนะ เอาเศษฟอยล์ส่วนเกินออก แล้วตัดให้เหลือประมาณ 30% ของความกว้างตามรูปที่ 4 พื้นที่ว่างตรงนี้แหละที่เราจะเอาไว้ติดตัวต้านทาน (Resistor)

ทีนี้ก็ทำเครื่องหมายห่างกัน 12mm ตามความยาวของบอร์ดเลย จะลองทำคีย์ให้เล็กลงกว่านี้เพื่อผลลัพธ์ที่ดีขึ้นก็ได้นะ หลังจากนั้นก็ตัดฟอยล์ตามเส้นที่ทำไว้ เราจะได้แผ่นแยกๆ กันหลายแผ่น ซึ่งจะเอาไว้ใช้เป็นคีย์สัมผัส (touch key/plates) จากนั้นก็ปิดทับฟอยล์อลูมิเนียมทั้งหมดด้วยเทปพลาสติก จะได้ไม่ต้องสัมผัสแผ่นโลหะโดยตรง

สำคัญมาก: แผ่นทุกแผ่น (ทุกคีย์) ต้องแยกวงจรไฟฟ้าออกจากกันนะจ๊ะ

ขั้นตอนที่ 2: ต่อวงจรไฟฟ้า

  • ตรวจสอบให้แน่ใจว่าแผ่นทุกแผ่นแยกจากกันจริงๆ ต้องไม่มีไฟฟาต่อถึงกันนะ ตรวจสอบทุกแผ่นหลังทำทุกขั้นตอนเลย
  • ต่อตัวต้านทาน 87K เข้ากับทุกแผ่น แล้วบัดกรีให้แน่นหนา
  • ต่อปลายอีกข้างของตัวต้านทานทุกตัวเข้าด้วยกัน (common) แล้วต่อเข้าไปที่ขา 4 ของ Arduino จากนั้นก็ดึงสายจากทุกแผ่น (ตรงปลายอีกข้างของตัวต้านทานที่ไม่ได้ต่อ common) ออกมา
  • ต่อขา 12 ของ Arduino เข้ากับลำโพง (speaker)

การเชื่อมต่อ:

  • KEY 1 ไปที่ A6
  • KEY 2 ไปที่ 13
  • KEY 3 ไปที่ A5
  • KEY 4 ไปที่ A4
  • KEY 5 ไปที่ A3
  • KEY 6 ไปที่ A2
  • KEY 7 ไปที่ A1
  • KEY 8 ไปที่ A7
  • KEY 9 ไปที่ 2
  • KEY 10 ไปที่ 3
  • KEY 11 ไปที่ 5
  • KEY 12 ไปที่ 6
  • KEY 13 ไปที่ 7
  • KEY 14 ไปที่ 8
  • KEY 15 ไปที่ 9
  • KEY 16 ไปที่ 10
  • KEY 17 ไปที่ 11

น้องจะต่อขาเองก็ได้นะ แต่ต้องจัดให้ค่าของคีย์ที่ 'i' ในอาร์เรย์ตรงกับ x[i] ให้ถูกต้องด้วยล่ะ วางแผนดีๆ หน่อย!

รายละเอียดทางเทคนิคเพิ่มเติม: เมทริกซ์สถาปัตยกรรมการสัมผัส

  • Arduino Uno/Nano: ความเร็วของโปรเซสเซอร์มาตรฐานทำงานได้พอดีกับคณิตศาสตร์จับเวลาพัลส์
  • ตัวต้านทานค่าสูง (87K ถึง 10M Ohm): จำเป็นมากๆ เพื่อให้ค่าคงที่ RC ช้าพอให้สัญญาณนาฬิกา 16MHz จับการเปลี่ยนแปลงเล็กน้อยจากความจุไฟฟ้าของร่างกายมนุษย์ได้
  • เทปทองแดงหรือฟอยล์อะลูมิเนียมหนาๆ: ทำหน้าที่เป็นแผ่นเซ็นเซอร์สัมผัสทางกายภาพ
  • ออดเพียโซหรือลำโพงแบบขยายสัญญาณ: ต่อกับขา Digital สำหรับสร้างโทนเสียง

ขั้นตอนที่ 3: เข้าใจโค้ด:

เริ่มแรกเลย น้องต้องติดตั้งไลบรารี CapacitanceSensor ก่อนนะ

1. กำหนดช่วงคีย์:

float N_min=48; float N_max=70;

ตรงนี้คือการเลือกช่วงของคีย์เปียโน ตัวอย่างในโค้ดนี้คือแมปคีย์ที่ 48 ถึง 70 ลงบนแผ่นเซ็นเซอร์ของเรา

2. การทำให้เรียบ (Smoothing):

int smooth=2;

ค่านี้คือค่าการทำให้เรียบ ยิ่งค่ามากก็ยิ่งลื่นไหล แต่ก็จะตอบสนองช้าลงหน่อยนะ เอาไว้ลดการกระตุกของค่าอ่าน

3. กำหนดขาเซ็นเซอร์ความจุ:

CapacitiveSensor   i20 = CapacitiveSensor(4,A6);
CapacitiveSensor   i13 = CapacitiveSensor(4,13);
.
.
.
CapacitiveSensor   i11 = CapacitiveSensor(4,11);

ส่วนนี้คือการกำหนดขาต่างๆ ให้เป็นอินพุตเซ็นเซอร์ โดยขา 4 เป็นขาส่งสัญญาณร่วม (common transmitter pin)

4. การแมปค่า:

N_map();

ฟังก์ชันนี้ทำหน้าที่แมปช่วงความถี่ตามค่า N_min และ N_max ลงบนแต่ละแผ่นเซ็นเซอร์

5. อ่านค่า: ฟังก์ชัน Read_val() นี้คือโค้ดที่อ่านค่าจากแต่ละแผ่นเซ็นเซอร์

x[1] =  i20.capacitiveSensor(30);
x[2] =  i13.capacitiveSensor(30);
 ..
x[18] =  i11.capacitiveSensor(30);

6. key_calc(): ฟังก์ชันนี้ทำการคำนวณหาคีย์ที่ถูกสัมผัสจากค่าต่ำสุดและสูงสุดของเซ็นเซอร์

for(int z=1;z<19;z++)
{ if(x[z]>t1){t1=x[z];t4=z;}

โค้ดส่วนนี้ตรวจจับแผ่นเซ็นเซอร์ที่มีค่าการสัมผัสสูงสุด

kt=((x[t4-1]*N[t4-1])+(x[t4]*N[t4])+(x[t4+1]*N[t4+1]))/(x[t4-1]+x[t4]+x[t4+1]);

สมการนี้เอาแผ่นที่มีค่าสูงสุดบวกกับแผ่นข้างเคียงมาคำนวณหาตำแหน่งสัมผัสที่แม่นยำและต่อเนื่อง โดยใช้ค่าเฉลี่ยถ่วงน้ำหนักของตำแหน่งและความเข้มของแต่ละแผ่น

7. freq_calc(): ทีนี้เราก็ต้องคำนวณความถี่ของคีย์นั้นๆ

float n;n=(key-49)/12;
freq=m*220*pow(2,n);

ตรงนี้ 'key' คือเลขคีย์ที่คำนวณได้ ส่วนตัวแปร m นี่มันจะกลายเป็น 1 ก็ต่อเมื่อค่าอินพุตจากการสัมผัสสูงพอ เอาไว้เป็น Noise Gate น่ะ ดังนั้นถ้าไม่มีใครแตะจริงจัง ค่าความถี่ก็จะเป็น 0

ขั้นตอนที่ 4: อัพโหลดโค้ดและดีบั๊ก

หลังจากอัพโหลดโค้ดแล้ว มันอาจจะทำงานหรือไม่ทำงานก็ได้ อย่าเพิ่งท้อนะ นี่คือปัญหาบางส่วนที่พี่เจอตอนทำโปรเจคนี้

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

เปียโนนี้อาจไม่ทำงานกับแบตเตอรี่ นะ เพราะขาดกราวด์ที่ดี มันจะทำงานได้สุดๆ ถ้าใช้ไฟจาก PC เพราะมีกราวด์ที่ชัดเจน

วิธีตรวจหาปัญหา:

  • เปิดฟังก์ชัน print_raw() แล้วลองแตะทุกแผ่นพร้อมกัน ดูซิว่าแผ่นไหนไม่ตอบสนอง
  • อัพโหลดโค้ดแบบอื่นเพื่อทดสอบแผ่นเซ็นเซอร์แต่ละแผ่นแบบตัวต่อตัวก็ได้

มาทำเปียโนกันเถอะ: ตอนจบ...

ข้อจำกัดของเจ้านี่ก็มีอยู่นะ:

  • เสียงมันฟังดูไม่หวานเท่าเปียโนจริงหรอก เพราะมันเป็นคลื่นสี่เหลี่ยม (square wave) ธรรมดา ในขณะที่เปียโนจริงๆ มันเป็นการผสมของฮาร์มอนิกหลายตัว
  • กดคีย์พร้อมกันหลายปุ่มไม่ได้นะตัวนี้ (ห้ามช็อตนะ!)
  • ความดังของเสียงมันปรับตามแรงกดไม่ได้ ตั้งไว้เท่าไหร่ก็เท่านั้น

ก็ลองปรับช่วงคีย์ (key range) กับค่าความลื่น (smoothness number) ตามสไตล์ตัวเองเลย แล้วก็ไปไล่หาตำแหน่งโน๊ตต่างๆ เอาไว้ จะได้เอาไปเล่นเพลงโปรดได้ สู้งานนะน้อง!

ข้อมูล Frontmatter ดั้งเดิม

apps:
  - "1x Arduino IDE"
author: "abhilashpatel121"
category: "Audio & Sound"
components:
  - "1x 17k Resistor"
  - "1x Wooden block"
  - "20x 87k resistor"
  - "1x Aluminium foil"
  - "1x Speaker: 0.25W, 8 ohms"
  - "1x Arduino Nano R3"
description: "Capacitive biological oscillators! Abandon physical push-buttons entirely by injecting raw, high-speed megahertz frequencies into sheets of copper tape, reading the micro-farad distortion caused when a human fingertip touches the metal."
difficulty: "Intermediate"
documentationLinks: []
downloadableFiles: []
encryptedPayload: "U2FsdGVkX19Qh6JjeetfreOr5BMGQD1AG2WK/m9MfmBYHoN/1B537g7eO97nkP/+w49b9+BeGjwU17uda8iaobpjDp7MB7e92vO/mDGFKZg="
heroImage: "https://cdn.jsdelivr.net/gh/bigboxthailand/arduino-assets@main/images/projects/diy-arduino-based-continuous-touch-piano-b0b8e3_cover.jpg"
lang: "en"
likes: 5
passwordHash: "86fe7d8abfb67ae766591f0822acbd46448697383ea34fd74f63178ad2c3747a"
price: 1999
seoDescription: "Build a DIY Arduino continuous touch piano that plays any frequency in a range. A fun music and coding project for Arduino enthusiasts."
tags:
  - "continuous"
  - "touch"
  - "keyboard"
title: "DIY: เปียโนสายช่าง! สร้างคีย์บอร์ด Arduino แบบกดค้างได้ งานง่ายแต่หล่อ"
tools: []
videoLinks:
  - "https://www.youtube.com/embed/vX1ChDaV6Uc"
views: 9144