Menu
CoddyTech
flag Ar iconالعربيةdown icon

عدّ الضغطات بالمقاطعة

جزء من قسم التوقيت دون delay في رحلة Arduino على Coddy. الدرس 15 من 18.

كما رأيت في قسم المدخلات، ترتد الأزرار: لمدة نحو ميلي ثانية، تتلامس نقاط التوصيل ثم تنفصل ثم تتلامس مجددًا، عند الضغط وعند الإفلات. يرى روتين خدمة المقاطعة كل تلامس، لذا فإن روتين خدمة المقاطعة FALLING الذي يضيف 1 يحتسب النقرة الواحدة عدة مرات.

لا يمكن لروتين خدمة المقاطعة إزالة ارتداد الإشارة باستخدام delay(): إذ تحتاج delay() إلى مقاطعة الساعة نفسها، وتُوقف المقاطعات مؤقتًا أثناء تشغيل روتين خدمة المقاطعة. استخدم الساعة بدلًا من ذلك. تذكّر متى حدث آخر ضغط تم احتسابه، وتجاهل أي هبوط يحدث بعده بوقت قصير جدًا:

unsigned long lastPress = 0;

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

لا بأس بقراءة millis() داخل روتين خدمة المقاطعة: فهي تعطي الوقت الذي بدأ فيه روتين خدمة المقاطعة. اختر نافذة زمنية أطول من النقرة، بحيث تقع خلالها ارتدادات الإفلات، وأقصر من الفاصل بين نقرتين سريعتين. 200 مللي ثانية مناسبة للبشر.

challenge icon

التحدي

متوسط

يحتسب هذا العداد كل نقرة عدة مرات. أضف إزالة الارتداد إليه داخل onPress():

  • أضف متغيرًا من النوع unsigned long lastPress
  • احتسب الحافة الهابطة فقط إذا مرّت 200 ms على الأقل منذ lastPress، ثم خزّن الوقت في lastPress

اضغط Run، وانقر على الزر بضع مرات وراقب العداد، ثم اضغط Check.

جرّب بنفسك

const int buttonPin = 2;

volatile int presses = 0;
int shown = 0;

void onPress() {
  // كل انتقال للطرف إلى المستوى المنخفض يُحتسب، حتى الارتدادات: أزِل أثر الارتداد هنا
  presses = presses + 1;
}

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

void loop() {
  // اطبع العدد كلما تغيّر
  if (presses != shown) {
    shown = presses;
    Serial.println(shown);
  }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس التوقيت دون delay

تدرّب بنفسك: Playground لـ Arduino