Đế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.
Thử thách
Trung bìnhBộ đế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àolastPress
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);
}
}
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