3.11. ביטול ריטוט (Debouncing)¶
מתג מצויר כמגע מושלם של פתוח-או-סגור, אך המגעים של מתג אמיתי אינם עוברים באופן נקי בין שני המצבים. הם מרטטים – יוצרים ומנתקים מגע חשמלי פעמים רבות בתוך מספר מילישניות לפני שהם מתייצבים. כניסת GPIO שקוראת את הפין רואה זאת כצרור של קצוות; לולאת תשאול לא זהירה סופרת מספר ”לחיצות“ עבור לחיצה אמיתית אחת, ומטפל פסיקה רץ מספר פעמים עבור כל לחיצה ממשית.
מתג מרטט מייצר צרור של מעברים מהירים לפני שהוא מתייצב.¶
ביטול ריטוט היא הפעולה של סינון הריטוט כך שכל לחיצה פיזית נרשמת כאירוע יחיד. שתי גישות פותרות זאת – תוכנה (כלל תזמון בקושחה) או חומרה (מסנן קטן על החוט). הן אינן סותרות זו את זו.
3.11.1. ביטול ריטוט בתוכנה¶
הרעיון הוא לזכור מתי הכניסה השתנתה לאחרונה ולדחות שינויים נוספים בתוך חלון קצר מאותה חותמת זמן. ריטוט מגע נמשך בדרך כלל פחות מ-10 מ“ש; לחיצה אמיתית אורכת 50 – 100 מ“ש; חלון של 30 – 50 מ“ש לוכד את כל הריטוטים מבלי לחסום לחיצות אמיתיות.
בלולאת תשאול, קרא את הפין, השווה לערך היציב האחרון, וקבל שינוי רק לאחר שחלון ביטול הריטוט חלף:
import time
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
last_state = 1
last_change = 0
DEBOUNCE_MS = 50
while True:
now = time.ticks_ms()
state = button.value()
if state != last_state and time.ticks_diff(now, last_change) > DEBOUNCE_MS:
last_change = now
last_state = state
if state == 0:
do_action()
time.sleep_ms(10)
עבור קריאות מונעות-פסיקה, החל את אותו כלל תזמון בתוך המטפל, ואז העבר את הלחיצה האמיתית להקשר הראשי באמצעות micropython.schedule() (ראה כניסת GPIO):
import time
import micropython
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
last_irq = 0
DEBOUNCE_MS = 50
def handle_press(pin):
do_action()
def on_press(pin):
global last_irq
now = time.ticks_ms()
if time.ticks_diff(now, last_irq) < DEBOUNCE_MS:
return
last_irq = now
micropython.schedule(handle_press, pin)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
ה-ISR מסנן ריטוטים לפי חותמת זמן ומציב את פונקציית ה-callback בתור; handle_press רץ בחזרה בהקשר הראשי, שם הקצאה וקלט/פלט איטי בטוחים.
3.11.2. ביטול ריטוט בחומרה¶
ביטול ריטוט בחומרה מסנן את הריטוט בצורה חשמלית, לפני שהוא מגיע בכלל אל הפין. הכלי הסטנדרטי הוא קבל.
קבל הוא רכיב בעל שני הדקים המאחסן מטען חשמלי. פיזית, מדובר בשתי לוחיות מוליכות המוחזקות במרחק קצר זו מזו, מופרדות על ידי מבודד (הדיאלקטרי).
קבל לוחיות מקבילות: שני מוליכים מופרדים על ידי שכבה מבודדת.¶
הפעלת מתח על פני ההדקים שלו מניעה מטענים שווים ונגדיים אל שתי הלוחיות; היחס הוא
Q = C × V
כאשר Q הוא המטען המאוחסן (קולון), V הוא המתח על פני הקבל, ו-C היא הקיבול שלו (פאראד). הקיבול נקבע על ידי מבנה ההתקן; קיבול גבוה יותר פירושו אחסון מטען רב יותר באותו מתח.
התוצאה: קבל אינו יכול לשנות את מתחו באופן מיידי. מטען הזורם פנימה או החוצה חייב לעבור דרך כל התנגדות שנמצאת בנתיב, והתנגדות זו קובעת באיזו מהירות המתח יכול להשתנות.
3.11.2.1. קבוע הזמן RC¶
טעינת קבל דרך נגד מייצרת עלייה מעריכית חלקה לעבר מתח האספקה, ולא מדרגה. הזמן האופייני של עלייה זו הוא קבוע הזמן RC:
τ = R × C
לאחר τ אחד, הקבל הגיע לכ-63 % ממתח האספקה. לאחר 5 τ, הוא מעל 99 % – ”טעון במלואו“ לצרכים מעשיים.
קבל נטען לאורך עקומה מעריכית. τ = RC הוא הזמן להגיע ל-63 % מהמתח הסופי.¶
פריקה דרך נגד עוקבת אחר התמונה ההפוכה: המתח יורד מעריכית מערכו ההתחלתי לעבר אפס, צונח ל-37 % ממתח ההתחלה לאחר τ אחד, ולמתחת ל-1 % לאחר 5 τ.
קבל נפרק לאורך דעיכה מעריכית. τ = RC הוא הזמן לרדת ל-37 % ממתח ההתחלה.¶
3.11.2.2. מעגל ביטול הריטוט¶
קבל בין פין כניסה לבין אדמה, המוזן דרך נגד טורי, יוצר מסנן מעביר נמוכים. קוצים מהירים אינם מספיקים לטעון או לפרוק את הקבל דרך אותו נגד; הפין נשאר קרוב לכל מתח שהיה בו לפני הקוץ. שינויים איטיים – לחיצה מכוונת – טוענים או פורקים את הקבל והקריאה עוקבת.
R1 מושך את הצד הגבוה של המתג מעלה אל Vcc, ומייצר אות מתג גולמי שמרטט. R2 ו-C לאחר מכן מסננים-מעביר-נמוכים את האות הזה אל הפין:
ביטול ריטוט בחומרה: R2 ו-C מסננים-מעביר-נמוכים את אות המתג הגולמי לפני שהוא מגיע אל הפין.¶
ערכים טיפוסיים: R1 = 10 kΩ (משיכה-מעלה), R2 = 10 kΩ (טורי), C = 100 nF.
כאשר המתג פתוח, זרם זורם Vcc → R1 → R2 → קבל (בטור), וטוען את הקבל ל-Vcc עם τ_charge = (R1 + R2) × C = 2 ms.
כאשר המתג נסגר, צומת המתג נצמד לאדמה והקבל מתנקז דרך R2 בלבד אל אותה אדמה עם τ_discharge = R2 × C = 1 ms.
שני הקצוות מסוננים-RC. מכיוון שהקבל יושב על הצומת שלו עצמו, במורד הזרם מ-R2 מהמתג, הוא מתנדנד בצורה נקייה בין Vcc (פתוח) ל-0 V (סגור) – שום זרם אינו צריך לזרום דרך R1 במצב יציב באף אחד מהמקרים.
3.11.3. בחירה ביניהם¶
תוכנה היא ברירת המחדל. היא אינה עולה דבר ברכיבים, הסף קל לכוונון, והיא עובדת על כל פין שהמעבד קורא.
חומרה שווה את הרכיבים כאשר הריטוט מגיע למשהו אחר מלבד קוד התשאול של המעבד – פסיקה שאסור לה להיפלט פעמיים, מונה חומרה, התקן היקפי ללא מסנן משלו.
ביטול ריטוט בתוכנה ובחומרה גם דרים יחד בשלום: מסנן RC קטן מדכא את הקוצים החמורים ביותר, וחלון ביטול ריטוט בתוכנה מכסה את מה שנותר.