מבוא
לאחרונה עדכנתי את הספריות EBF ו-Plug-n-Play ב-GitHub, כדי להכין אותן להפצה והתחלתי להוסיף דוגמאות קוד לרכיבי Plug-n-Play שכתבתי עליהם קודם.

מההתחלה היה לי ברור שיהיו אתגרים עם המיזם הזה, ביניהם העובדה שיהיה קשה להסביר לאנשים למה מערכת Embedded צריכה להתבסס על פסיקות (Interrupts) ולא על לולאות מחזוריות.
למתחילים בתחום לא ברור למה לדגום קו כניסה של מיקרובקר כל 100 מילי-שניות כדי לזהות לחיצה על כפתור זה פחות טוב מאשר להגיב לפסיקה בצורה מיידית.
הסיבה העיקרית לדעתי היא כי המתחילים לומדים מהקוד הקיים בשפע ברשת. בסביבת ארדואינו עבודה עם פסיקות לא פשוטה כמו דגימת קו כניסה, וכמעט ואין דוגמאות קוד שידגימו איך כל זה מתבצע. לכל זה מתווסף הטאבו של הנושא בפורומים של ארדואינו, כי רוב האנשים שם גדלו על הלולאות ולא השתמשו בפסיקות בפרוייקטים שלהם, אז הם מנסים לשכנע את כולם שפסיקות זה מסובך.
אוקי. לוקח צעד אחורה בשכנוע הזה לבינתיים. בסופו של דבר, מי שיתקל בבעיות עם הפרוייקט, ירצה שהקוד שלו יעבוד חלק יותר, שמנוע הסרוו לא יקפוץ, או שהוא ירצה לחסוך בחשמל, אז כנראה שיגיע לזה בעצמו. אגיד רק שעם רכיבי Plug-n-Play הכל מתבסס על פסיקות בצורה שקופה למשתמש. לחצתם על כפתור, פסיקה מטופלת בספריית ה-EBF, נקראת הפונקציה שהגדרתם. עד כדי כך פשוט.
אתגר נוסף שהיה לי ברור שאתתקל בו הוא הצורך בדוגמאות הקוד שאנשים משתמשים בהם כדי ללמוד איך לעבוד עם רכיבים, או פשוט מעתיקים אותם לפרוייקט שלהם.
מערכת Plug-n-Play אומנם מבוססת על ארדואינו, אבל סגנון הכתיבה קצת שונה ממה שמוצאים בדוגמאות ברשת.
ברור לי שאני צריך לספק הרבה דוגמאות קוד כדי שלמשתמשים יהיה מובן יותר איך להשתמש ברכיבים החדשים.
וזה מה שהתחלתי לעשות תוך כדי עדכון הספריות ב-GitHub.
בעיית גידול
מהר מאוד הבנתי שזה יהיה בלתי אפשרי לספק דוגמה לכל פונקציונליות של כל רכיב שאוסיף בעתיד. אני רוצה שהדוגמאות יהיו הגיוניות ויהיו סוג של מיני-תוכנית שאפשר להעתיק ולהשתמש כמעט כמו שהיא בפרוייקט של מישהו אחר, ולא סתם קריאות לפונקציות של הרכיב בתחילת ריצה (בפונקציית ה-()setup למשל).
חשבתי לעצמי שאני חייב איזה שהוא כלי שיעזור לי עם המשימה. כלי שיאפשר להגדיר פעולות והוא ייצר את הקוד בעצמו.
משהו בכיוון של "כשלוחצים על כפתור" - "להדליק לד". "משחררים כפתור" - "לכבות לד". ופוף - יש לי קוד מוכן.
או דברים קצת יותר מסובכים, כמו למשל: "כשטמפרטורה עולה מעל סף מוגדר" - "להבהב בלד", "לשנות צבע רקע של מסך LCD לאדום", "להדפיס HOT על מסך LCD".
ובבקשה אל תתחילו עם זה שה-AI יכול לייצר לי תונית כזו בכמה שניות. הוא לא. במיוחד לא לרכיבים חדשים שלא קיימים בשוק, אין להם עדיין שום תיעוד וכל הדוגמאות קוד שקיימות זה רק מה שאני הוספתי לספריה ב-GitHub.
כיוון מחשבה
חשבתי על זה עוד קצת ומייד ראיתי שכל הקוד שמטפל ברכיבי Plug-n-Play הוא מאוד מובנה ומסודר (Structured). הכל מתכנס בסופו של דבר למבנה של INPUT -> OUTPUT, כלומר קוד שמטפל בלחיצה על הכפתור (ה-Input) עוטף קוד שמטפל בהדלקת לד (ה-Output).
לפעמים השרשרת היא של 3 שלבים: INPUT -> OUTPUT -> VALUE, כמו במקרים בהם רוצים להדפיס משהו, כמו טקסט, או מדידת טמפרטורה.
גם הצורה של הוספת טיפול ברכיב נוסף לקוד היא מאוד מובנית. צריך להגדיר משתנה שמטפל ברכיב, לעשות לו ()Init בפונקציית ()Setup של התוכנית, ואז אפשר להשתמש ב-API של המשתנה כדי להשתמש בפונקציונליות שלו.
נראה מאוד ישים... עוברות כמה סופי שבוע, ונהנה אני מציג לפניכם את אשף יצירת הקוד עבור רכיבי Plug-n-Play.
אחד הדברים שהיה מעניין לפתור הוא סדר הבחירה של הפעולות. לא תמיד הסדר יהיה INPUT -> OUTPUT -> VALUE. לפעמים למשתמש חשוב להתחיל מה-OUTPUT, כמו למשל למישהו יש רצון להבהב בלד, אז האשף ישאל את המשתמש "להבהב בלד (LED) כתוצאה מ..." ויאפשר לבחור מכל אפשרויות ה-INPUT במערכת.
או שאפשר להתחיל בכלל מה-VALUE, כשמישהו רוצה להדפיס/להציג טמפרטורה נוכחית. אז המשתמש ישאל איך הוא רוצה להציג את הטמפרטורה (מסך LCD, להדפיס דרך Serial של הבקר), כלומר ה-OUTPUT. ואחרי זה כתוצאה ממה לבצע את זה (ה-INPUT).
איך זה עובד
בחירת כל פעולה מתבצעת בשלושה שלבים:
- בחירת כיוון פעולה כללי, לדוגמה: להגיב לכפתור, לשלוט על לד
- בחירת רכיב Plug-n-Play המתאים לפעולה שבחרתם בשלב הקודם, לדוגמה: מודול עם כפתורים, לד על כרטיס פיתוח
- בחירת ממשק מדוייק של הרכיב שבחרתם בשלב הקודם, לדוגמה: להגיב ללחיצת כפתור, להדליק לד
בגלל שאין הרבה רכיבים במערכת כרגע, אז זה נראה כאילו האשף חופר לכם עם יותר מדי שאלות, כי יש רק אפשרות אחת לבחירה. בעתיד, כשיהיו יותר רכיבים שיכולים לספק את אותה הפעולה, אז הבחירות יראו יותר הגיוניות.
יש כמה מקרים שאפשר היה לדלג על שאלה או שתיים, כמו למשל, אם כבר ידוע מהו כרטיס הפיתוח שמשתמשים בו, כי בחרתם להשתמש בו כדי להדליק את הלד שיש על הכרטיס, אז די ברור שזה יהיה אותו הכרטיס שיצטרך לספק את הפונקציונליות של טיימרים (Timers) או "תחילת ריצת התוכנית", כלומר פונקציית ה-()setup. אבל בינתיים החלטתי להשאיר את כל שלושת השלבים לכל הפעולות כדי שתהיה אחידות בתהליך.
חוץ משלושת השלבים שתיארתי קודם, האשף יבקש מהמשתמש לספק מאפיינים שדרושים לביצוע פעולות שבחרתם. למשל, אם אתם רוצים להדפיס מחרוזת על מסך, אז תצטרכו לספק את תוכן המחרוזת, ובמקרים מסויימים גם האם צריך לרדת שורה אחרי ההדפסה או לא. אם אתם רוצים להבהב בלד, אז תצטרכו לספק את הזמן שהלד יהיה דלוק וזמן שהלד יהיה כבוי.
חלק מהרכיבים זקוקים גם לנתונים מסויימים בזמן אתחול, כמו למשל חיישן הטמפרטורה צריך לדעת את קצב המדידה שהוא מבצע בצורה עצמאית. גם נתונים אלה ישאלו.
בהתחלה כיוונתי לאפשר שרשרת INPUT -> OUTPUT -> VALUE אחד כדי להציג שימוש ב-API כזה או אחר. אבל אחרי שהגעתי לשלב זה, ראיתי שלא נדרש הרבה כדי לאפשר להוסיף עוד ועוד פעולות לתוכנית. הוספתי את האפשרות וכרגע אפשר להגיע לתוכניות של ממש. שחקו עם הכלי וספרו מה אתם חושבים על זה.
הנה לדוגמה תוכנית עובדת למערכת אזעקה לטמפרטורת יתר, שתואמת לתוכנית הדוגמה שהוספתי ל-GitHub.

אני מודה, לקח קצת זמן להגדיר את הכל, וצריך להיות ממוקד כדי לבחור את אותם הרכיבים לכל הפעולות, אחרת יתווספו רכיבים נוספים לפרוייקט (כמו מודול LCD של SparkFun ולא של SeeedStudio למשל). ולוקח די הרבה זמן עם כל הבחירות החוזרות של אותו ה-API, שאולי אפשר יהיה בעתיד לשפר עם ממשק משוכלל יותר, שיאפשר להוסיף פעולה ישירות לתוך המיקום הרצוי (כמו פעולה כאשר טמפרטורה עולה מעל הסף הגבוה או פונקציה של אחד הטיימרים). זה ללא ספק היה חוסך קצת זמן.
אבל המנגנון עובד ולדברים פשוטים הוא מספיק. במיוחד למי שבכלל לא יודע לכתוב קוד.
עם אשף כזה לא צריך לדעת לתכנת כדי לייצר תוכנית שמפעילה את הפונקציונליות הרצויה של הרכיבים, שזה כנראה 80% מהקוד למיקרובקרים.
מקבלים רשימה של רכיבים שדרושים לביצוע התוכנית (בעתיד עם קישורים לרכיבים באתר).
חיבור רכיבי Plug-n-Play לא דורש ידע באלקטרוניקה, אין אפשרות לחבר משהו לא נכון. פשוט מחברים את הרכיבים עם כבלים לחיבור PnP במיקרובקר, אפילו לא משנה לאיזה מהם.
כמות הרכיבים ידועה, כך שאוסף בעתיד גם כמה כבלים דרושים וקישורים למוצרים המתאימים.
כרגע אין רכיבים מתאימים כדי להדגים את זה, אבל מערכת Plug-n-Play מאפשרת חיבור קל של רכיבים שדורשים מתחים שונים. כמו למשל 12V לבקר מנוע DC ו-5V למנועי סרוו, בנוסף ל-3.3V למיקרובקר וחיישנים.
גם בנושא זה האשף יוכל לעזור ולהמליץ על חיבורים ורכיבים מתאימים כדי לחבר את כל מה שדרוש כדי לבנות את הפרוייקט שתכננתם!
אני מתכנן גם לשמור תוכניות לדוגמה בבסיס נתונים, כך שאפשר יהיה להציג אותן למשתמשים בהתאם לרכיב שמתעניינים בו באתר. מסתכלים על חיישן טמפרטורה מסדרת ה-Plug-n-Play באתר? קבלו קישור לדוגמאות שמשתמשות ברכיב זה...
כל זה יאפשר גם לספק מידע למנועי חיפוש כדי שה-AI ילמד וישכיל.
מגבלות
כרגע המנוע של האשף מוגבל לרכיב אחד מכל סוג. בינתיים לא מצאתי דרך אלגנטית לשלב כמה רכיבים מאותו הסוג. זה מסבך מאוד את קטעי הקוד שצריך לשמור בצד כדי לייצר את הקוד שאשף פולט.
יש רכיבים שיש להם כמה "מופעים" (instances), כמו מודול עם שני כפתורים, או בעתיד הקרוב מודולים עם מספר כניסות או מספר יציאות. האשף תומך ברכיבים אלה בצורה מספקת. להוסיף עוד מימד של "המופעים", כמו שלושה מודולים עם שני כפתורים יסבך את הכל פי כמה.
מערכת Plug-n-Play עצמה תומכת בחיבור של כמה רכיבים מאותו הסוג, פשוט צריך להגדיר כמה משתנים שמטפלים ברכיבים אלה ולהשתמש במשתנה המתאים לצורך.
כופפתי את ההגדרות של הטיימרים (Timers) כדי להשתמש באותם המנגנונים של המופעים, כמו שיש לכפתורים, כדי שאפשר יהיה להשתמש ביותר מטיימר אחד בתוכנית. אני פחות מרוצה ממה שיצא, אבל טיימר אחד מגביל מאוד את התוכניות שאפשר יהיה לייצר עם האשף. הדוגמה של אזעקה במקרה של טמפרטורה גבוהה משתמשת בשני טיימרים למשל. לא כזה נוח, אבל עובד.
האשף מייצר רק את הקוד סביב העבודה מול רכיבים ולא יודע לייצר לוגיקה, התנאיות, לולאות או משתנים.
לדעתי רוב הקוד בפרוייקטי ארדואינו הוא סביב הגישה לרכיבים וזה בדיוק מה שהאשף מספק.
לוגיקה וכל השאר זה כבר שפת C הבסיסית שהשמתש יצטרך להוסיף לבד. ודווקא בזה ה-AI של היום עושה עבודה די טובה ואפשר להעזר בו כדי להוסיף משהו לתוכנית שהאשף יצר.
וכמובן שלא בדקתי את כל אפשרויות הקוד שהאשף יכול לייצר, אבל אני בודק כל מקרה שאני מוסיף לקוד ובדיקות נוספות שמשהו לא השתבש עם השינויים.
פה תקווה גדולה שמשתמשים ידווחו אם משהו לא יעבוד להם.
אני עדיין ממשיך לעבוד על הכלי הזה, כך שאתם עלולים לראות כל מני הודעות או שדברים לא יעבדו זמנית. פשוט נסו שוב קצת יותר מאוחר.
אשמח מאוד לשמוע את דעתכם על כלי כזה. שימושי? מיותר? יש לכם רעיונות לשיפור? ספרו לי בתגובות לפוסט זה בפייסבוק.




