3.1. מיקרו-בקרים#
ה-OpenMV Cam פועלת על מיקרו-בקר (MCU): שבב יחיד המשלב מעבד (CPU), זיכרון עבודה (RAM), אחסון תוכנית (זיכרון פלאש (flash)) ואוסף של התקנים היקפיים – בלוקים חומרתיים לאינטראקציה עם העולם החיצוני.
ההתקנים ההיקפיים הם החלק המעניין. כל אחד מהם הוא רכיב סיליקון המוקדש למשימה אחת: הנעת פין למצב גבוה או נמוך, מדידת מתח אנלוגי, שידור בתים על גבי אפיק טורי. המעבד מגדיר וקורא כל התקן היקפי דרך אוגרים – כתובות זיכרון קבועות שהחומרה עוקבת אחריהן ומעדכנת.
MicroPython עוטף את האוגרים הללו במחלקות בתוך המודול machine. machine.Pin(...) מחזיר אובייקט השולט בפין קלט/פלט כללי (GPIO) – חוט שהשבב יכול להחזיק גבוה (סביב 3.3 V) או נמוך (סביב 0 V), או לקרוא כאחד משני המצבים הללו כאשר משהו חיצוני מניע אותו. machine.ADC(...) חושף את הממיר האנלוגי-לדיגיטלי, המודד את המתח על פין ומדווח עליו כמספר. machine.UART(...) מפעיל משדר/מקלט אסינכרוני אוניברסלי (UART) – התקן היקפי השולח ומקבל בתים סיבית אחת בכל פעם על גבי זוג חוטים, TX (שידור) ו-RX (קליטה). מחלקות אחרות מכסות את שאר ההתקנים ההיקפיים. הסקריפט קורא וכותב אובייקטים של Python; MicroPython מתרגם כל גישה לקריאות וכתיבות של האוגרים המתאימים, ואלה מזיזים סיביות על גבי חוטים פיזיים.
MCU אורז את המעבד, הזיכרון וההתקנים ההיקפיים לשבב יחיד. כל התקן היקפי נחשף ל-Python על ידי מחלקה במודול machine.#
3.1.1. הלולאה הראשית#
כמעט כל תוכנית מיקרו-בקר חולקת אותו מבנה: הגדרה חד-פעמית בראש הסקריפט (ייבוא מודולים, הגדרת פינים, פתיחת אפיקים), ולאחר מכן לולאת while True: אינסופית בתחתית. בתוך הלולאה, התוכנית קוראת קלטים, מקבלת החלטות ומעדכנת פלטים שוב ושוב. הלולאה היא התוכנית; כאשר הסקריפט מסתיים, ההתקן מפסיק לעשות דבר.
# setup, runs once
from machine import Pin
led = Pin("P0", Pin.OUT)
# main loop, runs forever
while True:
led.value(1)
# ... do work ...
led.value(0)
# ... do other work ...
מבנה זה – הגדרה פעם אחת, ואז לולאה לנצח – הוא דפוס הלולאה הראשית. כל מה שבא בהמשך עוסק במה שמתרחש בתוכה.
3.1.2. בקרה בזמן אמת#
תוכנית שולחן עבודה רצה לצד תוכניות רבות אחרות. מערכת ההפעלה מתזמנת את עבודתה על פני threads אחד או יותר – זרמי ביצוע עצמאיים שהיא מתחלפת ביניהם מילישנייה אחר מילישנייה. כאשר thread אחד ממתין לקלט/פלט (דיסק, רשת, המשתמש מזיז את העכבר), מערכת ההפעלה מעבירה את המעבד לאחר. התוכנית היא בעיקרה מונחית-אירועים: מנהל החלונות קורא לקוד שלך כאשר מגיע קלט, ספריית ה-HTTP מחדשת את הקוד שלך כאשר מגיעים בתים בשקע. משהו גדול יותר קורא לך.
תוכנית מיקרו-בקר היא ההפך. כברירת מחדל אין מערכת הפעלה, אין מתזמן, ואין thread אחר. הלולאה הראשית שהוצגה זה עתה היא הלולאה היחידה. התקנים היקפיים מפעילים פסיקות או חושפים דגלי סטטוס; הלולאה דוגמת אותם או מטפלת בפסיקות ישירות. אם הלולאה נתקעת ב-time.sleep_ms(1000), ההתקן אינו עושה דבר במשך אותה שנייה; אין thread אחר שימלא את הפער.
שתי השלכות נובעות מכך וחלות בכל מקום:
הזמן הוא ממשי. קריאת פין פעמיים בלולאה צמודה אורכת מיקרו-שניות; שינה של עשר מילישניות פירושה עשר מילישניות שבהן דבר אחר אינו מתרחש. דפוס התזמון הלא-חוסם הוא המענה לכך.
החומרה היא ממשית. קביעת
machine.Pin.valueל-1מציבה בערך 3.3 V על חוט פיזי; קביעתה ל-0מציבה בערך 0 V שם. חלקים אחרים במעגל רואים את המתח הזה מיד – כולל כל רכיב שהפין עלול לפגוע בו אם הוא מונע בצורה שגויה.