מדור פרסומי: 4Probot – פרק שלישי

זוכרים את 4Probot, רובוט ההדגמה והניסוי שנבנה בשיתוף עם אתר 4project.co.il? העבודה עליו הוקפאה לזמן ממושך בגלל עניינים אחרים, אך הפרויקט לא בוטל. כעת, אחרי ניעור של שכבות האבק שהצטברו, הרובוט חוזר ובגדול – עם ג'ויסטיק אלחוטי לשליטה מרחוק!

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

מה נשתנה

לפני שניגש לג'ויסטיק, ראוי לציין את השינוי המשמעותי שנעשה ברובוט מאז הפרק הקודם: הותקן בו לוח תואם Arduino Pro Mini שני. הלוח הראשון יטפל, כפי שעשה עד כה, בהפעלת המנועים, הפנסים ושאר החלקים הפיזיים הבסיסיים. הלוח החדש ישמש לבקרה וניהול "גבוהים" ולתקשורת עם גורמים חיצוניים, כולל שליטה מרחוק כפי שיוצג בפרק זה.

התקשורת בין שני הלוחות ברובוט מתבצעת באמצעות הצלבת ה-UART (פינים RX/TX) שלהם, כך שלמעשה הקוד שמטפל בתקשורת "פנימית" זו מבוסס על אובייקט ה-Serial המובנה של ארדואינו.

הג'ויסטיק

הג'ויסטיק מבוסס על מגן Arduino Joystick – לוח PCB ייעודי בתצורת Shield של ארדואינו, מבית Sparkfun. ללוח זה מלחימים לבד את הרכיבים הדרושים ליצירת הג'ויסטיק – מודול ג'ויסטיק קטן ("בוהן") בסגנון PS2, ארבעה לחצנים 12mm, וכן headers לחיבור ללוח הארדואינו ולחצן 6mm לאיפוס. לי היו רכיבים כאלה מבעוד מועד, ולכן הזמנתי את ה-PCB בלבד. מי שרוצה יכול להזמין ב-4Project גם סט שכולל את כל הרכיבים.

PCB למגן ג'ויסטיק לארדואינו
PCB למגן ג'ויסטיק לארדואינו. מימין, הרכיבים הנוספים הדרושים.

המגן הזה מחבר בין רכיבי הג'ויסטיק לבין הפינים של הארדואינו באופן הבא:

  • ציר X –> פין A0 (אנלוגי)
  • ציר Y –> פין A1 (אנלוגי)
  • לחצן בחירה (לחיצה אנכית על הג'ויסטיק) –> פין 2
  • לחצן עליון –> פין 4
  • לחצן תחתון –> פין 5
  • לחצן ימין –> פין 3
  • לחצן שמאל –> פין 6

חשוב להזכיר שהלחצנים למעשה מקצרים את פין הארדואינו לאדמה, כך שיש להגדיר את הפינים לקלט עם נגד Pull-up (אפשר פנימי), ולפרש קלט LOW כלחיצה וקלט HIGH כלא-לחיצה.

הפלט האנלוגי של הג'ויסטיק מבוסס על פוטנציומטרים שמותקנים בצירי X ו-Y. לכן, ערך 0 פירושו הטיה מלאה לכיוון אחד (שמאלה או למטה), ערך 1023 פירושו הטיה מלאה לכיוון ההפוך (ימינה או למעלה), וערכי ביניים מייצגים הטיה חלקית.

מגן הג'ויסטיק המורכב
מגן הג'ויסטיק המורכב

מכיוון שהשליטה ברובוט תהיה אלחוטית, הוספתי לעסק משדר RF בסיסי מהסוג הזול והנפוץ (RF Kit, 433MHz). למען המודולריות ופרויקטים עתידיים הרכבתי אותו על מגן נפרד, שממוקם בין הארדואינו לג'ויסטיק כמו סנדביץ', אבל כמובן שזה לא הכרחי. המשדר מקבל חשמל ברציפות מהארדואינו ופין הנתונים שלו מחובר לפין 12 בארדואינו.

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

שידור: מה ואיך

הקוד עבור הארדואינו שמחובר לג'ויסטיק פשוט למדי: הוא קורא שוב ושוב את הערכים ממגן הג'ויסטיק ומצמצם אותם לתוך שני בייטים.הצמצום נעשה כך: בבייט הראשון נשמרים ערכי הלחצנים, ביט אחד לכל לחצן, ובבייט השני נשמרות הקריאות האנלוגיות מצירי הג'ויסטיק, אחרי סילוק של ששת הביטים התחתונים, הפחות-חשובים, מכל קריאה – מה שמשאיר ארבעה לציר X וארבעה לציר Y.

הצמצום נועד למזער את זמן השידור – הרי אין טעם לשלוח בייט שלם עבור כל לחצן, וגם לא שני בייטים לכל ציר של הג'ויסטיק כאשר מערכת ההנעה של הרובוט בכלל לא מסוגלת להגיע לרזולוציה כזו!

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

עוד נקודה חשובה היא אימות הנתונים. בתקשורת "גולמית", מומלץ תמיד להוסיף לשידור משהו שיאפשר לצד הקולט לאמת את המידע ולהבטיח שהקליטה התבצעה ללא שיבושים. במקרה שלנו, הספריה VirtualWire בה אשתמש כבר כוללת מנגנון בדיקה שכזה.

יחידת השידור במלואה, מבט מהצד
יחידת השידור במלואה, מבט מהצד

אופס, רגע

בבדיקות הראשוניות של העסק התגלתה בעיה: המשדר שידר כל הזמן במרווחים די קצרים, גם כשלא נגעתי בג'ויסטיק. הסתבר שהסיבה לכך היא חוסר הדיוק של הקריאה האנלוגית, או של רכיבי הג'ויסטיק עצמו, או של שניהם גם יחד: במצב מנוחה, כל ציר של הג'ויסטיק אמור לתת לי קריאה יציבה באמצע טווח הערכים האפשריים. עם זאת, יש "קפיצות" קטנות ואקראיות בקריאה, שרצות הלוך ושוב בין שני הערכים 511 ו-512, שהם למעשה שתי האופציות המעוגלות עבור האמצע האמתי שצריך להיות 511.5. בבינארי, המספרים האלה נראים כך:

  • 511 = 0111111111
  • 512 = 1000000000

ולכן, אף על פי שאני מקצץ את הקריאות ל-4 הביטים הכי חשובים בלבד (השמאליים), הקפיצות הזעירות מ-511 ל-512 ובחזרה נקלטות ונתפסות על ידי הקוד כבעלות משמעות (0111 לעומת 1000) ומשודרות לרובוט. כדי להתגבר על הבעיה, העברתי כל מדידה דרך פונקציית ייצוב פרימיטיבית: אם הערך מספיק קרוב ל-511 (פלוס מינוס 10, למשל), הפונקציה מחזירה 511 בדיוק – אחרת היא מחזירה את הערך כמו שהוא.

בעיה נוספת צצה כשניסיתי לשלוח את המידע מהג'ויסטיק גם אל ה-Serial Monitor: משהו שם פשוט לא עבד והמידע לא עבר. זה מדאיג וראוי לבדיקה, אבל יש לי דברים דחופים יותר לעשות, ומכיוון שידעתי שהמשדר כן עובד (שמעתי את ההפרעות שהוא יוצר ברמקולים!) החלטתי לעבור לשלב הבא – וידוא קליטה במקלט מאולתר.

רגע האמת

לקחתי לוח ארדואינו נוסף, חיברתי אליו את המקלט המתאים והעליתי אליו את הקוד הבא, שמקבל נתונים משודרים ופולט אותם ל-Serial Monitor. הקוד הזה הוא זמני ולא מתיימר להיות ברור במיוחד.

#include <VirtualWire.h>

const int receive_pin = 11;
struct tJSData { 
    uint8_t part[2]; 
  } reading;

void setup() {
  Serial.begin(9600);
  Serial.println("Getting ready...");
  vw_set_rx_pin(receive_pin);
  vw_setup(2000);     // Bits per sec
  vw_rx_start();       
  Serial.println("Waiting for input.");
}

void loop() {

  uint8_t len = 2;
  if (vw_get_message(reading.part, &len)) { 
    Serial.print("Got ");
    Serial.print(len);    
    Serial.print(" bytes: ");
    Serial.print(reading.part[0]);    
    Serial.print(", ");        
    Serial.println(reading.part[1], BIN);        
  }
  
}

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

להרשמה
הודע לי על
4 תגובות
מהכי חדשה
מהכי ישנה לפי הצבעות
Inline Feedbacks
הראה את כל התגובות

תוכל לפרט איך עובד התקשורת עם הRF ואיך הפקודות נשלחות ומתקבלות? תודה! 🙂

מה עדיף bluetooth או rf