תוכן עניינים:

Going Beyond Standard Firmata - מחדש: 5 שלבים
Going Beyond Standard Firmata - מחדש: 5 שלבים

וִידֵאוֹ: Going Beyond Standard Firmata - מחדש: 5 שלבים

וִידֵאוֹ: Going Beyond Standard Firmata - מחדש: 5 שלבים
וִידֵאוֹ: Top 10 Foods To Detox Your Kidneys 2024, יולי
Anonim
Going Beyond Standard Firmata - Revisited
Going Beyond Standard Firmata - Revisited

לפני זמן קצר יצרתי קשר עם ד"ר מרטין וילר, משתמש ב- pymata4, לקבלת הדרכה בהוספת תמיכה בחיישן הלחות/טמפרטורה DHT22 לספריית pymata4. ספריית pymata4, בשיתוף עם עמיתו Arduino, FirmataExpress, מאפשרת למשתמשים לשלוט ולפקח על מכשירי Arduino שלהם מרחוק. בתוך כמה סבבים של חילופי דוא"ל, ד"ר וילר הצליח לשנות הן את pymata4 והן את FirmataExpress. כתוצאה מכך, תמיכה בחיישני DHT22 ו- DHT11 היא כעת חלק סטנדרטי ב- pymata4 ו- FirmataExpress.

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

FirmataExpress מבוסס על StandardFirmata, ומבנה הספרייה StandardFirmata התפתח. בנוסף, ה- API של pymata4 שונה גם לא מעט מממשק ה- PyMata המקורי של 2014. חשבתי שזה הזמן המושלם לבקר ולעדכן את המאמר הזה. בעזרת שימוש בעבודתו של ד ר וילר כבסיס, בואו לחקור כיצד להרחיב את הפונקציונליות של pymata4/FirmataExpress.

לפני שנתחיל - קצת מידע רקע על Arduino/Firmata

אז מה זה Firmata? ציטוט מדף האינטרנט של Firmata, "Firmata הוא פרוטוקול כללי לתקשורת עם בקרי מיקרו מתוכנה במחשב מארח."

Arduino Firmata משתמש בממשק טורי להעברת מידע פיקודי ודיווח בין מיקרו -בקר Arduino למחשב, בדרך כלל באמצעות קישור טורי/USB המוגדר ל- 57600 bps. הנתונים המועברים דרך הקישור הזה הם בינארי, והפרוטוקול מיושם במודל לקוח/שרת.

צד השרת מועלה למיקרו בקר Arduino בצורה של סקיצה של Arduino. מערכון StandardFirmata, הכלול ב- IDE של Arduino, שולט בסיכות הקלט/פלט של Arduino, כפי שהלקוח פקוד עליו. הוא גם מדווח ללקוח על שינויי סיכת קלט ומידע אחר על דיווח. FirmataExpress היא גרסה מורחבת של StandardFirmata. הוא פועל במהירות קישור טורי של 115200 bps.

לקוח Arduino המשמש למאמר זה הוא pymata4. זהו יישום Python המבוצע במחשב. הוא גם שולח פקודות ומקבל דוחות מהשרת Arduino. מכיוון ש- pymata4 מיושם ב- Python, הוא פועל במחשבי Windows, Linux (כולל Raspberry Pi) ומחשבי macOS.

למה להשתמש ב- Firmata?

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

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

מדוע להשתמש ב- pymata4?

בהיותי המחבר שלה, כמובן, אני משוחד. עם זאת, זהו לקוח Firmata היחיד המבוסס על פייתון שנשמר ברציפות במהלך השנים האחרונות. הוא מספק ממשק API אינטואיטיבי וקל לשימוש. בנוסף לסקיצות מבוססות StandardFirmata, הוא תומך ב- Firmata באמצעות WiFi למכשירים כמו ESP-8266 בעת שימוש בסקיצה StandardFirmataWifI.

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

שלב 1: הבנת פרוטוקול Firmata

הבנת פרוטוקול Firmata
הבנת פרוטוקול Firmata

פרוטוקול התקשורת של Arduino Firmata נגזר מפרוטוקול MIDI, שמשתמש בבת אחת או יותר של 7 סיביות לייצוג נתונים.

Firmata תוכנן כך שניתן להרחבה על ידי משתמשים. המנגנון המספק הרחבה זו הוא פרוטוקול העברת ההודעות System Exclusive (SysEx).

הפורמט של הודעת SysEx, כהגדרתו בפרוטוקול Firmata, מוצג באיור לעיל. זה מתחיל בתא START_SYSEX עם ערך קבוע של 0xF0 הקסדצימלי, ואחריו בייט פקודה SysEx ייחודי. הערך של בית הפקודה חייב להיות בטווח הקסדצימלי 0x00-0x7F. לאחר מכן, בייט הפקודה ואחריו מספר לא מצוין של בתים של 7 סיביות. לבסוף, ההודעה מסתיימת עם בייט END_SYSEX, עם ערך קבוע של 0xF7 הקסדצימלי.

קידוד/פענוח נתוני Firmata

מכיוון שחלק נתוני המשתמש בהודעת SysEx מורכב מסדרה של בתים של 7 סיביות, אתה עשוי לתהות כיצד אחד מייצג ערך גדול מ- 128 (0x7f)? Firmata מקודד ערכים אלה על ידי פירוקם לחתיכות בתים רבות של 7 סיביות לפני שהנתונים מועברים על פני קישור הנתונים. הבייט הפחות משמעותי (LSB) של פריט נתונים נשלח תחילה, ואחריו רכיבים משמעותיים יותר ויותר של פריט הנתונים לפי מוסכמה. הבייט המשמעותי ביותר של פריט הנתונים הוא פריט הנתונים האחרון שנשלח.

איך זה עובד?

נניח שאנחנו רוצים לשלב ערך 525 בחלק הנתונים של הודעת SysEx. מכיוון שערך של 525 גדול יותר בערך של 128, עלינו לפצל או לפרק אותו ל"נתחים "של 7 ביט.

הנה איך זה מתבצע.

הערך של 525 בעשרוני שווה ערך לערך ההקסדצימלי של 0x20D, ערך של 2 בתים. כדי לקבל את ה- LSB, אנו מסווים את הערך על ידי AND'ing אותו עם 0x7F. הן יישומי "C" והן פייתון מוצגים להלן:

// יישום "C" לבידוד LSB

int max_distance_LSB = max_distance & 0x7f; // להסוות את הבייט התחתון # יישום Python כדי לבודד LSB max_distance_LSB = max_distance & 0x7F # להסוות את הבייט התחתון

לאחר מיסוך, max_distance_LSB יכיל 0x0d. 0x20D & 0x7F = 0x0D.

לאחר מכן, עלינו לבודד את MSB עבור ערך זה של 2 בתים. לשם כך, נעביר את הערך של 0x20D ימינה, 7 מקומות.

// יישום "C" לבידוד MSB בעל ערך 2 בתים

int max_distance_MSB = max_distance >> 7; // העבר את בית הסדר הגבוה # יישום Python כדי לבודד MSB של ערך 2 בתים max_distance_MSB = max_distance >> 7 # shift כדי לקבל את הבייט העליון לאחר הסטה, max_distance_MSB יכיל ערך של 0x04.

כאשר מתקבלים נתוני המרשל "הנתונים", יש להרכיבם מחדש לערך יחיד. כך אוספים את הנתונים מחדש הן ב- "C" והן בפייתון

// יישום "C" להרכיב מחדש את 2 הבייטים, // ערכי 7 סיביות לערך יחיד int max_distance = argv [0] + (argv [1] << 7); # יישום פייתון להרכיב מחדש את ערכי הסיביות של 2 בתים, # 7 לערך max_distance = data [0] + (data [1] << 7)

לאחר ההרכבה מחדש, הערך שוב שווה 525 עשרוני או 0x20D הקסדצימלי.

תהליך פירוק/הרכבה זה עשוי להתבצע על ידי הלקוח או השרת.

שלב 2: בואו נתחיל

תמיכה במכשיר חדש דורשת שינויים הן בשרת תושבי Arduino והן בלקוח Python תושב PC. עבודתו של ד ר וילר תשמש להמחשת השינויים הדרושים.

אולי השלב החשוב ביותר הוא להחליט אם ברצונך לשלב ספריית מכשירים תומכים קיימת בצד הארגואינו של המשוואה או לכתוב משלך. מומלץ שאם תוכל למצוא ספרייה קיימת, הרבה יותר פשוט להשתמש בה מאשר לכתוב משלך מאפס.

לתמיכה במכשירי DHT, ד"ר וילר ביסס את קוד ההרחבה שלו על ספריית DHTNew. בחוכמה רבה, ד"ר וילר פיצל את הפונקציונליות של ספריית DHTNew על פני הצדדים של Arduino ו- pymata4 של המשוואה כדי לספק חסימה מינימלית בצד Arduino.

אם נסתכל על DHTNew, הוא מבצע את כל הפעולות הבאות:

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

כדי לשמור על הדברים הכי יעילים שאפשר בצד FirmataExpress, ד ר וילר הוריד את שגרת המרת הנתונים מה- Arduino ל- pymata4.

שלב 3: שינוי FirmataExpress לתמיכת DHT

עץ מדריכי FirmataExpress

להלן כל הקבצים המרכיבים את מאגר FirmataExpress. עץ זה זהה לזה של StandardFiramata, רק שחלק משמות הקבצים משקפים את שם המאגר.

הקבצים הדורשים שינוי הם אלה שיש להם כוכבית (*) לידם.

FirmataExpress

├── * Boards.h

├── דוגמאות

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LICENSE.txt

Ef └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

בואו נסתכל על כל אחד מהקבצים ועל השינויים שבוצעו.

Boards.h

קובץ זה מכיל הגדרות מאקרו מסוג pin עבור כל אחד מסוגי הלוח הנתמכים. הוא מגדיר את המספר המרבי של מכשירים הנתמכים כאשר יש צורך לתמוך ביותר ממכשיר אחד.

עבור מכשיר DHT, ניתן לחבר עד 6 מכשירים בכל פעם וערך זה מוגדר כ:

#ifndef MAX_DHTS

#הגדר MAX_DHTS 6 #endif

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

#הגדר IS_PIN_DHT (p) (IS_PIN_DIGITAL (p) && (p) - 2 <MAX_DHTS)

כמו גם מאקרו להגדרת המרת מספר סיכה.

#הגדר PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

קובץ זה מכיל את מספר גירסת הקושחה, שתרצה לשנות כדי לעקוב אחר איזו גירסה הטענת ב- Arduino שלך. הוא מכיל גם את ערכי הודעת Firmata, כולל הודעות Firmata SysEx.

יהיה עליך להקצות הודעה חדשה או קבוצת הודעות למכשיר שלך בקובץ זה. ל- DHT נוספו שתי הודעות. האחד מגדיר סיכה כסיכת "DHT", והשני, כהודעת כתב, בעת שליחת נתוני ה- DHT האחרונים ללקוח.

סטטי const int DHT_CONFIG = 0x64;

const סטטי int DHT_DATA = 0x65;

מצבי סיכה מצויינים גם בקובץ זה. עבור DHT, נוצר מצב סיכה חדש:

סטטי const int PIN_MODE_DHT = 0x0F; // סיכה מוגדרת ל- DHT

בעת הוספת מצב סיכה חדש, יש להתאים את TOTAL_PIN_MODES:

const סטטי int TOTAL_PIN_MODES = 17;

FirmataDefines.h

יש לעדכן קובץ זה כך שישקף את ההודעות החדשות שנוספו ל- FirmataConstants.h:

#ifdef DHT_CONFIG #undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // DHT request #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DfD_DE_DDE_DDE_DDE_DDE_DDE_DDE_DDE_DDE_DDE_DDE_DE_DDE_DDE_DDE_DDE_DDE_DDE_DDE_DE_DDE_DE_DODE_DDE_DDE:: PIN_MODE_DHT

FirmataExpress.ino

בדיון זה נסקור את "נקודות השיא" של השינויים שנעשו במערכון ארדואינו זה.

על מנת ש- FirmataExpress תומך בעד שישה מכשירי DHT בו זמנית, נוצרו 3 מערכים כדי לעקוב אחר כל אחד ממספר הסיכה המשויך של המכשיר, ערך WakeUpDelay שלו וסוג המכשיר, כלומר DHT22 או DHT11:

// חיישני DHT

int numActiveDHTs = 0; // מספר DHTs המצורפים uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

מכיוון ששני סוגי המכשירים דורשים כשתי שניות בין הקריאות, עלינו לוודא שאנו קוראים כל DHT פעם אחת בלבד במסגרת הזמן של 2 שניות. התקנים מסוימים, כגון מכשירי DHT וחיישני מרחק HC-SR04, ניגשים רק מעת לעת. זה מאפשר להם זמן לתקשר עם סביבתם.

uint8_t nextDHT = 0; // אינדקס ל- dht לקריאת המכשיר הבא

uint8_t currentDHT = 0; // עוקב אחר החיישן הפעיל. int dhtNumLoops = 0; // היעד מספר הפעמים דרך לולאה b4 גישה ל- DHT int dhtLoopCounter = 0; // מונה לולאה

הגדרה וקריאה של מכשיר ה- DHT

כאשר FirmataExpress מקבלת פקודה SysEx להגדרת סיכה לפעולת DHT, היא מוודאת כי המספר המרבי של התקני DHT לא חרג. אם ניתן לתמוך ב- DHT החדש, מערכי DHT מתעדכנים. אם סוג ה- DHT אינו ידוע, נוצרת הודעת מחרוזת SysEx ומועברת בחזרה ל- pymata4

מקרה DHT_CONFIG: int DHT_Pin = argv [0]; int DHT_type = argv [1]; if (numActiveDHTs <MAX_DHTS) {if (DHT_type == 22) {DHT_WakeUpDelay [numActiveDHTs] = 1; } אחרת אם (DHT_type == 11) {DHT_WakeUpDelay [numActiveDHTs] = 18; } אחרת {Firmata.sendString ("שגיאה: סוג חיישן לא ידוע, חיישנים תקפים הם 11, 22"); לשבור; } // בדוק את החיישן DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = סוג DHT; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

לאחר מכן מנסה FirmataExpress לתקשר עם מכשיר ה- DHT. אם יש שגיאות, היא יוצרת הודעת SysEx עם נתוני השגיאה ושולחת את הודעת SysEx בחזרה ל- pymat4. משתנה _bits מחזיק את הנתונים המוחזרים על ידי מכשיר ה- DHT לעיבוד נוסף על ידי pymata4 במידת הצורך.

Firmata.write (START_SYSEX);

Firmata.write (DHT_DATA); Firmata.write (DHT_Pin); Firmata.write (DHT_type); עבור (uint8_t i = 0; i> 7 & 0x7f); } Firmata.write (abs (rv)); Firmata.write (1); Firmata.write (END_SYSEX);

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

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // הכל בסדר }

אם הוגדרו מכשיר DHT אחד או יותר בפונקציית הלולאה של הסקיצה, אז מכשיר ה- DHT הבא נקרא. או שהנתונים התקפים או מצב השגיאה שלהם מוחזרים ל- pymata4 בצורה של הודעת SysEx:

if (dhtLoopCounter ++> dhtNumLoops) {if (numActiveDHTs) {int rv = readDhtSensor (nextDHT); uint8_t current_pin = DHT_PinNumbers [nextDHT]; uint8_t current_type = DHT_TYPE [nextDHT]; dhtLoopCounter = 0; currentDHT = nextDHT; if (nextDHT ++> = numActiveDHTs - 1) {nextDHT = 0; } if (rv == DHTLIB_OK) {// TEST CHECKSUM uint8_t sum = _bits [0] + _bits [1] + _bits [2] + _bits [3]; אם (_ ביטים [4]! = סכום) {rv = -1; }}} // שלח את ההודעה בחזרה עם מצב השגיאה Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (current_pin); Firmata.write (current_type); עבור (uint8_t i = 0; i <sizeof (_bits) - 1; ++ i) {Firmata.write (_bits ); // Firmata.write (_bits ;} Firmata.write (abs (rv)); Firmata.write (0); Firmata.write (END_SYSEX);}}

הקוד המשמש לתקשורת עם מכשיר DHT נגזר ישירות מספריית DHTNew:

int readDhtSensor (אינדקס int) {

// INIT BUFFERVAR כדי לקבל נתונים uint8_t mask = 128; uint8_t idx = 0; // EMPTY BUFFER // memset (_bits, 0, sizeof (_bits)); עבור (uint8_t i = 0; i 5 BYTES עבור (uint8_t i = 40; i! = 0; i--) {loopCnt = DHTLIB_TIMEOUT; while (digitalRead (pin) == LOW) {if (--loopCnt == 0) החזר DHTLIB_ERROR_TIMEOUT;} uint32_t t = micros (); loopCnt = DHTLIB_TIMEOUT; בעוד (digitalRead (pin) == HIGH) {if (--loopCnt == 0) החזר DHTLIB_ERROR_TIMEOUT;} אם ((micros ()-t)> 40) {_bits [idx] | = מסכה;} מסכה >> = 1; אם (mask == 0) // בתים הבאים? {Mask = 128; idx ++;}} החזר DHTLIB_OK;}

שלב 4: שינוי Pymata4 לתמיכת DHT

private_constants.h

כדי לתמוך ב- DHT, עלינו להוסיף לקובץ זה הן את הודעת ה- pin החדשה והן את הודעות SysEx:

# מצבי סיכה INPUT = 0x00 # סיכה מוגדרת ככניסה OUTPUT = 0x01 # סיכה מוגדרת כפלט ANALOG = 0x02 # סיכה אנלוגית במצב קלט אנלוגי PWM = 0x03 # סיכה דיגיטלית במצב פלט PWM SERVO = 0x04 # סיכה דיגיטלית במצב פלט סרוו I2C = 0x06 # סיכה כלולה בהגדרת I2C STEPPER = 0x08 # כל סיכה במצב צעד SERIAL = 0x0a PULLUP = 0x0b # כל סיכה במצב זרימה SONAR = 0x0c # כל סיכה במצב SONAR TONE = 0x0d # כל סיכה במצב צליל PIXY = 0x0e # שמור למצב מצלמה פיקסי DHT = 0x0f # חיישן DHT IGNORE = 0x7f # DHT SysEx הודעות פקודה DHT_CONFIG = 0x64 # פקודת config config DHT_DATA = 0x65 # תשובת חיישן dht

סוג הסיכה והפקודות SysEx שנוספו חייבים להתאים לערכים ב- FirmataConstants.h שנוספו ל- FirmataExpress.

pymata4.py

Pymata4 משתמשת במילון Python כדי לקשר במהירות הודעת Firmata נכנסת עם מטפל בהודעות. שמו של מילון זה הוא report_dispatch.

הפורמט של ערך מילון הוא:

{MessageID: [message_handler, מספר בייט הנתונים לעיבוד]}

ערך נוסף למילון לטפל בהודעות DHT נכנסות:

{PrivateConstants. DHT_DATA: [self._dht_read_response, 7]}

7 בתים הנתונים בהודעה הם מספר הסיכה הדיגיטלית של Arduino, סוג התקן DHT (22 או 11) ו- 5 בתים של נתונים גולמיים.

שיטת _dht_read_response בודקת אם יש שגיאות שדווחו. אם אין שגיאות מדווחות, הלחות והטמפרטורה מחושבים באמצעות האלגוריתם המועבר מספריית ה- Arduino DHTNew.

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

הגדרת התקן DHT חדש

בעת הוספת מכשיר DHT חדש נקראת שיטת set_pin_mode_dht. שיטה זו מעדכנת את pin_data עבור סיכות דיגיטליות. הוא גם יוצר ושולח הודעת DHT_CONFIG SysEx ל- FirmataExpress.

שלב 5: עטיפה

כפי שראינו, הוספת תמיכה ב- Firmata למכשיר חדש מחייבת אותך לשנות את קוד שרת ה- Arduino FirmataExpress ואת קוד הלקוח pymata4 מבוסס Python. קוד FirmataExpress יכול להיות מאתגר לאיתור באגים. שיטה בשם printData נוספה ל- FirmataExpress כדי לסייע באיתור באגים. שיטה זו מאפשרת לך לשלוח ערכי נתונים מ- FirmataExpress ותדפיס אותם במסוף pymata4.

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

printData ((char*) "argc =", argc);

אם יש לך שאלות, השאר רק הערה, ואשמח לענות.

קידוד שמח!

מוּמלָץ: