การต่อวงจรปุ่มกด (Button Switch) เพื่อรับสัญญาณ Digital และการเขียนโปรแกรมอ่านค่าปุ่มอย่างถูกต้องด้วยการใช้ Pull-up / Pull-down Resistor
🎯 จุดประสงค์การเรียนรู้
- อธิบายหลักการทำงานของสวิตช์กดติด-ปล่อยดับ (Push Button Switch) ได้
- อธิบายความแตกต่างของวงจร Pull-up และ Pull-down
- สามารถต่อวงจรปุ่มกดเข้ากับ ICON-32 และเขียนโปรแกรมอ่านค่าสัญญาณได้
- ป้องกันปัญหา Floating Input และการเด้งของสวิตช์ (Switch Bounce)
- ประยุกต์ใช้งานร่วมกับ LED เพื่อแสดงผลสถานะได้
🧩 อุปกรณ์ที่ใช้
| ลำดับ | รายการอุปกรณ์ | จำนวน | หมายเหตุ |
|---|---|---|---|
| 1 | บอร์ดไมโครคอนโทรลเลอร์ ICON-32 | 1 | (ESP32 compatible) |
| 2 | สวิตช์กดติดปล่อยดับ (Push Button) | 1 | แบบ 4 ขา หรือ 2 ขา |
| 3 | ตัวต้านทาน 10 kΩ | 1 | ใช้เป็น Pull-down resistor |
| 4 | ตัวต้านทาน 220 Ω | 1 | ต่อกับ LED |
| 5 | LED สีใดก็ได้ | 1 | แสดงผลสถานะ |
| 6 | สาย Jumper | 5–6 เส้น | สำหรับต่อบน Breadboard |
🧠 หลักการทำงานของสวิตช์ (Button Switch)
เมื่อเรากดปุ่ม สวิตช์จะเชื่อมต่อขา IN กับ VCC หรือ GND ทำให้บอร์ดอ่านได้ว่าเป็น HIGH (1) หรือ LOW (0)
แต่ถ้าไม่มีตัวต้านทาน “ดึง” ค่าให้คงที่เมื่อไม่กด →จะเกิดสถานะ “ลอย” (Floating) และค่าที่อ่านได้จะไม่แน่นอน
แก้ไขโดยใช้
- Pull-up Resistor: ดึงขา Input ขึ้นไปที่ VCC
- Pull-down Resistor: ดึงขา Input ลงไปที่ GND
⚙️ 1. การต่อวงจรแบบ Pull-down
🔌 การต่อวงจร

+3.3V ──┬─────────────┐
│ │
│ [Button]
[10kΩ] │
│ │
GND GPIO 4 (ICON-32)
- ขณะไม่กด → ขา GPIO ถูกดึงลง GND → อ่านค่า LOW
- ขณะกด → GPIO ต่อกับ +3.3 V → อ่านค่า HIGH
💻 โปรแกรมทดสอบ Pull-down
const int button = 4;
const int led = 2;
void setup() {
pinMode(button, INPUT);
pinMode(led, OUTPUT);
Serial.begin(115200);
}
void loop() {
int val = digitalRead(button);
digitalWrite(led, val);
Serial.println(val);
delay(100);
}
🔹 เมื่อกดปุ่ม → LED จะสว่าง
🔹 เมื่อปล่อยปุ่ม → LED ดับ
🍼 หลักการทำงานทีละขั้นตอน
จะแบ่งการทำงานเป็น 2 ส่วนหลัก ตามโครงสร้างของ Arduino/ESP32:
1. ส่วน const int (การประกาศตัวแปร)
const int button = 4;- กำหนดตัวแปรชื่อ
buttonให้มีค่าคงที่ (const) เป็น4 - หมายความว่า เราจะใช้ GPIO 4 ของ ESP32 เพื่อต่อกับสวิตช์ปุ่มกด
- กำหนดตัวแปรชื่อ
const int led = 2;- กำหนดตัวแปรชื่อ
ledให้มีค่าคงที่ (const) เป็น2 - หมายความว่า เราจะใช้ GPIO 2 (ซึ่งเป็นขาที่มี LED สีฟ้าติดอยู่บนบอร์ด ESP32 ส่วนใหญ่) เพื่อเป็น Output
- กำหนดตัวแปรชื่อ
2. ส่วน void setup() (ทำงานครั้งเดียวตอนเปิดเครื่อง)
pinMode(button, INPUT);- สั่งให้ ESP32 ตั้งค่าขา
button(GPIO 4) ให้เป็นโหมด รับค่า (Input)
- สั่งให้ ESP32 ตั้งค่าขา
pinMode(led, OUTPUT);- สั่งให้ ESP32 ตั้งค่าขา
led(GPIO 2) ให้เป็นโหมด ส่งค่า (Output)
- สั่งให้ ESP32 ตั้งค่าขา
Serial.begin(115200);- เปิดการสื่อสารแบบอนุกรม (Serial) ที่ความเร็ว 115200 bps เพื่อใช้ดูค่าผ่าน Serial Monitor ในคอมพิวเตอร์
3. ส่วน void loop() (ทำงานวนซ้ำไปเรื่อยๆ)
int val = digitalRead(button);- (สำคัญ) อ่านค่าดิจิทัล (สถานะ 0 หรือ 1) จากขา
button(GPIO 4) แล้วเก็บไว้ในตัวแปรชื่อval - ถ้าขานี้ได้รับไฟ (HIGH หรือ 3.3V)
valจะเท่ากับ1 - ถ้าขานี้ต่ออยู่กับกราวด์ (LOW หรือ 0V)
valจะเท่ากับ0
- (สำคัญ) อ่านค่าดิจิทัล (สถานะ 0 หรือ 1) จากขา
digitalWrite(led, val);- (สำคัญ) สั่งให้ขา
led(GPIO 2) ปล่อยสถานะตามค่าในตัวแปรval - ถ้า
valเป็น1(HIGH) -> LED จะติด - ถ้า
valเป็น0(LOW) -> LED จะดับ
- (สำคัญ) สั่งให้ขา
Serial.println(val);- ส่งค่า
val(ที่เป็น 0 หรือ 1) ไปแสดงผลที่ Serial Monitor เพื่อให้เราตรวจสอบได้
- ส่งค่า
delay(100);- หน่วงเวลา 100 มิลลิวินาที (0.1 วินาที) เพื่อให้โปรแกรมไม่ทำงานเร็วเกินไป ช่วยลดภาระการทำงานและทำให้อ่านค่าใน Serial Monitor ได้ง่ายขึ้น
⚙️ 2. การต่อวงจรแบบ Pull-up
ใน ICON-32 (ESP32) เราสามารถใช้ “ตัวต้านทาน Pull-up ภายในบอร์ด” ได้เลย
โดยไม่ต้องต่อต้านทานจริงจากภายนอก
🔌 การต่อวงจร

GPIO 4 ──[Button]───► GND
- ขณะไม่กด → ขา GPIO ถูกดึงขึ้นด้วย Pull-up ภายใน → HIGH
- ขณะกด → ต่อกับ GND → LOW
💻 โปรแกรมทดสอบ Pull-up
const int button = 4;
const int led = 2;
void setup() {
pinMode(button, INPUT_PULLUP); // เปิด Pull-up ภายใน
pinMode(led, OUTPUT);
Serial.begin(115200);
}
void loop() {
int val = digitalRead(button);
digitalWrite(led, !val); // กด = LED ติด
Serial.println(val);
delay(100);
}
🔹 กดปุ่ม = LOW (LED ติด)
🔹 ปล่อยปุ่ม = HIGH (LED ดับ)
⚡ 3. ปัญหาสัญญาณ “เด้ง” (Switch Bounce)
เมื่อกดปุ่มจริง สัญญาณอาจเด้ง HIGH-LOW หลายครั้งในไม่กี่มิลลิวินาที
ทำให้ไมโครคอนโทรลเลอร์เข้าใจว่ากดหลายครั้ง
💻 โปรแกรมแก้ด้วย Software Debounce
const int button = 4;
const int led = 2;
int ledState = LOW;
int buttonState = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
long debounceDelay = 50;
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(led, OUTPUT);
digitalWrite(led, ledState);
}
void loop() {
int reading = digitalRead(button);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
ledState = !ledState;
digitalWrite(led, ledState);
}
}
}
lastButtonState = reading;
}🍼 หลักการทำงานทีละขั้นตอน
โปรแกรมนี้แบ่งการทำงานใน loop() เป็น 3 ส่วนอย่างชัดเจน: 1. กันสั่น (Debounce), 2. ตรวจจับการเปลี่ยนแปลง (State Change), และ 3. อัปเดตความจำ (Update)
1. ส่วนประกาศตัวแปร (Global Variables)
ledState: จำสถานะ LED (LOWหรือHIGH)buttonState: “ความจำ” ของสถานะปุ่มที่ นิ่งแล้ว (Stable State)lastButtonState: “ความจำ” ของสถานะปุ่ม ดิบ (Raw State) ที่อ่านได้ในloopรอบที่แล้วlastDebounceTime,debounceDelay: ตัวแปรสำหรับจับเวลา Debounce (50ms)
2. ส่วน void setup()
pinMode(button, INPUT_PULLUP): ตั้งค่าขาปุ่มเป็น Input Pull-up (ปกติเป็นHIGH, กดแล้วเป็นLOW)pinMode(led, OUTPUT): ตั้งค่าขา LED เป็น OutputdigitalWrite(led, ledState): สั่งให้ LED เริ่มต้นในสถานะ “ดับ” (ตามค่าledState = LOW)
3. ส่วน void loop() (หัวใจของโปรแกรม)
int reading = digitalRead(button);- อ่านค่า “ดิบ” (Raw) จากปุ่มในรอบนี้ (อาจจะสั่นเป็น 0 หรือ 1 ก็ได้)
if (reading != lastButtonState)- “ตัวตรวจจับการสั่น”: “ค่าดิบ (
reading) รอบนี้ ไม่เหมือน ค่าดิบ (lastButtonState) รอบที่แล้วใช่ไหม?” - ถ้าใช่: แปลว่ามีการเปลี่ยนแปลงเกิดขึ้น (เริ่มกด, เริ่มปล่อย, หรือแค่สั่น)
- “ตัวตรวจจับการสั่น”: “ค่าดิบ (
lastDebounceTime = millis();- รีเซ็ตตัวจับเวลา ทันทีที่ตรวจพบการเปลี่ยนแปลง
if ((millis() - lastDebounceTime) > debounceDelay)- “ตัวตรวจสอบความเสถียร”: “เวลาผ่านไปนานเกิน 50ms โดยที่ ไม่มีการเปลี่ยนแปลงค่าดิบ (ตามข้อ 2) แล้วหรือยัง?”
- ถ้าใช่: แปลว่าค่า
readingที่อ่านได้ตอนนี้ “นิ่ง” และ “เสถียร” แล้ว
if (reading != buttonState)- “ตัวตรวจจับการเปลี่ยนแปลงสถานะ” (State Change Detector):
- (ทำงานต่อเมื่อผ่านข้อ 4 มาแล้ว)
- “สถานะที่นิ่งแล้ว (
reading) ไม่เหมือนกับ สถานะที่นิ่งที่เราจำไว้ (buttonState) ใช่หรือไม่?” - ถ้าใช่: แปลว่าสถานะ “นิ่ง” ได้เปลี่ยนไปแล้ว (เช่น จาก “ปล่อย” เป็น “กด” หรือ “กด” เป็น “ปล่อย”)
buttonState = reading;- อัปเดต “ความจำ” สถานะที่นิ่งแล้ว (
buttonState) ให้เป็นสถานะใหม่ทันที
- อัปเดต “ความจำ” สถานะที่นิ่งแล้ว (
if (buttonState == LOW)- ตรวจสอบว่าสถานะใหม่ที่นิ่งแล้วนั้น คือ “ถูกกด” (
LOW) ใช่หรือไม่ - ถ้าใช่: นี่คือ “จังหวะขอบขาลง” (Falling Edge) ที่เราตามหา!
ledState = !ledState;-> สลับค่า (Toggle) สถานะ LED ใน “ความจำ”digitalWrite(led, ledState);-> สั่งงาน LED จริง
- ตรวจสอบว่าสถานะใหม่ที่นิ่งแล้วนั้น คือ “ถูกกด” (
lastButtonState = reading;- (สำคัญมาก) อัปเดต “ความจำ” สถานะดิบ (
lastButtonState) ให้เป็นค่าปัจจุบัน (reading) - นี่คือการเตรียมพร้อมสำหรับ
loopรอบถัดไป เพื่อใช้เทียบในข้อ 2
- (สำคัญมาก) อัปเดต “ความจำ” สถานะดิบ (
✅ โปรแกรมนี้จะเปลี่ยนสถานะ LED ทุกครั้งที่กดปุ่มครั้งเดียว และป้องกันการเด้งของสวิตช์
📊 ตารางเปรียบเทียบ Pull-up vs Pull-down
| รายการ | Pull-up | Pull-down |
|---|---|---|
| ค่าเมื่อ “ไม่กด” | HIGH | LOW |
| ค่าเมื่อ “กด” | LOW | HIGH |
| ใช้ตัวต้านทานภายในได้ไหม | ✅ ใช้ได้ (INPUT_PULLUP) | ❌ ต้องต่อต้านทานภายนอก |
| การต่อปุ่มกับ | GND | VCC |
| ความนิยมใช้ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| แรงดันที่ใช้ | 3.3 V | 3.3 V |
📘 4. การทดลองเพิ่มเติม
1️⃣ เพิ่ม Serial Monitor แสดงข้อความ "Pressed" / "Released"
2️⃣ ใช้ LED 2 ดวงแสดงสถานะ ON / OFF
3️⃣ กดปุ่มค้าง → ให้ LED กระพริบต่อเนื่อง
4️⃣ ต่อ 2 ปุ่ม แล้วเขียนโค้ดควบคุม LED ซ้าย-ขวา
🧠 สรุป
| หัวข้อ | สรุป |
|---|---|
| Button Switch | ใช้ส่งสัญญาณควบคุม Digital (0/1) |
| Floating Input | ค่าสัญญาณไม่แน่นอนเมื่อไม่กด |
| Pull-up / Pull-down | ใช้ตัวต้านทานดึงค่าให้คงที่ |
| INPUT_PULLUP | ใช้ตัวต้านทานภายใน ESP32 |
| Debounce | หน่วงเวลาเพื่อป้องกันสัญญาณซ้ำ |
