Trang chủ Bài viết Chống nhiễu Kỹ thuật chống nhiễu cho nút nhấn

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.