KỸ THUẬT CHỐNG NHIỄU CHO NÚT NHẤN
Rung phím hay rung nút bấm là gì?
Khi bạn nhấn nút, công tắc, hai bộ phận kim loại chạm vào nhau. Đối với người sử dụng, nó có vẻ như tiếp xúc ngay lập tức. Nhưng không phải như vậy. Khi bạn nhấn công tắc, ban đầu nó sẽ tiếp xúc với nhũng vùng kim loại khác (có thể gọi là tiếp xúc chưa hoàn toàn), nhưng chỉ trong một khoảng thời gian cực ngắn, cỡ vài micro giây. Quá trình diễn ra dần dần cho đến khi tiếp xúc hoàn toàn.
Do phần cứng phản xạ cực nhanh với các tiếp xúc, nên khi trong quá trình nhấn nút như trên thì phần cứng nó hiểu rằng bạn nhấn công tắc nhiều lần. Đây chính là hiện tượng rung phím bấm.
Dưới đây sẽ là một minh họa cụ thể về hiện tượng này.
Như hình trên thì bạn có thể hoàn toàn thấy rằng trước khi nút nhấn tiếp xúc hoàn toàn thì trước đó tồn tại các tín hiệu đã tích cực trong một khoảng thời gian ngắn dẫn tới hiện tượng rung phím.
Mỗi một nút bấm có những đặc điểm riêng về hiện tượng rung phím. Để có thể có những so sánh khách quan tôi lấy ví dụ với 4 loại nút bấm. Tôi có 2 công tắc micro, 1 nút nhấn, và công tắc bật tắt:
Chống rung nút nhấn bằng phần cứng
Dưới đây tôi lấy một ví dụ: Với mỗi lần nhấn nút thì đèn LED sẽ sáng lần lượt. Tôi sử dụng nút nhấn với sơ đồ nguyên lý dưới đây.
Với cách nối thông thường này thì sẽ xảy ra hiện tượng rung phím, nó thể hiện rõ ở hình ảnh sau:
Điều đó cho thấy, khi bạn nhấn nút LED sáng rất khó chịu, nó không tuân thủ theo những gì bạn làm. Để khắc phục điều đó bạn hãy thêm 1 tụ gốm như hình sau.
Sau khi thêm 1 tụ gốm 0.1uF thì hiện tượng trên đã được khắc phục rất rõ nét và gần như không bị hiện tượng này nữa.
Chống rung nút nhấn bằng phần mềm
Khi làm việc với vi điều khiển, chúng ta có thể khắc phục hiện tượng này và điều đó làm cho giảm thiểu được phần cứng, tiết kiệm chi phí. Đa phần các lập trình viên sẽ thêm một trễ khoảng 50ms sau mỗi lần nhấn nút. Điều này làm cho vi điều khiển phải chờ một khoảng thời gian 50ms và sau đó mới tiếp tục với chương trình. Đây không phải là một giải pháp tốt, vì vi điều khiển mất một khoảng thời gian để đợi.
Một cách khác là sử dụng ngắt để khắc phục hiện tượng rung phím này. Sau đây là một phần mềm mã debounce đơn giản cho Arduino.
/* SoftwareDebounce | |
* | |
* At each transition from LOW to HIGH or from HIGH to LOW | |
* the input signal is debounced by sampling across | |
* multiple reads over several milli seconds. The input | |
* is not considered HIGH or LOW until the input signal | |
* has been sampled for at least "debounce_count" (10) | |
* milliseconds in the new state. | |
* | |
* Notes: | |
* Adjust debounce_count to reflect the timescale | |
* over which the input signal may bounce before | |
* becoming steady state | |
* | |
* Based on: | |
* http://www.arduino.cc/en/Tutorial/Debounce | |
* | |
* Jon Schlueter | |
* 30 December 2008 | |
* | |
* http://playground.arduino.cc/Learning/SoftwareDebounce | |
*/ | |
int inPin = 7; // the number of the input pin | |
int outPin = 13; // the number of the output pin | |
int counter = 0; // how many times we have seen new value | |
int reading; // the current value read from the input pin | |
int current_state = LOW; // the debounced input value | |
// the following variable is a long because the time, measured in milliseconds, | |
// will quickly become a bigger number than can be stored in an int. | |
long time = 0; // the last time the output pin was sampled | |
int debounce_count = 10; // number of millis/samples to consider before declaring a debounced input | |
void setup() | |
{ | |
pinMode(inPin, INPUT); | |
pinMode(outPin, OUTPUT); | |
digitalWrite(outPin, current_state); // setup the Output LED for initial state | |
} | |
void loop() | |
{ | |
// If we have gone on to the next millisecond | |
if(millis() != time) | |
{ | |
reading = digitalRead(inPin); | |
if(reading == current_state && counter > 0) | |
{ | |
counter--; | |
} | |
if(reading != current_state) | |
{ | |
counter++; | |
} | |
// If the Input has shown the same value for long enough let's switch it | |
if(counter >= debounce_count) | |
{ | |
counter = 0; | |
current_state = reading; | |
digitalWrite(outPin, current_state); | |
} | |
time = millis(); | |
} | |
} |
view rawArduino hosted with ❤ by GitHub
Đoạn mã trên được viết trên Arduino IDE.
Dưới đây là đoạn mã viết cho 2 đèn LED với vi điều khiển PIC
// INCLUDES | |
#include | |
#include | |
#include | |
// CONFIG | |
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) | |
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) | |
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) | |
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) | |
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) | |
#pragma config LVP = ON // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled) | |
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) | |
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) | |
// DEFINITIONS | |
#define _XTAL_FREQ 4000000 | |
#define LED1 PORTBbits.RB3 | |
#define LED2 PORTBbits.RB2 | |
#define BTN PORTBbits.RB5 | |
// VARIABLES | |
char BTN_pressed = 0; | |
char BTN_press = 0; | |
char BTN_release = 0; | |
char Bouncevalue = 500; | |
// MAIN PROGRAM | |
int main(int argc, char** argv) { | |
// Comparators off | |
CMCON = 0x07; | |
// Port directions, RB5 input, the rest is output | |
TRISA = 0b00000000; | |
TRISB = 0b00100000; | |
// Port state, all low | |
PORTA = 0b00000000; | |
PORTB = 0b00000000; | |
// Starting with LED1 high and LED2 low | |
LED1 = 1; | |
LED2 = 0; | |
while (1) | |
{ | |
// If BTN is pressed | |
if (BTN == 1) | |
{ | |
// Bouncing has started so increment BTN_press with 1, for each "high" bounce | |
BTN_press++; | |
// "reset" BTN_release | |
BTN_release = 0; | |
// If it bounces so much that BTN_press is greater than Bouncevalue | |
// then button must be pressed | |
if (BTN_press > Bouncevalue) | |
{ | |
// This is initial value of BTN_pressed. | |
// If program gets here, button must be pressed | |
if (BTN_pressed == 0) | |
{ | |
// Toggle the LEDs | |
LED1 ^= 1; | |
LED2 ^= 1; | |
// Setting BTN_pressed to 1, ensuring that we will | |
// not enter this code block again | |
BTN_pressed = 1; | |
} | |
// LEDs toggled, set BTN_pressed to 0, so we can enter | |
// toggle code block again | |
BTN_press = 0; | |
} | |
} | |
else | |
{ | |
// Increment the "low" in the bouncing | |
BTN_release++; | |
BTN_press = 0; | |
// If BTN_release is greater than Bouncevalue, we do not have a | |
// pressed button | |
if (BTN_release > Bouncevalue) | |
{ | |
BTN_pressed = 0; | |
BTN_release = 0; | |
} | |
} | |
} | |
return (EXIT_SUCCESS); | |
} |
view rawPic hosted with ❤ by GitHub
Lời kết
Trong bài tôi đã nối về trễ, nó ảnh hưởng thế nào đến hệ thống của bạn, và các giải pháp tốt. Các ví dụ được tối thiểu hóa và thực hiện đơn giản. Trong quá trình làm và thực hiện bạn nên có cái nhìn chính xác về hiện tượng bạn đang gặp phải và từ đó có thể hiệu chỉnh đối với loại nút nhấn bạn đang sử dụng sao cho phù hợp.
BÀI VIẾT CÙNG CHỦ ĐỀ