הפרויקט הקטנטן שיוצג כאן הוא תוצר לוואי של תוכנית גרנדיוזית יותר, שמצריכה בין השאר מדידה של מרחק בין חיישן לבין כדור טניס שמתגלגל מולו. אלתרתי את המערכת ואת התוכנה שלה בזריזות, רק כדי לבדוק אם חיישן אולטרה-סוני מסוגל בכלל להתמודד עם כדורי טניס. הסתבר שהוא לא (וזה הגיוני, כי צורת הכדור מפזרת גלי קול לכל עבר במקום להחזירם ישירות, והשערות הרכות שמכסות כדורי טניס מפריעות גם כן להחזרה). אף על פי כן, זו היתה הזדמנות להתנסות בעבודה עם רכיב MAX7219 לניהול תצוגות LED מסוג Seven Segment, ואולי המידע יסייע לחלק מהקוראים בפרויקטים שלהם.
אז קודם כל, הנה המערכת בפעולה:
רכיב החיישן מוכר לכל מי שעיין קצת בחומרים למתחילים בארדואינו. הוא כולל שני גלילים כסופים, אחד משדר ואחד מקלט, מעגל שמנהל אותם וארבעה פינים: מתח (5V), אדמה, הפעלה (Trig) ואות חוזר (Echo). בדגמים מסוימים, כמו זה שלי, יש פין חמישי בשם Out שלא נחוץ ולא צריך לחבר אותו לשום דבר.
החיישן
לחיישן זה טווח מוצהר של 3-300 סנטימטרים, אם כי בפועל, כל מה שמעבר למטר הוא בערבון מוגבל מאד. כדי להשתמש בחיישן צריך לתת מתח לזמן קצרצר לפין Trig (כ-10 מיליוניות השניה) כדי להפעיל אותו, לחכות בסבלנות שיופיע מתח בפין Echo ולמדוד את משך הזמן (במיליוניות השניה) עד שהמתח הזה מפסיק, החיישן דואג שמשך הזמן הזה יהיה זהה למשך הזמן שנדרש לקול לעבור את המרחק מהחיישן לאובייקט ובחזרה, ולפי זה אפשר להסיק את המרחק בסנטימטרים. הנה פונקציה לארדואינו שמבצעת את כל זה (הפונקציה המובנית pulseIn היא זו שדואגת להמתנה ולמדידת הזמן ב-Echo):
int getDistance() { unsigned long pulseTime; digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); pulseTime = pulseIn(ECHO_PIN, HIGH, 18000); return pulseTime/59; }
למה מחלקים ב-59 בסוף? חשבון פשוט. מהירות הקול, בגובה פני הים, היא 340.29 מטרים בשניה, או 34,029 סנטימטרים בשניה. שניה אחת היא כמובן מיליון מיליוניות השניה, אז אם נחלק מיליון ב-34,029 נקבל משהו כמו 29.3867 מיליוניות השניה לסנטימטר אחד. אבל כדי שההד של הצליל יגיע למיקרופון הוא צריך לעשות דרך כפולה: מהרמקול אל המטרה, ומהמטרה בחזרה אל המיקרופון. זאת אומרת, 58.7734 מיליוניות השניה לסנטימטר אחד של מרחק בפועל, ולא נורא אם נעגל ל-59.
התצוגה
את המידע שמתקבל ומפוענח בחרתי להציג על רכיב LED עם ארבע ספרות בתצורת שבעה מקטעים. דיברתי על רכיבים כאלה כאן, ולכן לא אחזור על הפרטים שוב – רק אציין שהרכיב הספציפי שמופיע בסרטון למעלה הוא מסוג Common Cathode, כלומר שה"רגל" המשותפת לכל נוריות ה-LED שמרכיבות ספרה מסוימת היא רגל ה"מינוס". יש רכיבים שבהם דווקא ה"פלוס" היא המשותפת (Common Anode), אך כאן הייתי זקוק למינוס בגלל הרכיב הבא-
מנהל התצוגה
תפעול רכיב ה-LED לא נעשה ישירות על ידי המיקרו-בקר, אלא בתיווך של מעגל משולב בשם MAX7219CNG. ג'וק זה כולל רגליים שמתחברות לרגלי רכיב ה-LED (עד שמונה ספרות, כולל אלמנט הנקודה העשרונית), והוא מטפל בעצמו בכל נושא הכיבוי וההדלקה של נוריות ה-LED השונות. כל מה שאנחנו צריכים זה לומר לו, באמצעות פקודות שמועברות בחיבור טורי, איזה מספר (או סמל) אנחנו רוצים לראות על ספרה מסוימת בתצוגה, והוא ידאג לכל השאר. כאמור, הג'וק הזה מותאם לרכיבי LED בעלי Common Cathode, ואם נחבר אותו לסוג השני פשוט לא נראה כלום.
נשמע קל, נכון? אבל הפקודות של מנהל התצוגה לא מובנות מאליהן, וצריך להריץ מספר פקודות אתחול כדי שהוא יעבוד כמו שאנחנו מצפים (שלא לדבר על האפשרויות המתקדמות יותר שלו, כגון שינוי קצב הסריקה שגורם לספרות להיראות בהירות או כהות יותר). זה יכול להיות תרגיל מצוין בקריאה ויישום של Datasheet – המפרט הטכני שקישרתי אליו לפני רגע – אך למתחילים כדאי מאד לעבוד קודם כל ישירות עם רכיב LED שכזה, כדי להבין את עקרון הפעולה שלו ולקבל תמונה טובה יותר של מה שמנהל התצוגה עושה מאחורי הקלעים.
לא כל כך הבנתי איך התוכנה מחשבת את המרחק
של הגוף מהחיישן הרי לתוך הארדואינו נקלט משך זמן המעוף ואז
כתוב בהסבר על מהירות ושאנחנו מתאימים אותה ליחידות שהפעלנו את הפולס
מה שלא הבנתי איך מחילוק הזמן במהירות מתקבל המרחק
אשמח אם תוכל להסביר לי
החילוק הוא לא של [זמן] ב[מהירות], אלא של [זמן המעוף] ב[זמן הקבוע שנדרש כדי לעבור סנטימטר אחד].
לדוגמה, אם המעוף לקח 531 מיליוניות שנייה (הלוך ושוב ביחד), ואנחנו יודעים שבמהירות הקול צריך 59 מיליוניות שנייה כדי לעבור סנטימטר אחד הלוך ושוב, נחלק 531 ב-59 ונקבל 9, שזה מספר הסנטימטרים בין החיישן למכשול.
משהו קצת לא מובן לי עם הקוד שנתת. לפי מה שזכור לי הפונקציה pulseIn מחזירה את אורך הפולס, לפי הערך שנתת כפרמטר. כלומר, אם קראת לפונקציה עם HIGH, היא תחכה לערך HIGH, תתחיל לספור ותסיים ברגע שיתקבל LOW. כלומר הקוד שנתת ימדוד את אורך הפולס ששידרנו לפני כן (10us). איפה הטעות שלי?
הקוד נכון, אבל הסברתי אותו לא נכון. אני מתקן את ההסבר ברגעים אלו ממש. תודה ששמת לב!
אתה יכול לגלות מרחק בדיוק רב בעזרת Hokuyo UTM-30LX laser rangefinder
תראה את הסרטון הבא, בו השתמשו ברכיב זה:
http://www.youtube.com/watch?v=kYs215TgI7c&feature=player_embedded
במחיר שהרכיב הזה עולה, אני כבר מעדיף למדוד בעצמי עם סרגל… 🙂