3.10. כניסת GPIO

קריאת מתג (או כל אות דיגיטלי) מפין GPIO עוברת שוב דרך machine.Pin, הפעם מוגדר ככניסה. הממשק סימטרי לפלט: הגדר את המצב, ואז או תשאל את ערך הפין בלולאה הראשית או רשום מטפל פסיקה שנפלט כאשר הערך משתנה.

3.10.1. הגדרת כניסה

העבר Pin.IN לבנאי, ובאופן אופציונלי נגד משיכה:

from machine import Pin

button = Pin("P0", Pin.IN, Pin.PULL_UP)

זה מגדיר את P0 ככניסה עם נגד המשיכה-מעלה הפנימי של ה-MCU מאופשר. כשדבר אינו מחובר לפין, המשיכה-מעלה מחזיקה אותו גבוה; סגירת מתג מהפין לאדמה מושכת אותו נמוך.

3.10.2. קריאת הערך

value() ללא ארגומנטים מחזיר את המצב הנוכחי – 0 עבור נמוך, 1 עבור גבוה:

if button.value() == 0:
    print("button pressed")
else:
    print("button released")

בתבנית הלולאה-הראשית, התשאול נראה כך:

while True:
    if button.value() == 0:
        do_action()
    time.sleep_ms(50)

השינה של 50 מ“ש מונעת מהלולאה לרוץ במלוא עומס המעבד.

3.10.3. כניסה מונעת-פסיקה

תשאול עובד, אך כל איטרציה של הלולאה הראשית עולה זמן מעבד. עבור כניסות שמשתנות לעיתים רחוקות – לחיצת לחצן פעם בדקה, אות אזעקה – irq() רושם מטפל שרץ רק כאשר הפין משתנה.

המטפל רץ בהקשר פסיקה, מה שמגביל את מה שהוא יכול לעשות:

  • אין הקצאת זיכרון. יצירת אובייקטים חדשים – רשימות, מחרוזות, חריגות, מחרוזות מעוצבות – עלולה להיכשל בתוך ISR מכיוון שה-heap נעול. הקצה מראש כל חוצץ (buffer) שהמטפל צריך בהיקף המודול.

  • אין עבודה ממושכת. המטפל אמור להעביר הלאה ולחזור. בזבוז זמן ממשי בתוך ISR מעכב את כל השאר (פסיקות אחרות, הלולאה הראשית, תעבורת USB).

  • אין הדפסה ב-ISR צפוף. print() מקצה זיכרון, נחסם על ה-UART, והוא אחד הדברים היקרים ביותר שמטפל יכול לעשות.

התבנית הסטנדרטית היא שה-ISR מתזמן את העבודה האמיתית באמצעות micropython.schedule(), אשר מציב בתור פונקציה שתרוץ בחזרה בהקשר הראשי בנקודה הבטוחה הבאה:

import micropython

def handle_press(pin):
    print("button pressed")

def on_press(pin):
    micropython.schedule(handle_press, pin)

button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)

ה-ISR הוא שורה אחת: הצב בתור את פונקציית ה-callback וחזור. handle_press רץ אז בהקשר רגיל, שם הקצאה, print(), וקלט/פלט איטי כולם בטוחים שוב.

הארגומנט trigger בוחר איזה קצה נפלט: