Menu
CoddyTech

Đếm số lần nhấn bằng ngắt

Thuộc phần Định thời không dùng delay trong hành trình Arduino của Coddy. Bài học 15 trên 18.

Như bạn đã thấy trong phần Đầu vào, nút bấm bị dội: trong khoảng một mili giây, các tiếp điểm chạm nhau, tách ra rồi lại chạm nhau, cả khi nhấn lẫn khi nhả. Ngắt ghi nhận mọi lần chạm, nên một ISR FALLING cộng thêm 1 sẽ đếm một lần nhấp thành nhiều lần.

ISR không thể chống dội bằng delay(): delay() cần ngắt của chính đồng hồ, còn các ngắt bị tạm dừng trong khi ISR chạy. Thay vào đó, hãy dùng đồng hồ. Ghi nhớ thời điểm lần nhấn được đếm gần nhất và bỏ qua mọi lần chuyển xuống xảy ra quá sớm sau đó:

unsigned long lastPress = 0;

void onPress() {
  unsigned long now = millis();
  if (now - lastPress >= 200) {
    presses = presses + 1;
    lastPress = now;
  }
}

Đọc millis() trong ISR không sao: hàm này trả về thời điểm ISR bắt đầu. Chọn một khoảng thời gian dài hơn một lần nhấp để các lần dội khi nhả nút nằm trong khoảng đó, nhưng ngắn hơn thời gian giữa hai lần nhấp nhanh liên tiếp. 200 ms là phù hợp với mọi người.

challenge icon

Thử thách

Trung bình

Bộ đếm này đếm mỗi lần nhấn nhiều lần. Hãy chống dội bên trong onPress():

  • thêm một biến unsigned long lastPress
  • chỉ đếm một cạnh xuống nếu đã trôi qua ít nhất 200 ms kể từ lastPress, sau đó lưu thời gian vào lastPress

Nhấn Chạy, nhấn nút vài lần và theo dõi bộ đếm, sau đó nhấn Kiểm tra.

Tự làm thử

const int buttonPin = 2;

volatile int presses = 0;
int shown = 0;

void onPress() {
  // Mỗi lần tín hiệu trên chân chuyển xuống mức thấp đều được tính, kể cả khi nút bị dội: hãy chống dội tại đây
  presses = presses + 1;
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);
}

void loop() {
  // In ra số lần nhấn mỗi khi giá trị thay đổi
  if (presses != shown) {
    shown = presses;
    Serial.println(shown);
  }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Định thời không dùng delay

Tự luyện tập: Playground Arduino