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 מתרגם כל גישה לקריאות וכתיבות של האוגרים המתאימים, ואלה מזיזים סיביות על גבי חוטים פיזיים.

A single chip outline containing labelled blocks -- CPU, RAM, flash, and a row of peripheral blocks (GPIO, ADC, Timer/PWM, UART/SPI/I2C, CAN) connected by an internal bus, with arrows from each peripheral exiting the chip toward physical pin labels.

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 שם. חלקים אחרים במעגל רואים את המתח הזה מיד – כולל כל רכיב שהפין עלול לפגוע בו אם הוא מונע בצורה שגויה.