ปุ่มกด Arduino Pull-up Resistor ทำไมต้องมี Pull-down ด้วย? อธิบายวงจรจริง ๆ
เตรียมของให้พร้อม!
โปรเจคนี้ต้องใช้: (1ชิ้น) NA376 ST-Link V2 mini STM8 STM32 Programer อุปกรณ์ Uploader และ Debugger downloader STLINK Arduino
ปุ่มกด Arduino Pull-up ทำไมต้องมี Pull-down ด้วย
พี่เคยเจอปัญหาเบอร์กดปุ่มบนบอร์ดแล้ว Arduino จับได้ทีละหลายครั้ง หรือไม่กดแต่ค่าขึ้น HIGH มั่ว ๆ บ้างไหม ถ้าเคย แสดงว่าเจอปัญหาจากขา Input ที่ไม่ได้ต่อ Pull-up หรือ Pull-down resistor พอดี วันนี้พี่จะอธิบายเรื่องนี้ให้เข้าใจจริง ๆ ว่าทำไมต้องมี ต่างกันยังไง และจะต่อวงจรยังไงให้ทำงานได้แบบไม่มีปัญหา
สิ่งที่ต้องเข้าใจก่อนเลยคือ ขา Input ของ Arduino มันไม่ได้ถูกต่ออะไรแน่นอนตอนไม่กดปุ่ม มันจะรับสัญญาณลอย ๆ (floating) อยู่ ค่าที่อ่านได้อาจเป็น HIGH หรือ LOW ก็ได้ขึ้นอยู่กับ noise รอบตัว Pull-up หรือ Pull-down resistor จึงเป็นตัวบังคับให้ได้ค่าที่แน่นอน
[image: ภาพเปรียบเทียบขา Input เมื่อไม่มี Pull resistor (ลอย) กับมี Pull-up]
Pull-up Resistor คืออะไร
Pull-up คือการต่อ resistor จากขา Input ขึ้นไปที่ VCC (5V) ผ่านปุ่มกดที่อีกข้างต่อกับ GND ตอนไม่กดปุ่ม กระแสจะไหลผ่าน resistor ไปที่ VCC ทำให้ขา Input ได้ค่า HIGH อยู่เสมอ เมื่อกดปุ่ม วงจรลัดลง GND ทำให้ขา Input ได้ค่า LOW ทันที
ข้อดีของ Pull-up คือตอนกดปุ่ม วงจรจะลง GND ซึ่งเป็น reference ที่เสถียร ทำให้อ่านค่าได้แม่นยำกว่า และถ้าใช้ INPUT_PULLUP ในโค้ด Arduino จะใช้ Pull-up ภายในบอร์ดได้เลยโดยไม่ต้องต่อ resistor ภายนอก ประหยัดอุปกรณ์ไปได้เยอะ
[image: วงจร Pull-up resistor พร้อมปุ่มกดต่อลง GND]
Pull-down Resistor คืออะไร
Pull-down ต่อ resistor จากขา Input ลงไปที่ GND แทน ปุ่มกดต่อไว้ที่ VCC ตอนไม่กดปุ่ม กระแสจะไหลลง GND ผ่าน resistor ทำให้ขา Input ได้ค่า LOW อยู่เสมอ เมื่อกดปุ่ม กระแสไหลจาก VCC เข้าขา Input ทำให้ได้ค่า HIGH
วิธีนี้ก็ใช้ได้ดีเหมือนกัน แต่ต้องระวังเรื่อง VCC reference ที่อาจไม่เสถียรเท่า GND ถ้าใช้แหล่งจ่ายไฟคุณภาพต่ำ อาจอ่านค่า HIGH ผิดพลาดได้บ่อยกว่า Pull-up
[image: วงจร Pull-down resistor พร้อมปุ่มกดต่อไว้ที่ VCC]
วงจร Pull-up ที่ใช้จริงในงาน
สำหรับวงจรที่พี่ใช้บ่อยในงานจริง จะใช้ Pull-up resistor ค่า 10kΩ ต่อขึ้นไปที่ 5V ของบอร์ด อีกข้างของปุ่มกดต่อลง GND ขา Input ต่อที่จุดระหว่าง resistor กับปุ่ม
5V -- 10kΩ --+-- INPUT PIN (Arduino)
|
BUTTON
|
GND
ส่วนกรณีที่ใช้ INPUT_PULLUP ภายในบอร์ด โค้ดจะง่ายขึ้นมาก ต่อปุ่มระหว่างขา Input กับ GND แล้วใช้โค้ดนี้ได้เลย:
const int BUTTON_PIN = 2;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP); // ใช้ Pull-up ภายใน
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
// กด = LOW, ไม่กด = HIGH
Serial.println(buttonState == LOW ? "PRESSED" : "RELEASED");
}
ข้อควรระวังตรงที่ตอนกดจะได้ค่า LOW นะ พี่เคยเขียนโค้ดผิดเพราะลืมเรื่องนี้ ต้อง invert ค่าเอาเองถ้าต้องการให้กดแล้วได้ HIGH
ทำไมต้อง 10kΩ
ค่า 10kΩ เป็นมาตรฐานที่ใช้กันทั่วไปมีเหตุผลหลายอย่าง ค่าต่ำกว่านี้เช่น 1kΩ จะมีกระแสไหลมากตอนกดปุ่ม (5V/1kΩ = 5mA) ซึ่งไม่จำเป็นและทำให้ปุ่มร้อนเร็ว ค่าสูงกว่านี้เช่น 100kΩ จะทำให้ขา Input รับ noise ได้ง่ายเพราะกระแสที่ไหลน้อยเกินไป
ถ้าเจอปัญหา noise เยอะ ๆ ในงานจริง เช่น ต่อมอเตอร์หรือ relay ด้วย อาจต้องลดค่า resistor ลงมาที่ 4.7kΩ หรือ 2.2kΩ แล้วแต่สภาพแวดล้อม สังเกตุง่าย ๆ ว่าถ้าอ่านค่ามั่ว ๆ ลองใส่ Pull-down เพิ่มอีกตัวที่ขา Input ช่วยได้ในหลายกรณี
[image: ภาพเปรียบเทียบขนาดกระแสที่ไหลผ่าน Pull resistor ค่าต่าง ๆ]
การแก้ปัญหา Debounce
นอกจากเรื่อง Pull resistor แล้ว ปุ่มกดจริง ๆ มีปัญหา debounce ด้วย คือตอนกดหรือปล่อย จะมีการสัมผัสหลายครั้งภายใน milliseconds เดียว ทำให้ Arduino จับได้หลายครั้ง
โค้ด debounce แบบง่ายที่พี่ใช้บ่อย:
const int BUTTON_PIN = 2;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const int DEBOUNCE_DELAY = 50;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
if (reading != lastButtonState) {
lastButtonState = reading;
Serial.println(reading == LOW ? "PRESSED" : "RELEASED");
}
}
}
DEBOUNCE_DELAY ที่ 50ms ใช้ได้ดีกับปุ่มกดทั่วไป ถ้าเป็นปุ่มคุณภาพต่ำอาจต้องเพิ่มเป็น 100ms แต่ถ้ามากเกินไป response จะช้าจนรู้สึกได้
สรุป
- Pull-up หรือ Pull-down resistor จำเป็นต้องมีเพื่อให้ขา Input อ่านค่าได้แน่นอน
- Pull-up ต่อที่ VCC กดได้ LOW ส่วน Pull-down ต่อที่ GND กดได้ HIGH
- ใช้ INPUT_PULLUP ในโค้ดจะไม่ต้องต่อ resistor ภายนอก
- ค่า 10kΩ เป็นมาตรฐาน ปรับลงถ้าเจอ noise
- อย่าลืม debounce ทุกครั้งถ้าไม่อยากให้กดทีเดียวแต่จับได้หลายครั้ง
ถ้าอยากลงมือทำโปรเจกต์ที่ใช้ปุ่มกดจริง ๆ แนะนำให้ลองทำตามโปรเจกต์ การใช้งาน Pushbuttons กับ Arduino จะได้เห็นภาพวงจรและโค้ดที่ทดสอบแล้ว หรือถ้าอยากรู้เรื่อง Input อื่น ๆ เพิ่มเติม 10 โปรเจค Arduino มือใหม่ ก็มีตัวอย่างหลากหลายให้ลองทำ
สำหรับใครที่อยากลองกับบอร์ดที่มี WiFi ในตัว ลองดูเรื่อง ESP32 ก็ได้ มีขา Input หลายตัวและใช้หลักการเดียวกันนี้ทั้งหมด
อยากทำโปรเจคแบบนี้?
รับทำโปรเจค Arduino / IoT จบงานไว ส่งงานครบ พร้อมสอน
หากต้องการ รับทำโปรเจคอาดูโน่ หรือระบบ IoT แบบเร่งด่วน สามารถดูรายละเอียดบริการได้ที่หน้าแรก
จ้างทำโปรเจคเลย