ปุ่มสัมผัส บนชิ้นงานพิมพ์ 3 มิติ ด้วยขา touch ของ ESP32 กับ สีนำไฟฟ้า
ทำปุ่มแตะบนของเล่นพิมพ์ 3 มิติ ด้วยขา touch ของ ESP32 กับสีหรือฟิลาเมนต์นำไฟฟ้า ตั้งค่า threshold จาก baseline และจำไว้ว่า ESP32 ค่าลดเมื่อแตะ แต่ S2/S3 ค่าเพิ่ม
- ขา touch วัดความจุไฟฟ้า ไม่ต้องมีปุ่มกลไก แค่แผ่นนำไฟฟ้าต่อสายเข้าขาเดียวก็เป็นปุ่มได้
- ESP32 รุ่นแรกค่าที่อ่านได้ลดลงเมื่อแตะ ส่วน ESP32-S2 และ S3 ค่าเพิ่มขึ้น โค้ดต้องเช็กทิศให้ถูกรุ่น
- ตั้ง threshold จาก baseline ที่วัดตอนเปิดเครื่อง เป็นเปอร์เซ็นต์ ไม่ใช่ตัวเลขตายตัวจากเว็บอื่น
- ฟิลาเมนต์นำไฟฟ้ามีความต้านทานหลักพันโอห์ม ใช้ทำแผ่นสัมผัสได้ แต่ห้ามใช้เป็นสายจ่ายไฟ
อยากให้ของเล่นพิมพ์ 3 มิติมีปุ่มกดแบบไม่มีชิ้นส่วนขยับ ทำได้ด้วยขา touch ที่อยู่ในชิป ESP32 อยู่แล้ว ทาสีนำไฟฟ้าหรือพิมพ์ฟิลาเมนต์นำไฟฟ้าเป็นแผ่น ต่อสายเส้นเดียวเข้าขา touch แล้วอ่านค่าในโค้ด จุดที่คนพลาดบ่อยมีจุดเดียว: ESP32 รุ่นแรกค่าลดลงตอนแตะ แต่ ESP32-S2 กับ S3 ค่าเพิ่มขึ้น
บทนี้เป็นคู่มือวิธีทำ ยังไม่ใช่บันทึกงานที่ทำเสร็จแล้ว ตัวเลขทุกตัวในตัวอย่างใช้แสดงวิธีคำนวณ ค่าจริงบนบอร์ดของคุณต้องอ่านเองจาก Serial Monitor
ขา touch ทำงานยังไง
ขา touch วัดความจุไฟฟ้า (capacitance) ของแผ่นที่ต่ออยู่ ชิปชาร์จและคายประจุแผ่นนั้นซ้ำ ๆ แล้วนับเวลา พอนิ้วเข้ามาใกล้ ความจุเพิ่ม การชาร์จแต่ละรอบช้าลง ตัวเลขที่อ่านได้เลยเปลี่ยน ไม่มีหน้าสัมผัสกลไก ไม่ต้องมีสปริง ไม่ต้อง debounce แบบปุ่มกด (เทียบกับปุ่มกดธรรมดา)
ความต่างระหว่างรุ่นอยู่ที่วิธีรายงานตัวเลข เอกสาร ESP-IDF แบ่งเป็นสองเวอร์ชัน
| ESP32 (รุ่นแรก) | ESP32-S2 / ESP32-S3 | |
|---|---|---|
| เวอร์ชันวงจร touch | V1 | V2 |
| จำนวนขา touch | 10 ขา (T0–T9) | 14 ขา (GPIO1–GPIO14) |
| ตัวอย่างขา | GPIO4, 0, 2, 15, 13, 12, 14, 27, 33, 32 | GPIO1 ถึง GPIO14 |
| ค่าเมื่อแตะ | ลดลง | เพิ่มขึ้น |
ชนิดตัวแปรจาก touchRead() | uint16_t | uint32_t |
| interrupt ใน Arduino | ทำงานเมื่อค่าต่ำกว่า threshold | ทำงานเมื่อค่าสูงกว่า threshold |
ESP32-C3 ไม่มีวงจร touch ถ้าเลือกบอร์ดอยู่ ดูเทียบรุ่น ESP32 ก่อน
วัสดุทำแผ่นสัมผัส: สี หรือ ฟิลาเมนต์
มีสองทางหลัก ใช้ร่วมกันก็ได้
สีนำไฟฟ้า (conductive paint) เป็นสีที่ผสมคาร์บอน ทาบนหรือใต้ผิวชิ้นงานที่พิมพ์ด้วย PLA ธรรมดา เอกสารของผู้ผลิตรายหนึ่งระบุความต้านทานแผ่น (sheet resistance) ราว 55 Ω ต่อตาราง ที่ความหนาฟิล์ม 50 ไมครอน สีเป็นสูตรน้ำและละลายน้ำได้ และผู้ผลิตบอกว่าใช้กับไฟ DC แรงดันต่ำ กระแสน้อย งาน Fab Academy ชิ้นหนึ่งทาสีนำไฟฟ้าไว้ใต้ผิว PLA สีขาว แล้วใช้ขา T6 (GPIO14) ของ ESP32 อ่านการแตะผ่านพลาสติก
ฟิลาเมนต์นำไฟฟ้า (conductive PLA) เป็น PLA ผสมคาร์บอน พิมพ์เป็นแผ่นปุ่มตรง ๆ คู่กับสีอื่นในงานพิมพ์หลายสี ข้อมูลผู้ผลิตรายหนึ่งให้ค่า volume resistivity ไว้สามค่า
| สภาพ | volume resistivity |
|---|---|
| เนื้อวัสดุหล่อ (ไม่ได้พิมพ์) | 15 Ω·cm |
| พิมพ์แล้ว วัดตามแนวชั้น | 30 Ω·cm |
| พิมพ์แล้ว วัดข้ามชั้น (แกน Z) | 115 Ω·cm |
ข้ามชั้นแย่กว่าตามแนวชั้นเกือบ 4 เท่า เพราะรอยต่อระหว่างชั้นนำไฟได้ไม่ดีเท่าเนื้อเส้น ผู้ผลิตยังแนะนำพิมพ์ที่ 215–230 °C ค่อนไปทางสูง และวัสดุผสมคาร์บอนกัดหัวทองเหลือง (ดูเรื่องหัวพิมพ์)
| สีนำไฟฟ้า | ฟิลาเมนต์นำไฟฟ้า | |
|---|---|---|
| ต้องมีเครื่องหลายสีไหม | ไม่ต้อง | ต้องเปลี่ยนเส้นหรือมีระบบหลายเส้น |
| รูปทรงแผ่น | ทาได้ทุกผิว ขอบไม่คม | คมตามโมเดล |
| ความทน | ถลอกได้ ละลายน้ำได้ ควรเคลือบหรือซ่อนใต้ผิว | อยู่ในเนื้อชิ้นงาน |
| จุดต่อสาย | ทาสีทับปลายสาย | ฝังสายตอน pause หรือขันสกรูเข้าเนื้อ |
ตัวอย่างคำนวณ: ความต้านทานของเส้นนำไฟ
แผ่นปุ่มมักต้องมีเส้นนำไฟยาว ๆ จากผิวชิ้นงานไปถึงบอร์ด ลองคำนวณสองแบบ
แบบที่ 1 ฟิลาเมนต์นำไฟฟ้า เส้นยาว 50 mm กว้าง 5 mm หนา 1 mm วิ่งตามแนวชั้น
- แปลงหน่วยเป็นเซนติเมตร: ยาว 5 cm, หน้าตัด 0.5 cm × 0.1 cm = 0.05 cm²
- R = ρ × ยาว ÷ หน้าตัด = 30 × 5 ÷ 0.05 = 3,000 Ω
- ถ้าเส้นเดียวกันวิ่งขึ้นแนวตั้งข้ามชั้น ใช้ 115 แทน 30 ได้ 115 × 5 ÷ 0.05 = 11,500 Ω
แบบที่ 2 สีนำไฟฟ้า ทาหนาราว 50 ไมครอน ยาว 50 mm กว้าง 5 mm
- จำนวน “ตาราง” = ยาว ÷ กว้าง = 50 ÷ 5 = 10
- R = 55 × 10 = 550 Ω
ทั้งสองค่าใช้กับขา touch ได้ เพราะขา touch สนใจความจุ ไม่ได้ส่งกระแสผ่าน แต่ตัวเลขหลักพันโอห์มบอกชัดว่าวัสดุพวกนี้ไม่ใช่สายไฟ ห้ามใช้ส่งไฟเลี้ยงมอเตอร์หรือ LED กระแสสูง
ต่อวงจร
ต่อสายจากแผ่นสัมผัสเข้าขา touch หนึ่งขาต่อหนึ่งปุ่ม ไม่ต้องมีตัวต้านทานหรือกราวด์ที่แผ่น ขาที่ใช้บ่อย
- ESP32 รุ่นแรก: GPIO4 (T0), GPIO14 (T6), GPIO27 (T7), GPIO32/33 (T9/T8)
- ESP32-S3: GPIO1 ถึง GPIO14 เลือกขาที่บอร์ดไม่ได้เอาไปใช้อย่างอื่น
เดินสายจากแผ่นถึงบอร์ดให้สั้นและอยู่ห่างสายมอเตอร์หรือลำโพง สายยาวเองก็เป็นส่วนหนึ่งของ “แผ่น” ที่วัด ถ้าจับสายแล้วปุ่มทำงาน แปลว่าสายยาวหรืออยู่ใกล้มือเกินไป
โค้ดที่ใช้ได้ทั้ง ESP32 และ S3
หลักคือวัด baseline ตอนเปิดเครื่องโดยยังไม่มีใครแตะ แล้วดูว่าค่าขยับออกจาก baseline เกินกี่เปอร์เซ็นต์ ทิศของการขยับเลือกตามรุ่นชิปด้วย macro ของ ESP-IDF
// Arduino-ESP32, ESP32 รุ่นแรก หรือ ESP32-S3
const int PAD_PIN = 4; // T0 บน ESP32, GPIO4 (TOUCH4) บน S3
const float CHANGE = 0.20; // ต้องเปลี่ยน 20% ถึงนับว่าแตะ
uint32_t baseline = 0;
void setup() {
Serial.begin(115200);
delay(500); // มืออย่าเพิ่งแตะ
for (int i = 0; i < 32; i++) { baseline += touchRead(PAD_PIN); delay(10); }
baseline /= 32;
Serial.printf("baseline=%u\n", baseline);
}
bool touched(uint32_t v) {
#if CONFIG_IDF_TARGET_ESP32
return v < baseline * (1.0 - CHANGE); // V1: ค่าลดเมื่อแตะ
#else
return v > baseline * (1.0 + CHANGE); // V2 (S2/S3): ค่าเพิ่มเมื่อแตะ
#endif
}
void loop() {
uint32_t v = touchRead(PAD_PIN);
Serial.printf("%u %s\n", v, touched(v) ? "TOUCH" : "");
delay(50);
}
ตัวอย่างการตั้ง threshold สมมุติ ESP32 รุ่นแรกอ่าน baseline ได้ 90 (งาน Fab Academy ที่อ้างถึงรายงานค่าว่างราว 90 และค่าลดลงเมื่อแตะ)
- threshold = 90 × (1 − 0.20) = 72
- อ่านได้ 85 = ไม่แตะ, อ่านได้ 45 = แตะ
บน S3 ตัวเลขใหญ่กว่ามากและทิศกลับกัน สมมุติ baseline 30,000 threshold = 30,000 × 1.20 = 36,000 ค่าที่สูงกว่านี้นับว่าแตะ ตัวเลข 30,000 เป็นตัวอย่างการคำนวณเท่านั้น ให้ดูค่าจริงจาก Serial Monitor แล้วปรับ CHANGE จนแตะเบา ๆ ติด แต่วางมือใกล้ ๆ ไม่ติด
ถ้าโค้ดจากเน็ตใช้ได้บน ESP32 แต่บน S3 ปุ่ม “ติดค้าง” ตลอด แทบทุกครั้งคือเงื่อนไข
<กับ>สลับกัน
ออกแบบชิ้นงานให้แตะติดง่าย
- แผ่นใหญ่พอนิ้ว แผ่นที่ใหญ่กว่าปลายนิ้วเล็กน้อยให้การเปลี่ยนแปลงชัดกว่าจุดเล็ก ๆ
- ผนังทับบาง ถ้าซ่อนสีหรือแผ่นนำไฟฟ้าไว้ใต้ผิว ยิ่งบางยิ่งไว พิมพ์ชิ้นทดสอบความหนาต่างกันสัก 3 ระดับแล้วเทียบตัวเลข
- เว้นระยะระหว่างปุ่ม ปุ่มชิดกันเกินไปแตะปุ่มหนึ่งอีกปุ่มขยับตาม
- จุดต่อสายต้องแน่น สายหลวมทำให้ค่ากระโดด ฝังปลายสายลงในช่องตอนหยุดพิมพ์ หรือทาสีทับปลายสายที่ปอกแล้วจนมิด
ข้อผิดพลาดที่เจอบ่อย
- ใช้ threshold ตายตัวจากบทความอื่น ค่าเปลี่ยนตามขนาดแผ่น สาย และไฟเลี้ยง ต้องวัด baseline เอง
- ลืมว่า S2/S3 กลับทิศ ใช้เงื่อนไขของ ESP32 รุ่นแรกบน S3 ปุ่มจะไม่ทำงานหรือค้าง
- ซื้อบอร์ด C3 มาทำปุ่มสัมผัส C3 ไม่มีวงจร touch
- ใช้ฟิลาเมนต์นำไฟฟ้าเป็นสายจ่ายไฟ ความต้านทานหลักพันโอห์มทำให้ไฟตกและร้อน ใช้ทำแผ่นสัมผัสหรือสัญญาณกระแสน้อยเท่านั้น
- แตะตอนเปิดเครื่อง baseline ผิดตั้งแต่ต้น ปุ่มจะเพี้ยนทั้งรอบการใช้งาน
งานนี้อยู่ที่ไฟ 3.3 V จากบอร์ดเท่านั้น สีและฟิลาเมนต์นำไฟฟ้าออกแบบมาสำหรับไฟต่ำ อย่าต่อกับไฟบ้านหรืออุปกรณ์ที่เสียบปลั๊ก
แหล่งข้อมูล
- Capacitive Touch Sensor (ESP32-S2) — ESP-IDF Programming Guide
- Capacitive Touch Sensor (ESP32) — ESP-IDF Programming Guide
- Touch API — Arduino-ESP32 documentation
- Project development (touch pod with conductive paint) — Fab Academy 2023, Barcelona
- Electric Paint Technical Data Sheet — Bare Conductive (via SparkFun)
- Conductive PLA product data — MatterHackers
คำถามที่พบบ่อย
ESP32-C3 หรือ C6 ใช้ทำแบบนี้ได้ไหม
ไม่ได้ด้วยวิธีนี้ เพราะ C3 ไม่มีวงจร touch ในชิป ให้ใช้ ESP32 รุ่นแรก ESP32-S2 หรือ ESP32-S3 ซึ่งมีขา touch ในตัว
แตะผ่านพลาสติกได้ไหม ต้องโดนสีตรง ๆ หรือเปล่า
แตะผ่านผนังพลาสติกบาง ๆ ได้ แต่ยิ่งผนังหนา ค่าที่เปลี่ยนตอนแตะยิ่งน้อย ให้พิมพ์ชิ้นทดสอบหลายความหนาแล้วดูตัวเลขใน Serial Monitor ก่อนออกแบบชิ้นจริง
ทำไมเสียบ USB กับใช้แบตแล้วค่าไม่เท่ากัน
ค่าความจุรอบตัวเปลี่ยนตามการต่อกราวด์และสิ่งรอบข้าง เลยต้องวัด baseline ใหม่ทุกครั้งที่เปิดเครื่อง แทนการฝังตัวเลขไว้ในโค้ด
วงจรและโค้ดในบทความทดสอบกับบอร์ดตัวอย่าง บอร์ดต่างรุ่นอาจใช้ขาต่างกัน ตรวจ pinout ของบอร์ดที่ใช้ก่อนต่อไฟเสมอ