14 - הארדואינו ותקשורת נתונים

בפרויקט הזה, נשתמש ב Arduino על מנת לשלוט על תוכנית במחשב שלנו (באמצעות תקשורת טורית). המעגל האלקטרוני יהיה פשוט מאוד הפעם, וכך גם הקוד של ה Arduino, נתמקד נטו בשליטה על התוכנית מחשב האחרת, באמצעות ה Arduino.

נפתח חיבור בין ה Arduino למחשב שלנו, כמו שעשינו עד כה, אך הפעם נשתמש בחיבור זה כדי לשלוח ולקבל נתונים ליישומים אחרים.

ל Arduino יש שבב הממיר את התקשורת של המחשב (המבוססת USB) לתקשורת טורית אותה ה Arduino מבין. תקשורת טורית אומרת ששני מחשבים, ה Arduino והמחשב האישי שלנו, מחליפים פיסות מידע באופן סידרתי, ז”א אחד לאחר השני מבחינת רצף הזמן. כאשר מחשבים משתמשים בתקשורת טורית הם צריכים להסכים על המהירות בה הם ידברו זה עם זה (בטח שמתם לב שכאשר השתמשנו בתקשורת טורית והזנו את המס’ 9600 ביטים לשניה, אותו המספר הופיע גם בחלון התקשורת במחשב, בפינה הימינית התחתונה של החלון). המספר אותו אנו מזינים, 9600 ביטים לשניה, הוא המספר שאנו מכניסים כפרמטר לפונ’ ()Serial.begin והוא המהירות שבה ה Arduino והמחשב יחליפו נתונים (ביט – bit – סיבית, היא ספרה בינארית – יחידת הנתונים הקטנה ביותר שבה משתמש המחשב).

כבר השתמשנו ב serial monitor כדי להסתכל על ערכים מהכניסות האנלוגיות. נשתמש בשיטה דומה כדי להכניס ערכים לתוכנית שנכתוב בסביבת תכנות בשם Processing. סביבת תכנות זו מבוססת על Java, וסביבת התכנות של ה Arduino מבוססת על זו של Processing, ככה שאנחנו צריכים להרגיש די בבית. לכן לפני שנתחיל לעבוד על הפרויקט, נוריד את הגרסה העדכנית ביותר של Processing מכאן. וכדאי אולי להציץ, לפני שאנו מתחילים לעבוד על הפרויקט, ב מדריכים שבאתר, רק כדי להרגיש נוח יותר.

הדרך היעילה ביותר כדי לשלוח נתונים בין ה Arduino ו Processing היא עם הפונ’ ()Serial.write (בסביבת Arduino – הלא היא Sketch). זה דומה מאוד לפונ’ שהשתמשנו עד כה, ()Serial.print, אך במקום לשלוח מידע קריא לבני אדם (כמו אותיות ומספרים), הפונ’ הזו שולחת ערכים בין 0-255 כבתים (יחידת המידה מעל ביטים, bytes) של מידע גולמי. זה כמובן מגביל את המידע שה Arduino יכול לשלוח, אך מאפשר העברה מהירה יותר של מידע.

בשני המחשבים (המחשב האישי שלנו וה Arduino) יש משהו שנקרא serial buffer (חוצץ סידורי) המחזיק את המידע עד שהוא נקרא ע”י התוכנית. את המידע שנשלח (בצורת bytes), נשלח אל ה serial buffer של Processing, ולאחר מכן Processing תקרא את המידע מה buffer. כשתוכנית כלשהי קוראת את המידע מה buffer הוא מתרוקן, מה שאמפשר לנו לשלוח אליו מידע חדש. בנוסף, בעת השימוש בתקשורת טורית בין מכשירים ותוכניות, חשוב ששני הצדדים לא רק ידעו כמה מהר התקשורת תיהיה אלא גם למה לצפות.

 

חיבור הרכיבים

נחבר ללוח המטריצה חוטים מגשרים מעמודות ה+ וה-, אל ה 5V וה GND (בהתאמה, כפי שעשינו עד כה). נמקם פוטנציומטר על גבי לוח המטריצה ונחבר רגל אחת שלו לאדמה (-) ואת הרגל השניה לכוח (+), ואת הרגל האמצעית לפין האנלוגי A0.
להלן סכמה ואיור להמחשה:

Wiring Sketch

 

הקוד

תחילה, נכתוב את התוכנית ל Arduino:

בפוקנציית ה ()setup: נפתח חיבור למחשב, נבצע זאת עם הפונ’ ()Serial.begin, ונכניס לתוכה את הפרמטר 9600 (המהירות בו ה Arduino יתקשר, 9600 ביטים לשניה). אותו המספר (9600) יהיה כתוב בתוכנית Processing.

בפונקציית ה ()loop: בתוך ה loop נשתמש בפקודת ה ()Serial.write כדי לשלוח מידע על גבי החיבור הטורי. פקודת ה ()Serial.write יכולה לשלוח ערך אך ורק בטווח 0-255, אך הפקודה ()analogRead מקבלת ערכים בטווחים אחרים, גבוהים יותר. לכן נחלק את התוצאה שנקבל ב-4 על מנת להתאים את הערכים לאלה שאנו יכולים לשלוח. לאחר שליחת המידע, נחכה מילי-שניה אחת כדי לתת ל ADC לנוח לרגע.

void setup(){
    Serial.begin(9600);
}

void loop(){
    Serial.write(analogRead(A0)/4);
    dealy(1);
}

 

Processing Logo

התוכנית ל Processing:

processing, שלא כמו ה Arduino, לא יודע כלום על יצאות טוריות באופן מובנה, כך שאנו צריכים לייבא ספרייה חיצונית הנקראת *.processing.serial שתתן לנו את האפשרות הזו (הכוכבית אומרת שאנו מייבאים את כל הפונקציות בספריית ה serial). לאחר מכן, ניצור אובייקט (נקרא לו myPort) בדיוק כמו שעשינו עם ספריית ה Servo ב Arduino.

המטרה שלנו בתוכנית הזו היא לבצע שינויים על גבי תמונה. לכן ניצור עוד משתנה ונקרא לו logo, שיהיה מסוג PImage והוא יחזיק את התמונה. בנוסף, ניצור משתנה שיחזיק את ערך צבע הרקע, למשתנה הזה נקרא bgcolor והוא יהיה מסוג int.

 

בפוקנציית ה ()setup:

בדיוק כמו ל Arduino גם ל Processing יש פונ’ setup. כאן נפתח חיבור טורי ל Arduino, ונגדיר כמה פרמטרים שנשתמש בהם מאוחר יותר בתוכנית. בדרך כלל Processing עובדת בצבעים עם RGB, אך ניתן לשנות את הדרך שבה היא מעבדת את המידע של הצבעים. בפרויקט הזה נעבוד עם מוד צבע הנקרא HSB שמסמל גוון (Hue), רוויה (Saturation), ובהירות (Brightness). כשנזיז את הפונציומטר המחובר ל Arduino נשנה את הגוון (Hue) של צבע הרקע של תמונת ה PNG.

דבר ראשון הוא לקבוע את ערך ההתחלה של צבע הרקע, עם הפונ’ ()colorMode שמקבלת 2 פרמטרים, הראשון הוא סוג המוד של הצבע, והשני הוא הערך המקסימלי שעליה לצפות לו. בנוסף, עלינו לטעון את התמונה לתוכנית שלנו. נטען אותה מהכתובתhttp://arduino.cc/logo.png בעזרת הפונ’ ()loadImage ונשמור אותה באוביקט שיצרנו במיוחד בשביל התמונה (logo). לאחר מכן עלינו להגיד ל Processing מה גודל החלון שעליו להציג, נעשה זאת עם הפונ’ ()size, ונספק לו את הרוחב והגובה של התמונה (באוביקט logo).

ולבסוף ניצור אובייקט של החיבור הטורי ונכניס אותו לתוך myPort (היצירה של האובייקט מתבצעת ע”י כתיבת המילה השמורה new ולאחריה האובייקט (Serial) והפרמטרים שהבנאי שלו מקבל (הראשון הוא עם איזה יישום האובייקט ידבר, לכן אנו מכניסים this, השני הוא על איזה פורט סיריאלי הוא יבצע את התקשורת, במקרה שלנו אנו מבקשים את הרשימה עם ()Serial.list, הרשימה תוחזר בדמות של מערך ( Array), ולכן אנו מבקשים את האיבר הראשון בתוך סוגרים מרובעים [0] (במחשבים האיבר הראשון הוא תמיד 0 ולא 1, והסוגריים המרובעים משמשים למיקום איבר במערך), ולבסוף באיזה מהירות הוא יתקשר עם היישום).

 

בפונקציית ה ()draw:
פונקציית ה draw היא המקבילה ל loop ב Arduino, בכך שהיא מתבצעת שוב ושוב עד אין סוף. כאן אנו מתארים את הדברים שיצטיירו על החלון של התוכנית. דבר ראשון שנעשה הוא לבדוק האם קיבלנו בכלל מידע מה Arduino ע”י משפט if. הפקודה ()available של האוביקט myPort תחזיר לנו את גודל של ה serial buffer, אם הגודל שלו גדול מ-0, סימן שיש שם משהו. לכן נקרא את הבתים (bytes) לתוך משתנה הרקע (bgcolor) בעזרת הפקודה ()read על האוביקט myPort, ולאחר מכן נדפיס לנו את הערך לחלון ה debug (רק כדי לוודא שהכל תקין).

הפונקציה ()background קובעת את הצבע של החלון (הרקע של התמונה הוא שקוף, לכן הצבע של החלון יהיה צבע הרקע של התמונה). הפונ’ מקבלת 3 פרמטרים: הראשון הוא הגוון (hue), השני הוא הבהירות (brightness) והשלישי הוא הרוויה (saturation). נשתמש בערך שקלטנו מה Arduino ושמרנו במשתנה bgcolor כדי לקבוע את הגוון (hue, הפרמטר הראשון). ואת הבהירות והרוויה נקבע לערך המקסימלי, הלא הוא 255, באופן קבוע. לבסוף אנו צריכים לצייר את הלוגו על המסך (אחרי שטענו אותו ושמרנו אותו במשתנה logo), ונעשה זאת עם הפונ’ ()image המקבלת גם היא 3 פרמטרים: הראשון את התמונה (במקרה שלנו נכניס logo), והפרמטר השני והשלישי אלה נקודות הגובה והרוחב שבהם התמונה תמוקם. מכיוון שאנו רוצים אותה מתחילת המסך, נכניס 0 ו-0.

import processing.serial.*;
Serial myPort;
PImage logo;
int bgcolor = 0;

void setup(){
    colorMode(HSB, 255);
    logo = logoImage("http://arduino.cc/logo.png");
    size(logo.width, logo.height);
    myPort = new Serial(this, Serial.list()[0], 9600);
}

void draw(){
    if(myPort.available() > 0){
        bgcolor = myPort.read();
        println(bgcolor);
    }
    beckground(bgcolor, 255, 255);
    image(logo, 0, 0);
}

 

לסיכום

בפרויקט הזה התמקדנו בלמידת תוכנית חדשה בשם Processing, השפה דומה לזו שנו משתמשים ב Sketch (ה IDE של Arduino), אך מספיק שונה בשביל שנצטרך לדבר עליה ולהתנסות קצת. הפן הפיזי בפרויקט הזה היה קטן, כמו גם תכנות ה Arduino. אך התמקדנו בעיקר בתקשורת שבין התוכנות על מנת להשפיע בעזרת ה Arduino על תוכנית חדשה ושונה לגמרי שמבצעת דברים אחרים, במקרה הזה במחשב שלנו, אך את המידע ניתן להעביר גם על גבי האינטרנט ולהשפיע על תוכנית הנמצאת במחשב / בשרת מרוחק. וודאו שאתם מבינים כיצד בנינו וכתבנו את הפרויקט מכיוון שהוא מהווה קפיצת מדרגה משמועתית ובסיס לפרויקטים עתידים. כעת, נפתח בפנינו עולם חדש של אפשרויות לתקשר עם המכשירים שסביבנו ולשלוט בהם.