Ngắt là một kỹ thuật được dùng rất nhiều với vi điều khiển. Sử dụng ngắt giúp giảm tải việc chương trình phải thường xuyên quét trạng thái. Mỗi khi xảy ra sự kiện tạo ngắt, chương trình ngắt được thực hiện và sau đó tự động quay lại chương trình chính. Trong bài này, chúng ta sẽ sử dụng ngắt với công tắc hồng ngoại RPR-220.
Cảm biến công tắc hồng ngoại RPR-220 có hai phần, một là đèn LED phát hồng ngoại và một là LED thu. Nó có thể được sử dụng để phát hiện vật cản, đo đếm sự kiện, v.v.. Chính vị sự đơn giản và rẻ tiền mà RPR-220 được sử dụng khá rộng rãi.
Trong bài này, chúng ta sẽ thực hiện một mạch đo vận tốc chuyển động của vật. Khi vật di chuyển qua phía trước cảm biến, nó sẽ phản xạ tín hiệu hồng ngoại về phía đầu thu, sinh ra một tín hiệu điện có thể phát hiện được. Tín hiệu này là nguồn tạo ngắt.
Kết nối với Arduino rất đơn giản, bổ sung thêm hai điện trở để hạn dòng là đủ điều kiện cho cảm biến hoạt động. Trong ví dụ này, ta sử dụng ngắt ngoài tại chân 2 và 3 để nhận biết và tính toán thời gian. Bình thường, LED thu không nhận được tín hiệu nên không dẫn, mức điện áp tại mức cao. Khi vật đi qua phía trước cảm biến, tín hiệu hồng ngoại bị phản xạ trở lại LED thu khiến nó dẫn. Mức điện áp bị hạ xuống thấp, đây là một tín hiệu ngắt để bắt đầu đo thời gian. Khi vật đi khỏi vùng cản, tín hiệu hồng ngoại không phản xạ trở lại khiến LED thu ngưng dẫn. Mức điện áp từ thấp trở về cao, đây là tín hiệu ngắt thứ hai để ngưng việc đo thời gian. Với kích thước vật biết trước, ta có thể tính ra vận tốc dựa trên tham số trên.
Để sử dụng ngắt, ta dùng hàm sau: attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
Tham số thứ nhất là chân nhận tín hiệu ngắt, thứ hai ISR là hàm ngắt, thứ ba mode là dạng tín hiệu ngắt. Với ngắt ngoài, dạng ngắt có thể là LOW, CHANGE, RISING, FALLING; tương ứng với sự thay đổi mức tín hiệu hoặc sườn xung.
Chương trình này chỉ có độ chính xác đến ms. Nếu muốn tăng độ chính, ta phải đếm xung bằng bộ đếm của vi điều khiển. Tuy nhiên, phương pháp đó khá phức tạp và đòi hỏi người viết phải nắm rõ kỹ thuật lập trình vi điều khiển.
// Đo vận tốc của vật
// Sử dụng 2 ngắt tại chân 2 và 3
const byte ledPin = 13;
const byte Ngat01Pin = 2;
const byte Ngat02Pin = 3;
volatile int thoigian01 = 0;
volatile int thoigian02 = 0;
int khoangtg = 0;
volatile byte trangthai = 0;
void setup()
{
pinMode(ledPin, OUTPUT);
//pinMode(Ngat01Pin, INPUT_PULLUP);
pinMode(Ngat02Pin, INPUT_PULLUP);
Serial.begin(9600);
cli();
sei();
//
// ngắt 01 tác dụng ở cạnh xuống
attachInterrupt(digitalPinToInterrupt(Ngat01Pin), Ngat01, FALLING );
// ngắt tác dụng ở cạnh lên
attachInterrupt(digitalPinToInterrupt(Ngat02Pin), Ngat02, RISING);
}
void loop()
{
if(trangthai == 2)
{
trangthai = 0;
// tính toán khoảng thời gian
khoangtg = thoigian02 - thoigian01;
// gửi về máy tính
Serial.print("Khoảng thời gian: ");
Serial.print(khoangtg);
Serial.println(" ms");
}
}
void Ngat01()
{
// ghi lại mốc thời gian
// hàm millis() cung cấp giá trị
// thời gian hiện tại theo ms
thoigian01 = millis();
digitalWrite(ledPin, HIGH);
trangthai = 1;
}
void Ngat02()
{
if(trangthai == 1)
{
thoigian02 = millis();
trangthai = 2;
digitalWrite(ledPin, LOW);
}
}