תקשורת אלחוטית בין יחידות עם DA14531MOD – חלק ב'

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

מודולי DA14531MOD ארוזים
מודולי DA14531MOD ארוזים

כלי העבודה

בפוסט הקודם בחרתי לצרוב למודולים את הקושחה המוכנה-מראש "Standalone Set Two", כי היא היחידה שמספקת מידע RSSI (אינדיקציה לעוצמת אות נקלט), וזה מידע שימושי מאוד. הקושחה הזו מכירה עוד כמה פקודות חמודות שבלעדיוֹת לה, כגון הפעלת טיימר פנימי להרצת פקודות ששמרנו מראש, או תקשורת עם רכיב חיצוני בפרוטוקול I2C. אבל יש משהו מאוד שימושי אחר שהיא דווקא לא מכירה: הפקודות לפתיחת ערוץ העברת מידע גולמי, "בינארי". אפילו פקודת AT+PRINT, שהייתה מאפשרת לנו לכתוב מחרוזות טקסט ישר ל-UART, לא נתמכת כאן. אז בהנחה שאנחנו לא מחליפים קושחה, איך כן אפשר להעביר בייטים בין יחידות?

לפי שאציג את התשובה, בואו נדמיין ש-AT+PRINT כן עובדת לנו: פשוט נכתוב ATr+PRINT בתוספת מחרוזת כלשהי, ותוך זמן קצרצר אותה מחרוזת בדיוק תופיע ב-TX של המודול המרוחק. האם זה אידאלי? לא לגמרי, כי זה אומר שה-TX ההוא משחק תפקיד כפול: גם משוב לפקודות מקומיות, וגם צינור לנתונים מרחוק. אמנם הבייטים עצמם לא יתערבבו, כי הקושחה תריץ מן הסתם את הפקודות שקיבלה לפי תור מסודר – לא משנה מאיפה הגיעו. ובכל זאת, ברמת המיקרו-בקר המנהל, נצטרך להקדיש יותר תשומת לב לקלט מהמודול, שיכול להגיע בכל רגע.

אפרופו צינור, זמן קצר אחרי שכתבתי את הפסקאות הקודמות גיליתי את הפקודה pipe – פשוט הסימן "|", ללא "AT", ואחריו מחרוזת. היא תישלח מיד לצד השני, ותופיע שם ב-TX כשלפניה שני התווים CR (מס' 13) ו-LF (מס' 10), בסדר הזה. הבעיה של התפקיד הכפול של TX נשארת בעינה.

מה שיכול לעזור לנו מאוד הוא שילוב של שני אלמנטים: 1) מקום לאחסן בו את הנתונים הנכנסים עד שיהיה למיקרו-בקר נוח לקרוא אותם, ו-2) איזושהי אינדיקציה לכך שהגיעו לאחסון נתונים שצריך לקרוא. ובכן, תשמחו לשמוע שהקושחה Set Two נותנת לנו בדיוק את הדברים האלה. למעשה, את (2) כבר ראינו: הרי הפין שהגדרנו כפלט לא חייב להדליק לד, הוא יכול במקום זה לעורר פסיקה אצל המיקרו-בקר המרוחק!

בשביל אחסון הנתונים יש לנו את הפקודה AT+MEM. בקושחה מוגדרים (ב-SRAM) ארבעה מערכים של 100 תווים כל אחד, ואנחנו יכולים לכתוב ולקרוא מחרוזות מתוכם כרצוננו. כלומר, כדי להעביר מחרוזת, אני אשתמש קודם כל ב-ATr+MEM כדי לכתוב את המחרוזת למודול ה-BLE המרוחק, ולאחר מכן ב-ATr+IO כדי לשנות מצב של פין וכך להודיע למיקרו-בקר המרוחק שהמודול שומר עבורו מחרוזת חדשה. הפקודות האלה פועלות גם מצד המודול שמוגדר כ-Central וגם מצד המודול ה-Peripheral, כך שהשיטה הזו היא דו-סטרית. עלינו רק לוודא שהנתונים מותאמים לפורמט טקסט, ושהמחרוזות שאנחנו שולחים לא ארוכות מדי. בואו נבנה פרויקט הדגמה קטן שמבוסס על הטכניקה הזו.

"כמה אור אצלך?" – פרויקט הדגמה

למען התאימות החשמלית עם המודולים שעובדים ב-3V3, השתמשתי בזוג לוחות Xiao RP2040 בתור המיקרו-בקרים המנהלים. כל אחד מהם מודד פעם בשנייה את רמת התאורה בסביבתו (באמצעות מחלק מתח עם נגד תלוי-אור), ומעביר את הנתונים דרך מודולי ה-BLE אל הלוח האחר, שממיר אותם לעוצמת בהירות של ה-Neopixel המובנה שלו. במילים אחרות, לוח א' יציג את רמת התאורה שיש סביב לוח ב', ולהיפך.

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

הדגמה של העברת מידע על עוצמת אור בין מודולים
הדגמה של העברת מידע על עוצמת אור בין מודולים (לחצו לתמונה גדולה)

כדי ליצור את ההדגמה הזו כמה שיותר מהר, קצת "רימיתי" וביצעתי את ההגדרה המקדימה של המודולים, כולל קביעת צד ה-Central ופעולת ה-Connect, באופן ידני. יש להם סוללות, אז ההגדרות נשמרו לאורך כל הבנייה והניסוי. זה אומר גם שהקוד ללוחות ה-Xiao בשני הצדדים היה זהה לחלוטין, כי הוא לא היה צריך לטפל בהגדרות האלה.

לא אכנס כאן לכל פרטי הקוד, שנכתב ב-MicroPython. בגדול, הגדרתי טיימר שמריץ פעם בשנייה פונקציה. הפונקציה הזאת קוראת את רמת התאורה ושולחת את הערך (דרך מודול ה-BLE) לאחסון במערך מס' 0 במודול השני. כיוון שפקודות ה-AT הן מחרוזות טקסט, אי אפשר לשלוח את הערך הבינארי הגולמי – צריך להמיר אותו לייצוג טקסטואלי, למשל באמצעות str. מיד לאחר מכן, הפונקציה שולחת פקודה "להדליק" את פין 11 במודול המרוחק, כאינדיקציה למידע החדש. שימו לב ל-"r" שמצורף לכל "AT" כאן – זה מה שמריץ את הפקודות על המודול המרוחק.

s = 'ATr+MEM=0,' + val_str + chr(13) uart0.write(s) uart0.write('ATr+IO=11,1'+chr(13))

בזמן שהקוד לא מריץ את הפונקציה הזו, הוא מנטר בלולאה את המצב של פין 11 של המודול הקרוב. אם הוא מזהה שם מתח – אינדיקציה לכך שהגיעה מחרוזת חדשה – הוא שולח למודול פקודת AT+MEM לקריאת המחרוזת הזאת (דרך ה-UART), ואחרי זה שולח פקודה להחזיר את פין 11 למצב LOW. כאן הפקודות הן AT בלי r, כדי שירוצו על המודול הקרוב:

uart0.write('AT+MEM=0'+chr(13)) # ... uart0.write('AT+IO=11,0'+chr(13))

החלק שסימנתי כהערה עם שלוש נקודות הוא, כמובן, הקליטה והפענוח של המחרוזת שמגיעה כתשובה לפקודת ה-MEM. כאן צריך לשים לב לתווים לא רלוונטיים (מס' 10 ו-13), למחרוזת אישור הביצוע ("OK") ול-echo של הפקודה עצמה, אם שכחנו לנטרל אותו קודם בעזרת ATE=0.

צריכת חשמל

את המספרים הבאים קיבלתי במדידות בשטח באמצעות ה-Joulescope. כאשר מחברים את מודול ה-BLE לחשמל, הוא נכנס למצב Advertising. במצב זה הוא צורך כ-0.8mA. פעם ב-0.7 שניות הוא משדר מידע למשך כ-1.5 אלפיות שנייה, ואז הצריכה עולה, בפרצים קצרים מאוד, עד כ-3-4 מיליאמפר.

לאחר שמתבצע Connect, הצריכה הממוצעת של שני הצדדים יורדת – בהערכה גסה,הם צורכים 0.1-0.3 מיליאמפר, עם קפיצות קטנות לשידור כל 15 אלפיות שנייה.

מסקנות ביניים

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

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