קלט ופלט בסיסיים ב-Xiao RP2040

אחרי שראינו איך מכינים את לוח הפיתוח הזעיר לעבודה עם MicroPython ומעלים אליו קוד, בואו נלמד כיצד מבצעים את הפעולות הבסיסיות של קלט ופלט דיגיטליים, פלט PWM וקלט אנלוגי. המידע הזה יתאים גם ללוח Raspberry Pi Pico.

לוח Xiao RP2040 עם לד ולחצן
לוח Xiao RP2040 עם לד ולחצן

בדיוק כמו בארדואינו, הספריות הייחודיות של MicroPython מספקות לנו פונקציות לגישה קלה – גם אם לא הכי מהירה – לשימושים השונים של פיני הקלט/פלט. זה נעשה באמצעות מחלקות שונות שמוגדרות בספרייה machine. אבל לפני כן…

הערת שוליים: שעון וזרם

בואו נדבר רגע על פרמטרים מעניינים אחרים – מהירות המעבד וצריכת הזרם. מה תדר השעון של ה-Xiao? כמה חשמל הוא לוקח? בדפי היצרן כתוב שתדר השעון הוא עד 133MHz, ובשרטוט הסכמטי לא כתוב בכלל מה תדר הגביש שמזין את המעבד. הפונקציה machine.freq ב-MicroPython, כשקוראים לה בלי פרמטרים, מחזירה לנו את תדר שעון המערכת, ולטענתה מדובר על 125MHz דווקא (מספר הגיוני שמופיע ב-datasheet של המעבד). בתדר הזה מדדתי צריכת זרם – של הלוח כולו, כולל מייצב המתח המובנה ולד ה-Power שתמיד דולק – של 27.8 מיליאמפר תחת 5V. אם מוסיפים פרמטר ל-machine.freq אפשר לכוון בעצמנו את תדר השעון: כשהעליתי אותו ל-240MHz(!) הקוד אכן עבד הרבה יותר מהר, וגם הצריכה עלתה ל-45.6mA. כשהורדתי ל-24MHz הצריכה ירדה ל-10.5mA. הטווח המעשי הוא כנראה בסביבות 10-250MHz: מעבר לגבולות האלה הלוח התחיל לעשות לי בעיות בתקשורת עם המחשב. באופן אישי, אני מעדיף להישאר בטווח הרבה יותר שמרני סביב ברירת המחדל.

קלט ופלט דיגיטליים

חזרה לנושא. בספרייה machine, המחלקה שמטפלת בקלט ופלט דיגיטליים בסיסיים נקראת Pin, וראינו אותה בקוד הבלינק שהופיע בסוף הפוסט הקודם. בתחילת קוד ה-MicroPython שלנו נכתוב את השורה

from machine import Pin

לאחר מכן, ניצור אובייקט נפרד עבור כל פין שמעניין אותנו. לדוגמה, אם אנחנו רוצים להפוך לפין פלט את פין מס' 26 (או פין "0" לפי המספור שעל הלוח), נכתוב פקודה כזו:

myOutputPin = Pin(26, Pin.OUT)

ה-"Pin.OUT" הוא קבוע שמוגדר בספרייה, כמו OUTPUT של ארדואינו. יודעים מה, בואו ניצור מעגל שלם עם כפתור ולד, שיכבה את הלד כאשר הכפתור לחוץ. המעגל הזה מופיע בתמונה שבתחילת הפוסט. את פין הפלט בשביל הלד הגדרנו בשורת הקוד הקודמת, אז עכשיו נגדיר פונקציונליות קלט לפין 27 ("1" על הלוח):

myInputPin = Pin(27, Pin.IN, pull=Pin.PULL_UP)

חוץ מאשר להגדיר אותו כפין קלט עם הקבוע Pin.IN, הוספתי לו גם פרמטר (אופציונלי) pull עם הערך Pin.PULL_UP שמפעיל את נגד ה-pullup הפנימי. כך, ברירת המחדל של הקלט תהיה "יש מתח", ואנחנו נחבר את הכפתור כך שבעת לחיצה הוא יקצר בין הפין הזה לבין האדמה. לחלופין, אפשר להשתמש בערך Pin.PULL_DOWN כדי להפעיל נגד pulldown פנימי, או (כשזה הגיוני מבחינת המעגל) לא לציין שום pull בכלל.

עכשיו נותר רק לכתוב לולאה אינסופית שמעתיקה את הערך שמתקבל מפין הקלט אל פין הפלט:

while True:
    v = myInputPin.value()
    myOutputPin.value(v)

אם חיברנו נכון את הרכיבים והחוטים, התוכנית הזו תעבוד: כשהכפתור לא לחוץ, פין הקלט יזהה מתח בגלל ה-pullup הפנימי, וזה מה שייצא בפלט – הלד ידלוק. בלחיצה על הכפתור, לעומת זאת, החיבור הישיר דרכו לאדמה יגבור על ה-pullup, הקלט בפין 27 יהיה אפס, ובעקבותיו גם הפלט בפין 26. מה הערכים ש-v מקבל בתוכנית הזו? אפס (0) לאדמה ואחד (1) למתח. לא מפתיע. שימו לב, כשאנחנו שולחים ערך דרך המתודה value כדי לקבוע את הפלט, כל ערך שאינו 0 ייחשב 1.

יש עוד ארבע פונקציות שיכולות לקבוע מצב של פין פלט. השמות שלהן די מסבירים את עצמם. מי צריך את כולן? לא יודע, זה מה יש.

myOutputPin.low()
myOutputPin.off()
myOutputPin.on()
myOutputPin.high()

פלט "אנלוגי" (PWM)

כדי להוציא פלט PWM מפין מסוים, אנחנו צריכים קודם כול להגדיר אובייקט פין (כמו שעשינו קודם), ואחר כך ליצור אובייקט PWM ש"יעטוף" אותו. לשם כך נתחיל, בראש התוכנית, בייבוא של המחלקות הדרושות:

from machine import Pin, PWM

וניצור את האובייקטים המתאימים – שוב, בדוגמה זו, על פין 26. שימו לב שלא צריך להגדיר אותו במפורש כפין פלט!

myOutputPin = Pin(26)
myPWMPin = PWM(myOutputPin)

לאובייקט שיצרנו בשורה האחרונה יש שתי מתודות עיקריות: freq שקשורה למחזוריות של הסיגנל (כמה פעמים בשנייה), ו-duty_u16 שקשורה ל-duty cycle שלו (איזה חלק ממנו הוא "high"). אם נקרא לפונקציות האלה בלי שום פרמטר, הן יחזירו את הערכים הנוכחיים. אם ניתן להן ערך כפרמטר, הן יקבעו את פלט ה-PWM לפיו. כמובן שאי אפשר להגדיר כל ערך שבעולם, הבעיה היא ש-MicroPython לא אומרת לנו איפה עובר הגבול. לכן כדאי להיזהר בקוד שלנו ולשמור על ערכים הגיוניים. הסיומת "u16" של שם המתודה השנייה רומזת שמדובר באות PWM ברזולוציה של 16 ביטים, כלומר הערכים החוקיים נעים בין 0 ל-65535 כולל.

הנה שתי שורות קוד, שבתוספת השורות שלמעלה יפיקו לנו פלט PWM בתדר 20KHz ועם duty cycle של 25%:

myPWMPin.freq(20000)
myPWMPin.duty_u16(16384)

והנה הפלט מהרצת התוכנית, כפי שנצפה בסקופ (הסטייה הקטנה של הפרמטר width מימין למטה נעלמה כשהגדלתי את הרזולוציה):

פלט הסקופ בחיבור לפלט ה-PWM מהלוח
פלט הסקופ בחיבור לפלט ה-PWM מהלוח (לחצו לתמונה גדולה)

אגב, בשיטה הזו, שליטה במנועי סרבו הופכת לקלה עד כדי גיחוך. לא צריך שום ספרייה מיוחדת בשביל זה. מספיק לקבוע את תדירות אות ה-PWM ל-50Hz (20 אלפיות השנייה כל פעם), ולהפעיל duty cycle של 3277 (אחד חלקי עשרים מהמקסימום, כלומר אלפית שנייה אחת) עד 6554 (אחד חלקי עשר, שזה שתי אלפיות השנייה)!

קלט אנלוגי (ADC)

לסיום, בואו נקרא את המתח האנלוגי מאחד הפינים של ה-Xiao. גם פה, הרעיון הוא "להתלבש" עם מחלקה בשם ADC על אובייקט פין פשוט. הקוד הבא קורא, פעם בשנייה, מתח אנלוגי מפין "3" של הלוח (מספר אמיתי 29), ומדפיס את הערך שמתקבל בטרמינל של סביבת הפיתוח Thonny, שבה כזכור אנחנו מריצים את כל התוכניות האלה.

קוד לדוגמה לקריאה פשוטה של מתח אנלוגי
קוד לדוגמה לקריאה פשוטה של מתח אנלוגי

בקוד הזה הגדרתי את פין הקלט במפורש עם Pin.IN, אבל בפועל זה לא חיוני – MicroPython מגינה עלינו מעצמנו וזה יעבוד אפילו אם נגדיר את הפין כ-Pin.OUT. זיכרו רק נקודה חשובה – ללוח ה-Xiao RP2040 יש רק ארבעה פינים שמסוגלים לקרוא קלט אנלוגי: פינים 0 עד 3 כולל (מספרים אמיתיים 26-29). כמו ב-PWM, גם כאן הרזולוציה היא 16 ביטים(!) ולכן טווח הערכים נע בין 0 ל-65565 כולל.

מה הלאה?

כל המחלקות שהזכרתי כאן כוללות מתודות נוספות, וכדאי לכם לקרוא בהזדמנות את המפרטים ולהכיר אותן. מקום טוב להתחיל הוא הדף הזה, ויש קישורים חשובים שם בתחתית. אבל לשימוש בסיסי ומשחקים פשוטים, ראינו את כל מה שצריך. אם נרצה להתחיל להשתמש ב-Xiao לפרויקטים רציניים יותר, נצטרך להפעיל גם שיטות תקשורת מתקדמות, כגון UART ו-SPI. על כך – בפוסטים הבאים…

להרשמה
הודע לי על
0 תגובות
Inline Feedbacks
הראה את כל התגובות