איך הוספתי ממשק סריאלי ללוח ממסרים

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

לוח הממסרים המשופר
לוח הממסרים המשופר

הלוח והבעיה

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

אלא שהקוד לא מדמה מתאם סריאלי (USB-to-UART), כמו שקיים למשל בארדואינו. כשחיברתי אותו למחשב, מנהל ההתקנים הקצה לו דווקא את הדרייבר של digiUSB, שהיה מותקן אצלי מפרויקט קודם. אוקיי, אז עכשיו אנחנו יודעים מאיפה הסינים אימצו את הקוד שלהם… אבל מה עושים עם זה? צריך לחפש תוכנה ייעודית שכבר יודעת איך לדבר עם הלוח – ולא מצאתי כזו אצל המוכרים בעליאקפרס – או לחפש ולהוריד קובצי dll וספריות שאמורים להתאים ולנסות לכתוב על בסיסם תוכנה בעצמי. לא מפתה במיוחד. זה הזמן לגלות קצת יצירתיות.

פיצוח ראשון: שליטה מקומית

מצאתי ב-Datasheet את מיפוי הפינים של ה-ATmega8 והתחלתי לעקוב אחרי החיבורים שלו לשאר הלוח. הפינים PC0-PC5 ו-PD0-PD1 מחוברים, דרך ה-ULN, לממסרים עצמם. לרוע המזל, PD0 ו-PD1 הם גם אלה שמוקצים לחומרת ה-UART המובנית של המיקרו-בקר, כך שלא אוכל לנצל אותה. נו מילא.

הפינים PB0 ו-PB1 מתחברים לקווי הנתונים של חיבור ה-USB, אז הם יכולים בעיקרון להוות ממשק נוח יחסית עם העולם החיצון, ומה שהכי מעניין, הפינים PB2-PB5 מתחברים לחורים לא מאוכלסים לצד הג'וק. למה זה מעניין? כי אלה הפינים של חומרת ה-SPI, שדרכה אני יכול גם לצרוב קוד חדש. הדבר היחיד שחסר לי בשביל צריבה נוחה הוא גישה לפין ה-RESET.

חיברתי שורת headers לחורים הנ"ל, עם פין אחד נוסף שאותו הלחמתי, בתיווך של חוט נחושת מבודד דקיק, אל פין ה-RESET היתום. כמו כן, לקחתי כבל USB ישן, חתכתי באמצע, חשפתי את החוטים שבו והתאמתי להם ראשים נוחים של Jumper Wires. כשלב ראשון, זה נתן לי גישה נוחה לאדמה ול-5V של המיקרו-בקר (מקור החשמל של הלוח כולו הוא חיבור ל-12V).

הלוח עם הפינים לצריבה והחיבור ל-RESET (מימין למיקרו-בקר שבאמצע)

הלוח עם הפינים לצריבה והחיבור ל-RESET (מימין למיקרו-בקר שבאמצע, ליחצו להגדלה)

חיברתי את כל החוטים האלה לצורב AVRISP MKII הישן שלי, הפעלתי את סביבת הפיתוח Atmel Studio 7 – ובלי שום בעיה התחברתי למיקרו-בקר. לפני הכול חילצתי ממנו, לצורכי גיבוי ושחזור במקרה הצורך, את הקוד הצרוב על ה-Flash ואת הנתונים מה-EEPROM. הסינים לא טרחו לצרוב פיוזים להגנה כלשהי על המערכת.

כתבתי תוכנה קטנה דמוית Blink עבור ה-ATmega8, שמעלה מתח כל פעם בפין אחר מתוך השמונה שמחוברים ל-ULN. צרבתי אותה ללוח, ואכן הממסרים החלו לתקתק בשמחה. אפרופו, ליד המיקרו-בקר יש מתנד גביש בערך של 12MHz, הנפוץ במערכות Embedded שעובדות עם USB. זוהי מהירות השעון של המיקרו-בקר – פרט חשוב לתזמונים שיבואו בהמשך.

פיצוח שני: מידע סריאלי

כדי לשלוט בלוח – ממחשב, ארדואינו או כל מקור דיגיטלי אחר – אני צריך אמצעי קלט. בחרתי להשתמש ב-PB1, אחד הפינים שמחוברים ליציאת ה-USB, ובפורמט הרגיל והנפוץ ביותר של UART (במהירות שידור קבועה של 9600 ביט לשנייה). כדי לחסוך זמן מימשתי את הקליטה בצורה הגסה והפשטנית ביותר שאפשר: מרגע שזוהתה ירידת מתח בפין הקלט (שמעידה על ביט התחלה), פשוט חיכיתי בעזרת לולאה של פקודות דמויות delayMicroseconds עד לאמצע משך הזמן הצפוי של כל אחד משמונת הביטים של הנתונים, קראתי אותם מ-PB1 וכתבתי אותם בבייט בזיכרון.

אחרי תיקון של שני באגים מטופשים שלי בקוד, גם החלק הזה עבד מצוין. למשל, כששלחתי את המספר ההקסדצימלי 0x55 (שזה 85 בבסיס עשר) רק הממסרים האי-זוגיים נדלקו (אם מתחילים את הספירה מ-1 ולא מ-0!), ואילו כששלחתי את  0xAA, רק הזוגיים נדלקו.

החיבורים בין פיני הנתונים של כניסת ה-USB לבין המיקרו-בקר
החיבורים בין פיני הנתונים של כניסת ה-USB לבין המיקרו-בקר

שפצור אחרון: טיפה בטיחות

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

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

זהו, הכול מוכן – וכמובן, אם רוצים לעבוד עם הלוח בשליטה ממחשב צריך להוסיף למערכת מתאם USB-to-UART חיצוני פשוט, ולכתוב תוכנת דסקטופ שמשדרת את ה"סיסמה" ואת הנתונים.

להרשמה
הודע לי על
0 Comments
Inline Feedbacks
הראה את כל התגובות