สอนใช้ Arduino เช็คสถานะปุ่มกด (Push Button) หรือสวิตซ์ (Switch)
ปุ่มกด (Push Button) หรือสวิตซ์ (Switch) เป็นอุปกรณ์พื้นฐานที่ใช้กันทั่วไปในหลายๆ โปรเจค เพื่อเชื่อมจุด 2 จุดในวงจรให้ถึงกัน มักใช้เพื่อรับข้อมูลจากผู้ใช้ เช่น เมื่อผู้ใช้กดปุ่มให้อุปกรณ์ที่ต่อพ่วงเริ่มทำงาน หรืออาจจะรับสัญญาณจากกลไกต่างๆ เช่น เมื่อวัตถุเคลื่อนที่มาถึงลิมิตสวิตซ์ (Limit Switch) ให้เครื่องจักรหยุดทำงาน เป็นต้น นอกจากนี้ยังสามารถใช้ความรู้นี้ไปประยุกต์ต่อกับเซ็นเซอร์ (Sensor) บางประเภทได้อีกด้วย แต่อย่างไรก็ตามในบทความนี้จะเน้นไปที่การใช้สวิตซ์กดแบบธรรมดาครับ
อุปกรณ์ที่ต้องใช้
- x1 บอร์ด Arduino (หรือบอร์ดอื่นๆ ที่คล้ายกัน)
- x1 สวิตซ์ (Switch)
- x1 ตัวต้านทาน (Resistor) 4.7 – 10K kΩ (ค่าใดก็ได้)
- x1 สายไฟจั๊มเปอร์
- x1 บอร์ดทดลอง (Breadboard)
วิธีต่อวงจร
เราจะต่อสวิตซ์เพื่อใช้งานกับ Arduino โดยใช้การต่อวงจรที่เรียกว่า Pull-Up Resistor หรือ Pull-Down Resistor อย่างใดก็ได้ เพื่อป้องกันไม่ให้ขา Input อยู่ในสถานะ Floating จนอ่านค่าจากขา Input มาใช้งานไม่ได้
*** Floating เป็นสถานะที่ขา Input ของ MCU ไม่ได้ต่ออยู่กับ VCC หรือ GND อย่างใดอย่างหนึ่งเลย ทำให้เมื่ออ่านค่าจากขา Input นั้น จะได้ค่าออกมาในลักษณะสุ่มระหว่าง LOW และ HIGH แบบไม่สามารถคาดเดาได้ ***
โดยความแตกต่างในด้านการใช้งานของทั้ง 2 วงจรนี้ คือ
- Pull-Up Resistor
- ไม่ได้กดปุ่ม จะอ่านค่าได้เป็น HIGH
- กดปุ่ม จะอ่านค่าได้เป็น LOW
- Pull-Down Resistor
- ไม่ได้กดปุ่ม จะอ่านค่าได้เป็น LOW
- กดปุ่ม จะอ่านค่าได้เป็น HIGH
ตรงจุดนี้สามารถเลือกใช้ได้ตามความเหมาะสมนะครับ ว่าอยากได้สถานะตอนกดปุ่มเป็น HIGH หรือเป็น LOW ส่วนการต่อวงจรก็ตามภาพด้านล่างเลยครับ
Internal Pull-Up Resistor
นอกเหนือจากการต่อวงจร 2 แบบที่ได้อธิบายไว้ด้านบนแล้ว บอร์ด Arduino หรือบอร์ดอื่นๆ ที่คล้ายกันบางบอร์ด เขาก็ได้ติดตั้งวงจร Pull-Up Resistor มาให้เราในตัวบอร์ดแล้ว (เรียกว่า Internal Pull-Up Resistor) โดยที่เราไม่ต้องหาตัวต้านทานจากภายนอกมาต่อเพิ่ม มีแค่สวิตซ์อย่างเดียวเราก็สามารถต่อวงจรใช้งานได้แล้ว วิธีการต่อวงจรทำได้โดยต่อขาด้านหนึ่งของสวิตซ์เข้ากับขา Input ส่วนขาอีกด้านหนึ่งต่อเข้ากับ GND ซึ่งคล้ายกับการต่อ Pull-Up Resistor แบบปกติ แต่ต่างกันตรงที่ Resistor ถูกต่อแบบ Pull-Up มาให้ในตัวบอร์ดเรียบร้อยแล้ว
โค้ดโปรแกรมอย่างง่าย (เพื่อความเข้าใจ)
ตัวอย่างนี้จะเป็นโค้ดโปรแกรมอย่างง่ายที่สุด สำหรับอ่านค่าจากขา Input (ในที่นี้เป็นขา 2) และเมื่ออ่านค่าจากขา Input ได้เป็น HIGH ไฟที่ LED ติด แต่ถ้าอ่านค่าได้เป็น LOW ไฟที่ LED ดับ (ในที่นี้ใช้ built-in LED ของ Arduino UNO ซึ่งอยู่ที่ขา 13)
โดยโค้ดนี้ใช้ได้กับทั้งวงจร Pull-Up Resistor และ Pull-Down Resistor ซึ่งให้ผลลัพธ์การทำงานที่แตกต่างกันดังนี้
- Pull-Up Resistor หรือ Internal Pull-Up Resistor
- ไม่ได้กดปุ่ม จะอ่านค่าได้เป็น HIGH (ไฟที่ LED ติด)
- กดปุ่ม จะอ่านค่าได้เป็น LOW (ไฟที่ LED ดับ)
- Pull-Down Resistor
- ไม่ได้กดปุ่ม จะอ่านค่าได้เป็น LOW (ไฟที่ LED ดับ)
- กดปุ่ม จะอ่านค่าได้เป็น HIGH (ไฟที่ LED ติด)
หมายเหตุ : หากต้องการใช้งาน Internal Pull-Up Resistor ให้แทนที่คำสั่ง pinMode(buttonPin, INPUT) ด้วย pinMode(buttonPin, INPUT_PULLUP)
/*
* code from : http://www.arduino.cc/en/Tutorial/Button
* description : button example with comment removed (easier to read)
*/
const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
โค้ดโปรแกรมแบบใช้ไลบรารี Bounce2 (เพื่อใช้งานจริง)
โค้ดโปรแกรมก่อนหน้าเป็นเพียงการใช้งานฟังก์ชั่น digitalRead() อ่านค่าแบบธรรมดาๆ ไม่ได้ป้องกันการ bounce ของสวิตซ์เอาไว้เลย ซึ่งอาจก่อให้เกิดปัญหาขณะใช้งานจริงได้
วิธีแก้ไขคือ เราต้องเขียนโค้ดโปรแกรมเพื่อ debounce โดยผมแนะนำให้ใช้ไลบรารีชื่อ Bounce2 เพื่อให้โค้ดโปรแกรมของเราบำรุงรักษาได้ง่าย และง่ายต่อการนำกลับมาใช้ซ้ำในโปรเจคอื่นๆ (สามารถศึกษาวิธีติดตั้งไลบรารีได้ที่นี่)
*** การ bounce ของสวิตซ์ คือการสั่นของสวิตซ์ ทำให้เกิดสัญญาณดิจิตอลไปที่ขา Input หลายครั้งในการกดสวิตซ์เพียงครั้งเดียว จนส่งผลให้ระบบทำงานผิดพลาดเนื่องจากระบบจะเข้าใจว่าสวิตซ์ถูกกดหลายครั้งนั่นเอง ส่วนการป้องกันการ bounce เราจะถูกเรียกว่าการ debounce ***
ตัวอย่างโค้ดโปรแกรมเมื่อใช้งานไลบรารี Bounce2
/*
* code from : https://github.com/thomasfredericks/Bounce2
* description : Translate comment to thai.
*/
#include <Bounce2.h>
#define BUTTON_PIN 2
#define LED_PIN 13
int ledState = LOW;
Bounce debouncer = Bounce(); // สร้าง debouncer object
void setup() {
// กำหนดให้ debouncer object ใช้ BUTTON_PIN ในโหมด INPUT_PULLUP (จะแก้เป็น INPUT, INPUT_PULLUP หรือ OUTPUT ก็ได้ขึ้นอยู่กับการต่อวงจร)
debouncer.attach(BUTTON_PIN, INPUT_PULLUP);
debouncer.interval(25); // กำหนดเวลาการเปลี่ยนสถานะให้กับ debouncer object ที่ 25 มิลลิวินาที
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, ledState);
}
void loop() {
debouncer.update(); // อัปเดตสถานะให้กับ debouncer object
// กำหนดเงื่อนไขให้โค้ดโปรแกรมในวงเล็บปีกกาทำงานเมื่อสถานะปุ่มกดเปลี่ยนจาก HIGH เป็น LOW โดยเช็คจากฟังก์ชั่น fell()
// หากต้องการเช็คสถานะจาก LOW เป็น HIGH ให้แทนที่ฟังก์ชั่น fell() ด้วยฟังก์ชั่น rose()
if ( debouncer.fell() ) {
ledState = !ledState; // สลับสถานะติด/ดับของ LED
digitalWrite(LED_PIN, ledState); // สั่งให้ LED ติด หรือดับ
}
}
สรุป
- การต่อสวิตซ์เพื่อใช้งานกับ Arduino หรือไมโครคอนโทรลเลอร์ (MCU) จำเป็นต้องต่อวงจรแบบ Pull-Up Resistor หรือ Pull-Down Resistor เพื่อป้องกันไม่ให้ขา Input อยู่ในสถานะ Floating จนอ่านค่ามาใช้งานไม่ได้
- บอร์ดบางตัวจะติดตั้ง Pull-Up Resistor มาให้แล้วในตัวบอร์ดเรียบร้อยแล้ว (เรียกว่า Internal Pull-Up Resistor) แปลว่าเราสามารถใช้งานวงจรแบบ Pull-Up Resistor ได้ทันทีโดยที่ไม่ต้องต่อ Resistor เพิ่มจากภายนอก
- การเขียนโค้ดโปรแกรมเพื่อ debounce แนะนำให้ใช้ไลบรารีแทนการเขียนด้วยตัวเอง เพราะบำรุงรักษาง่ายกว่า และนำไปใช้ซ้ำในโปรเจคอื่นได้ง่ายกว่า
- การ debounce ด้วยการต่อวงจรก็สามารถทำได้ เพียงแต่ไม่ได้ถูกพูดถึงในบทความนี้ครับ
ข้อมูลเพิ่มเติม
- Electronics Hub – Types Of Switches
- Arduino – Button
- Arduino – Digital Pins
- Arduino – Input Pullup Serial
- Arduino Forum – INPUT or INPUT_PULLUP
- StackExchange – What’s the difference between INPUT and INPUT_PULLUP?