מה אנחנו יודעים לעשות בינתיים:
-
לשלוט על הפעלה של LED, מנועים, הפעלה של מכשירים וכו’.
-
קריאה של מתגים, חיישנים פשוטים וכו’.
-
כתיבה של לוגיקה פשוטה.
בשיעור הזה ובבא נכיר את סביבת התכנות Processing, בעזרתה ניתן לכתוב בפשטות יחסית תוכנות המשלבות גורמים ויזואליים ואודיו ובעיקר, בהקשר שלנו, לקשר בין המחשב לארדואינו. זה יאפשר לנו, לדוגמה:
-
ליצור ממשקים מיוחדים ולהפעיל בעזרתם אפליקציות במחשב (וידאו, סאונד ואחרות).
-
להפעיל יישומים פיזיים בעזרת המחשב (http://www.taomc.com/).
-
להשתמש במחשב כ”מיקרוקונטרולר” חזק יותר מהארדואינו, שיכול, לדוגמה, להפעיל גם מצלמות, לנגן סאונד איכותי וכו’.
-
ליצור מוצגים שמשתמשים בכלים ממוחשבים ליצירת חוויות חדשות (http://everyware.kr/portfolio/contents/09_oasis/).
-
ועוד…
בנוסף, התכנות בשפת Processing כמעט זהה לשפה בה מתכנתים את הארדואינו ולימוד האחת יפתח אצלנו גם את יכולותינו בשניה.
כמו לארדואינו, גם ל- Processing יש קהילת משתמשים ומפתחים עולמית רחבה ביותר וניתן למצוא המון חומר באינטרנט, החל מלימוד בסיסי של השפה ועד לחבילות תוכנה מוכנות שנותנות לבצע בקלות פעולות מתקדמות ביותר (למשל: עיבוד קול, ראייה ממוחשבת, אנימציות ועוד). מקום טוב להתחיל בו הוא האתר שלהם: http://processing.org
שלום, עולם
פתחו את העורך של Processing וכתבו את התוכנה הבאה:
המבנה הבסיסי של תוכנה ב-Processing כמעט זהה לזה של ארדואינו, אלא שבמקום void loop הפונקציה העיקרית נקראת void draw.
בנוסף, אין צורך לעשות upload, אלא מספיק להפעיל (Run) את התוכנה בשביל להפעיל אותה (אין מיקרוקונטרולר שצריך להעביר אליו את התוכנה – היא מופעלת על המחשב).
-
שימו לב לחלון הנפתח כאשר מריצים את התוכנה – זהו החלון בו התוכנה מופעלת. בהמשך נצייר בחלון זה.
-
שימו לב שההודעה “Hello World” לא מופיעה בחלון זה, אלא בתחתית החלון של העורך. בדומה לארדואינו, הפקודה println מיועדת בעיקר להעברת הודעות למתכנת לשם בדיקות (debug).
פקודות בסיסיות:
-
הפקודה size אומרת למערכת מהו גודל החלון שאנו מעוניינים בשביל התוכנה שלנו (בפיקסלים). היא חייבת להיות הפקודה הראשונה בתוך setup.
-
הפקודה background קובעת את צבע הרקע של החלון. 110 = אפור. דוגמאות לצבעים נוספים (אתם מוזמנים לנסות):
-
255 = לבן
-
0 = שחור
-
255,0,0 = אדום
-
0,255,0 = ירוק
-
0,0,255 = כחול
-
128,128,0 = חאקי
-
וכו’
-
-
בנוסף לשלושת הצבעים (אדום, ירוק, כחול) ניתן לקבוע גם שקיפות ע”י הוספת פסיק ומספר רביעי בתוך הסוגריים. שקיפות נקראת alpha channel, כאשר 0 = שקוף ו- 255 = אטום.
לצייר דברים
הרבה פקודות חדשות:
- noStroke – אומר למחשב שלא יצייר קווי מתאר של צורות עד להודעה אחרת בנושא.
- fill – אומר למחשב באיזה צבע למלא את הצורות הבאות שיצויירו, שוב עד הודעה חדשה בנושא זה. הצבע נקבע עפ”י המספירם שבסוגריים, בדיוק כמו בפקודה background. בפעם הראשונה שמופיעה הפקודה בתוכנה שלנו, אנו אומרים למחשב למלא את הצורות באדום.
- ellipse מצייר אליפסה, או עיגול, עפ”י המספרים שבסוגריים. שני המספרים הראשונים מצביעים על מרכז האליפסה יחסית לפינה השמאלית העליונה של החלון ושני האחרונים על גודל האליפסה. בדוגמה שלנו – מרכז האליפסה יהיה 320 פיקסלים ימינה ו- 240 פיקסלים למטה, כלומר במרכז המסך. רוחב האליפסה יהיה 200 וגובהה 200 – כלומר זה יהיה עיגול.
- כדאי מאד להסתכל על העזרה של העורך: help -> reference. יש שם הסברים מפורטים ודוגמאות רלוונטיות לגבי כל פקודה.
- בפעם השניה בה מופיעה פקודת fill בתוכנה שלנו, אנו אומרים למחשב למלא את הצורות בכחול.
- הפקודה rect אומרת למחשב לצייר מרובע. למספרים שבסוגריים תפקיד דומה לאלו שבפקודת ellipse, אלא ששני הראשונים מצביעים על הפינה השמאלית העליונה של המרובע ולא על מרכזו. כלומר, בדוגמה שלנו המחשב יצייר מרובע שפינתו השמאלית העליונה נמצאת 250 פיקסלים ימינה ו- 170 פיקסלים מתחת לפינתו השמאלית העליונה של החלון. גודלו של המרובע יהיה 140 על 140 פיקסלים – ריבוע.
- שימו לב – מכיוון שהפקודות לציור הצורות המצאות בתוך draw, הן מצויירות שוב ושוב (אנו לא רואים זאת, מכיוון שהן נשארות קבועות).
הכיף מתחיל – משתנים:
התוספות על התוכנה הקודמת:
-
הגדרנו משתנה (תא זכרון) בשם w והצבנו בו את הערך 0 (ישתנה במהלך ההפעלה של התוכנה).
-
הפקודה frameRate קובעת את קצב הרענון של התוכנה שלנו (כמו בסרט), כלומר מספר בשניה הפעמים בו תופעל הפרוצדורה draw (כל הפקודות שבה). באופן זה ניתן לשלוט על המהירות בה דברים יזוזו על המסך.
-
העברנו את הפקודה noStroke לתוך setup, מכיוון שאיננו רוצים לשנות את צבע קווי המתאר של העצמים במהלך ההפעלה של התוכנה ולכן מספיק להפעיל אותה פעם אחת.
-
לעומת זאת, העברנו את background להתחלה של draw מכיוון שאנו רוצים למחוק את התמונה בכל ציור מחדש (אחרת, הצורות יצוירו זו על-גבי זו מבלי להמחק אף-פעם – נסו!).
-
הוספנו ++w – זוהי פקודה המוסיפה 1 לערך של w. כלומר.
-
לבסוף, הוספנו משפט תנאי if, הבודק אם w שווה ל- 400. אם כן – מציבים ב- w את הערך 0.
מוסיפים קלט
-
הפרוצדורה mousePressed מופעלת באופן אוטומטי בכל פעם שאחד מלחצני העכבר נלחץ (בתוך החלון של התוכנה). כלומר, בכל פעם שלחצן יילחץ, יופעלו הפקודות שנרשום בתוך הפרוצדורה הזו.
-
mouseButton הינו תא זיכרון המתעדכן מעצמו ומכיל מידע על לחצן העכבר האחרון שנלחץ – LEFT’ RIGHT או CENTER.
-
mouseX ו- mouseY הם תאי זיכרון המתעדכנים מעצמם ומכילים את מיקום העכבר יחסית לפינה השמאלית העליונה של החלון.
-
שימו לב: כרגע התוכנה מציירת רק עיגול אחד עם כל לחיצה. נסו להחליף את mousePressed עם mouseDragged ותראו מה קורה.
-
השארתי את int w=0 בהתחלה (בטעות). שום דבר רע לא קורה, פרט לכך שהתוכנה טיפה גדולה יותר ממה שהיתה יכולה להיות.
-
שימוש במקלדת בתור קלט נעשה באופן דומה למדי. בהמשך נראה כיצד ללמוד לבד דברים נוספים.
לולאות
לפעמים צריך יותר מ”לולאה” אחת בתוכנה (הפרוצדורה draw היא לולאה שעובדת שוב ושוב עד שמפסיקים את התוכנה).
נניח שאנחנו רוצים שכל לחיצת עכבר תצייר 5 עיגולים במקום אחד. נחליף את תוכן הפרוצדורה mousePressed שכתבנו קודם בזה:
כאן היינו צריכים לכתוב ellipse רק 5 פעמים, אבל אם היינו רוצים להוסיף 20 עיגולים? ואם 500?
לכן קיימת האפשרות להשתמש בלולאות (באנגלית: loops):
כאן, אנו משתמשים בפרוצדורה for בשביל להפעיל קבוצה של פקודות מספר פעמים בזו אחר זו. נסביר איך for בנויה:
-
int i=0 – כאן אנו יוצרים תא זכרון (משתנה) חדש, בשם i, ומציבים בו את הערך 0 (אפס).
-
i<100 – זהו תנאי. כל עוד הערך של i קטן מ- 100, הלולאה תמשיך (כלומר הפקודות שבין הסוגריים המסולסלים שאחרי פקודת ה- for יבוצעו).
-
i += 20 – זוהי דרך מקוצרת לכתוב i = i + 20, כלומר להציב במשתנה i את הערך הנוכחי שלו ועוד 20, או במילים אחרות להוסיף 20 ל- i. פקודה זו מבוצעת לאחר ביצוע הפקודות שבתוך הסוגריים המסולסלים.
הלולאה עובדת כך (בדוגמה שלנו):
- יוצרת תא זכרון בשם i ומציבה בו את הערך 0.
- בודקת אם הערך של i קטן מ- 100. מתקיים ולכן ממשיכה:
- מבצעת את הפקודה שבתוך הסוגריים המסולסלים – מציירת עיגול במיקום שבו העכבר נמצא.
- מוסיפה 20 לערך של i. עכשיו ערכו הוא 20.
- מהתחלה – בודקת אם הערך של i קטן מ- 100. מתקיים ולכן ממשיכה:
- מצררית עיגול 20 פיקסלים ימינה מהמיקום של העכבר (mouseX + i).
- מוסיפה 20 לערך של i. עכשיו ערכו הוא 40.
- מהתחלה – בודקת…
- וכן הלאה עד לפעם החמישית בה הלולאה רצה:
- i עכשיו מכיל 80. מציירת עיגול 80 פיקסלים מימין למיקום העכבר.
- מוסיפה 20 לערך של i. עכשיו הוא מכיל 100.
- בודקת אם i קטן מ- 100. התשובה שלילית ולכן הלולאה נפסקת (לא מבצעת את הפקודות שבין הסוגריים המסולסלים) והתוכנה ממשיכה לרוץ מהפקודה הבאה (במקרה שלנו אין פקודה נוספת ולכן התוכנה פשוט ממשיכה לא לעשות כלום עד שלוחצים שוב על לחצן העכבר).
בתוך הלולאה, אנו משתמשים במשתנה i כתוספת למיקום מרכז המעגל שאנו מציירים על ציר x (כלומר ימינה מהפינה השמאלית העליונה של המסך). אם אנו מבינים את החישוב של הגופים החוזרים-על-עצמם שאנו רוצים לצייר, כמעט תמיד אנחנו יכולים להחליף תוכנה ארוכה בקצרה, על-ידי מציאת לולאות שיבצעו בשבילנו את העבודה. במקרה זה, החישוב היה להוסיף 20 לערך ה-x של מיקום מרכז המעגל עבור כל מעגל יחסית לקודמו.
אפשר להשתמש בלולאה בתוך לולאה:
כאן, הלולאה הפנימית (זו עם המשתנה j) מופעלת 5 פעמים עבור כל ערך של הלולאה החיצונית (זו עם המשתנה i). כך אנחנו מקבלים “מטריצה” של 25 עיגולים.
להבין פרוצדורות:
עד עכשיו השתמשנו בפרוצדורות לא פעם, אבל בוא נבין אותן טוב יותר:
פרוצדורות הן הפקודות אותן אנו אומרים למחשב לבצע. חלקן מוגדרות מראש (כמו size, ellipse או for), אבל אנחנו יכולים גם ליצור פרוצדורות חדשות בעצמנו. נעשה זאת בכמה מקרים:
- כאשר נרצה לבצע סט מסויים של פקודות במקומות שונים בתוכנה. לדוגמה, נרצה שגם מקש ימני של העכבר יצייר 5 עיגולים וגם לחיצה על המקש C במקלדת יעשה כן.
- כאשר נרצה לבצע את אותו סט של פקודות עם פרמטרים (מספרים) שונים. לדוגמה, נרצה לצייר עם לחיצת עכבר לפעמים 5 עיגולים לבנים ולפעמים 5 עיגולים שחורים.
- כאשר נכתוב תוכנה גדולה ונרצה שהיא תראה מסודרת יותר (חשוב!) כך שיהיה קל יותר למצוא טעויות ולשנות אותה בעתיד.
- כאשר נרצה “ליצוק תוכן” בפרוצדורות המיוחדות, אשר יש להן שם אך הן ריקות מתוכן – פרוצדורות כמו setup, draw, mousePressed ואחרות.
פרוצדורה יכול לקבל ערכים, שיועברו אליה כאשר מפילים אותהולהשתמש בהם בתוכה. בדוגמה שלעיל, הפרוצדורה trapeze שהגדרנו (השם יכול להיות כל שם – כל עוד הוא לא משמש למשהו אחר בשפה ואז הוא יצבע בצבע אחר משחור) מקבלת שני מספרים שלמים (integers) בשם x ו- y ומשתמשת בהם כדי לצייר טרפז החל מנקודה זו בחלון.
פרוצדורה יכולה גם להחזיר ערך. במקרה זה נגדיר אותה מראש עפ”י סוג הערך שהיא מחזירה במקום void. עדכנו את הפרוצדורות הבאות:
בדוגמה זו, התוכנה תחליף את צבע הקווים לאדום אם מציבים טרפז שחורג מהמסך (ימינה). נראה כיצד:
- הפעלנו את הפרוצדורה trapeze מתוך משפט תנאי if. בדרך זו, לאחר שהפרוצדורה מבוצעת, היא מחזירה ערך בו משתמש ה- if (במקרה זה – “0″ או “1″) כדי לבדוק האם הוא שווה ל- 1. אם אכן הוא שווה ל- 1 (כלומר הפונקציה trapeze החזירה 1), תבוצע הפקודה שבסוגריים המסולסלים שאחרי ה- if, כלומר צבע קווי המתאר של צורות שיצויירו מעכשיו יהיה אדום.
- בתוך הפרוצדורה trapeze הוספנו תנאי – שוב if – שבודק אם הפינה הימנית ביותר של הטרפז חורגת מצידו הימני של החלון (width ו- height הם משתנים שמכילים תמיד את גודל החלון שבו התוכנה רצה – הגודל שקבענו בפקודה size).
- הפקודות return 0 ו- return 1 אומרות לפרוצדורה שלנו איזה ערך להחזיר וכן גורמות לה להפסיק לעבוד ברגע שהן מופעלות. כלומר, פקודות הכתובות אחרי שורה זו – לא יבוצעו.
פרוצדורה יכולה גם להכיל משתנים משל עצמה, אשר לא ישמשו את שאר התוכנה. בדרך-כלל אין לנו צורך אמיתי בכך מלבד כתיסה מסודרת וברורה. נעשה זאת על-ידי הכרזה על המשתנים בתוך הפרוצדורה (בדרך-כלל בשורה הראשונה). ניתן להשתמש במשתנים אלו רק בתוך הפרוצדורה בה הוכרזו. הם יעילים בשביל חישובים פנימיים (בדומה לפקודת הלולאה for, בה הכרזנו על משתנה מקומי i לצורכי הלולאה עצמה). רצוי לתת למשתנים שמות אחרים מאלו בהם אנו משתמשים בשאר התוכנה (אלו שאנו מכריזים עליהם לפני הפרוצדורה- setup – אשר נקראים משתנים גלובליים).
ה”כיף” הגדול של debugging (מציאת שגיאות)
מה קורה כאן? די ברור איפה הטעות, אבל רק בשביל להעביר את הנקודה, הוסיפו את המשפט הבא אחרי השורה עם הפקודה ellipse:
כאשר אנו לוחצים על הלחצן השמאלי של העכבר, אנו יכולים לראות בתחתית החלון של העורך את המספר אותו אנו מנסים לשים ב- ellipse בתור ערך ה- x של מרכז העיגול. אנו יכולים לראות כעת שרוב הזמן ערך זה גדול מדי ולכן העיגול מצוייר מחוץ לחלון (כלומר, לא מצוייר בכלל). עכשיו הבנו איפה הבעיה בתוכנה.
ברוב הפעמים בה תוכנה לא מבצעת את הצפוי והרצוי, הטעות אינה כה בולטת לעין. לכן, אנו משתמשים ב- println על-מנת להציג נתונים שונים במקומות שונים בתוכנה בשביל לראות שהנתונים הגיוניים ומתאימים לצפי.
איך לומדים עוד?
עכשיו יש לכם תפיסה בסיסית לגבי יסודות התכנות ב- processing (שהם, שוב, דומים מאד ל- arduino). עליכם ללמוד עוד הרבה אם אתם רוצים לכתוב תוכנות שלא יצירו רק עיגולים וטרפזים. לשם כך אתם יכולים:
כמה דוגמאות חביבות מאת גולן לוין (חלקן כוללות את הטקסט של התוכנות וניתן לנסות ללמוד מהן):










