מימוש Fuzzy Logic באמצעות ההוראות המיוחדות הקיימות לכך ב- HC12

מימוש Fuzzy Logic ב-HC12  -  מאת אלי קולברג

 

כללי

מאמר זה מבוסס על סדרת הרצאות שהעברתי במועדון הרובוטיקה, בנושא בקרת Fuzzy Logic ומימושה באמצעות ההוראות המיוחדות לכך במיקרו קונטרלר 68HC12 של מוטורולה. מאמר זה עוסק בפן הישומי של מערכות פאזיות על ארבעת שלביו, ולא בפיתוח המתמטי והרעיוני של לוגיקה פאזית.

 

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

1.          פאזיפיקציה (fuzzification).

2.          היסק (inference).

3.          דה פאזיפיקציה (defuzzification).

4.          צירוף (combination).

 

שני הראשונים מתיחסים לחלק ה-"אם" (premise) ושני האחרונים קשורים לחלק ה-"אז" (conclusion).

 

1.          תהליך הפאזיפיקציה הוא הצעד הראשון המבוצע על ידי כל מערכת פאזית. כאן מתבצעת העברה של המידע לדרגות השתייכות מתאימות של כל אחד מהסעיפים (clause) של חלק האם (premise) של כל חוק פאזי. למשל טמפ' של 50 מעלות תקבל את דרגת ההשתייכות 0.7 ב term טמפ' חמה. זה מודגם באיור 1 (כאשר x הוא נתון כניסה ו- m הוא דרגת השתתיכות):


איור 1: המרת נתון כניסה לדרגת השתייכות בתהליך הפאזיפיקציה

 

בסיום התהליך, כל סעיף של כל חלק אם של כל חוק, יוחלף בדרגת השתייכות. ואז רשימת החוקים תראה כך:

 

if m1,1 and … and m1,m then C is z1 and … and D is w1

if m2,1 and … and m2,m then C is z2 and … and D is w2

         

…..

…..

if mn,1 and … and mn,m then C is zn and … and D is wn

 

 

2.                      תהליך ההיסק עוסק בחיבור כל המשתנים הפאזיים למשתנה אחד שמיוצג על ידי פונקציית השתייכות אחת. בדרך זו, צירוף של פונקציות השתייכות לאחת, מייצרת דרגת השתייכות אחת. ההיסק על חלק האם מתבצע לפי הכללים הבאים (בחלק האם שבו יש and נשתמש ב- min):


בסיום התהליך, נוצרת התוצאה הסופית שמסומנת ב- mp:

if mp1then C is z1 and … and D is w1

                                                                if mp2 then C is z2 and … and D is w2

                                                                                                 …….

                                                                                                 …….

 

                         

if mpn then C is zn and … and D is wn

 

3.                      תהליך הדהפאזיפיקציה עוסק בהמרת דרגת ההשתייכות mp שחושבה על ידי תהליך ההיסק בחזרה לערך מהתחום הנתון. תהליך זה מבוצע על חלק האז (conclusion) של החוק. היות ורוב פונקציות ההשתייכות בנויות בצורה שיוצרת טרנספורמציות של אחד להרבה בין דרגת ההשתייכות והתחום, קיים חוסר ודאות הקשור לבחירת הערך הנכון. ישנן שיטות רבות לבצע דהפאזיפיקציה. בכל חוק נקבל מערך מינימום של משתנה הכניסה, שטח ב term של משתנה מוצא. (איור 2)

 


 

איור 2: מציאת שטח של משתנה המוצא מתוך דרגת השתייכות כניסה מתהליך ההיסק

 

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

                          if mp1then A1,1 and … and B1,m

                          if mp2 then A2,1 and … and B2,m

                                        ……..

                                        ……..

 

 

                          if mpn then An1 and … and Bnm

כאשר A ו- B הם שטחים מחושבים. (כדוגמת השטח האפור באיור 2).

 

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

A=A1,1+A1,2+…+A1,n

אין מוסיפים שטחים משותפים יותר מפעם אחת. מתוך השטח הכולל מוצאים את מרכז הכובד וזה יהיה נתון המוצא הבודד (איור 3).


איור 3: מציאת ערך מוצא יחיד בתהליך הצירוף על ידי חישוב מרכז כובד משטחי משתני המוצא מתהליך הדהפאזיפיקציה

 

 

למערכת בקרה פאזית מבוססת מיקרו קונטרולר יש שני חלקים. החלק הראשון הוא גרעין היסק פאזי (fuzzy inference kernel) שמתבצע באופן מחזורי לקביעת מוצאי המערכת בהתבסס על המבואות הנוכחיים של המערכת. החלק השני של המערכת הוא בסיס הידע (knowledge base) שמכיל את פונקציות ההשתייכות והחוקים. איור 4 הוא דיאגרמת בלוקים של סוג זה של מערכת לוגיקת פאזי.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


איור 4: דיאגרמת בלוקים למערכת בקרה פאזית מבוססת מיקרו קונטרולר

 

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

 

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

 

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

 

הוראת MEM

 

במהלך שלב הפאזיפיקציה, משווים את ערכי מבואות המערכת הנוכחיים כנגד פונקציות השתייכות של המבואות, שאוחסנו קודם לכן, בכדי לקבוע את הדרגה שבה כל תווית (term) של כל מבוא מערכת  הוא אמת (דרגת השתייכות). (בספרות מוטורולה משתמשים במונח תווית (label) ולא term כיוון שבאופן רגיל, לterm  דרגת השתייכות בין 0 ל- 1 ולא בין 0 ל- 255 כמו כאן). את זה משיגים על ידי מציאת ערך ה- Y (ציר Y הוא דרגת ההשתייכות או דרגת האמת), עבור ערך המבוא הנוכחי על פונקציית השתייכות טרפזית לכל תווית של כל מבוא מערכת. ב- HC12 הוראת MEM מבצעת חישוב זה עבור תווית אחת של מבוא מערכת אחד. בכדי לבצע משימת פאזיפיקציה מלאה למערכת, חייבים לבצע מספר הוראות MEM, בדרך כלל בתוך לולאה.

ב HC12, דרגת ההשתייכות היא לא בין 0 ל- 1 אלא בין  $00 לבין $FF היות ודרגת ההשתייכות היא מילה בת 8 ביט.  כאן  היא נקראת דרגת האמת (Degree of Truth).

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

באיור 5, בכתובת ADDR יהיה המספר 40$ (מיקום על ציר ה-X של נקודה 1).

            בכתובת ADDR+1 יהיה המספר $D0 (מיקום על ציר ה-X של נקודה 2).

            בכתובת ADDR+2 יהיה המספר $08

                            [   שיפוע 1 :    $FF/(X OF SATURATION- X OF POINT 1)   ]

            בכתובת ADDR+3 יהיה המספר $04

                            [   שיפוע 2  :    $FF/( X OF POINT 2-X OF SATURATION)   ]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


איור 5: מבנה פונקצית השתייכות של תווית (term) בודדת

 

 

במעבד CPU12, הנמצא בתוך מיקרו הבקר HC12, אפשר להגדיר פונקציית השתייכות "קריספית".  במקרה זה אחד או שני הצדדים מאונך (שיפוע אינסופי). היות ולא משתמשים בערך שיפוע של 00$, הוא משמש להגדרת שיפוע אינסופי בהוראת MEM.

 

באיור 6 מופיעה מערכת עם שלוש פונקציות השתייכות מבוא, אחת לכל תווית של מבוא מערכת. ציר ה- X של כל שלושת פונקציות ההשתייכות מייצג את התחום של ערכים אפשריים של מבוא מערכת. הקו האנכי דרך כל שלושת פונקציות ההשתייכות מייצג ערך מבוא מערכת מסוים. ציר ה- Y מייצג את דרגת האמת (השתייכות) ומשתנה משקר מוחלט ($00 או 0%) לאמת מוחלטת ($FF או 100%). ערך ה- Y היכן שהקו האנכי חותך חותך כל אחת מפונקציות ההשתייכות, הוא הדרגה שבה ערך המבוא הנוכחי מתאים לתווית הקשורה אלי ועבור מבוא המערכת. לדוגמא, הביטוי "הטמפרטורה חמימה" הוא 25% נכון ($40).  הערך $40 יאוחסן בכתובת בזיכרון ה- RAM, והוא נקרא מבוא פאזי (במקרה זה, המבוא הפאזי עבור "הטמפרטורה חמימה"). קיימת כתובת ב- RAM לכל מבוא פאזי (לכל תווית של כל מבוא מערכת). ההבדל בין term לתווית מתבטא בשני אופנים: 1. דרגת השתייכות של term משתנה בין 0 ל- 1, ואילו של תווית משתנה בין 0 ל- 255 (מספר מקסימלי בן 8 ביטים). 2. ערך הכניסה לטרם הוא מספר התלוי בגודל פיסיקלי או אחר של המשתנה בעוד שתחום התוויות מוגבל למספרים בין 0 ל- 255, ולכן נדרש נירמול ערכי המשתנה. כאשר זה ידוע, ניתן להחליף את המושגים ביניהם.

 

איור 6: דוגמא לפונקציית השתייכות מבוא בעלת שלוש תוויות

 

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

 

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

 

האלגוריתם של הוראת MEM:  

1.      קרא מילה מ- (0,X) – נקודה 1 ונקודה 2.

2.       X:=X+4.

3.       קרא מילה מ- (2 ,X) - שיפוע 1 ושיפוע 2.

4.       delta 1:= ACCA-point 1 (ערך הכניסה צריך להיות ב- ACCA)

5.       delta 2 := point 2-ACCA

6.       אם אחד ההפרשים הוא שלילי, אז סמן טעות, ובצע: 0=שיפוע 1 וגם 0= שיפוע 2

7.       אם אין טעות, grade 1 := slope 1 * delta1                                                             
           וגם
grade 2 := slope 2 *delta 2

8.       אם   שיפוע 2 = 0   או   דרגה 2 גדולה מ- $FF, ואין טעות, אז דרגת השתייכות  := $FF, אחרת דרגת השתייכות := דרגה 2

9.       אם שיפוע 1 = 0 או דרגה 1 גדולה מ- $FF, ואין טעות, אז דרגת השתייכות    := דרגת השתייכות, אחרת דרגת השתייכות := דרגה 1

10.    כתיבת byte בכתובת 1,Y- עם תוצאת כניסת פאזי (דרגת השתייכות).

 

 

הוראת REV

 

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

 

כאן נתאר את הוראות הערכת החוקים. הוראת REV אינה כוללת אפשרות למשקל שונה לכל חוק. כאן כל החוקים הם בעלי חשיבות זהה. הוראת REVW עושה זאת אך לא נדון בכך כאן. בהוראת REV אנו מממשים הערכת min-max של החוקים. אוגרי המעבד משמשים כמצביעים ולתוצאות חישובי ביניים.

 

לדוגמא, חוק אופייני יכול להיות:

 

            אם הטמפרטורה היא חמימה והלחץ הוא גבוה, אז החימום (צריך להיות) כבוי.

 

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

 

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

 

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

 

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

 

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

 

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

 

התוצאה הסופית של צעד הערכת החוק היא טבלה של מוצאים פאזיים מומלצים או גולמיים ב- RAM. ערכים אילו התקבלו מהכנסת התנאים הנוכחיים (ערכי מבוא פאזיים) לחוקי המערכת בבסיס הידע. לא ניתן לספק את התוצאות הגולמיות ישירות למוצאי המערכת היות והם יכולים להיות שנויים במחלוקת או מעורפלים. למשל, מוצא גולמי אחד יכול להצביע על כך שמוצא המערכת צריך להיות בינוני עם דרגת אמת של 50%, ובאותו זמן, מוצא גולמי אחר מצביע על כך שמוצא המערכת צריך להיות נמוך עם דרגת אמת של 25%.

 

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

 

הכנות קודמות לביצוע הוראת REV

 

יש צורך לבצע הכנות לחלק מאוגרי המעבד ולמספר מיקומים בזיכרון, לפני הפעלת הוראת REV. האוגרים X ו- Y משמשים כמצביעים לרשימת החוקים ולמבואות ולמוצאים הפאזיים. צובר A משמש לאיחסון תוצאות חישובי ביניים וצריך להיות מאותחל ל- $FF. ביט V (גלישה) באוגר המצב (CCR) משמש לקביעת מצב ההוראה ומראה האם מבוצע כעת חלק התנאי או חלק ה- then. בתחילה ערך V מאותחל לאפס,  בכדי לסמן עיבוד של החלק הראשון. צריך לאפס את המוצאים הפאזיים (כתובות בזיכרון RAM). אם לא נאפס אותם קודם לביצוע ההוראה, אנו עלולים לקבל תוצאות שגויות.

 

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

 

אוגר מציין Y מאותחל להצביע על כתובת הבסיס של המבואות והמוצאים הפאזיים (בזיכרון ה- RAM). כל חלק תנאי של חוק הוא היסט של 8 ביט unsigned מכתובת בסיס זו למבוא הפאזי המיוחס. כל חלק then של חוק הוא היסט של 8 ביט unsigned מכתובת בסיס זו למוצא הפאזי המיוחס. ערך אוגר מצביע Y נשאר קבוע לכל אורך ביצוע הוראת REV.

 

צובר A בן 8 ביט, משמש לאיחסון תוצאות חישובי ביניים במהלך ביצוע הוראת REV. במהלך עיבוד חלק התנאי, A מאותחל ל- $FF, והוא מוחלף בכל ערך קטן יותר שמאוזכר בחלק התנאי של החוק (MIN). במהלך עיבוד חלק ה- then, A מחזיק את ערך האמת של החוק. ערך אמת זה מאוחסן לכל מוצא פאזי שמאוזכר על ידי חלק ה- then, אלא אם מוצא פאזי זה כבר גדול יותר (MAX).

 

לפני תחילת ביצוע הוראת REV, חייבים לאתחל את A ל- $FF (הערך הגדול ביותר של 8 ביט) היות והערכת החוק מתחילה תמיד עם עיבוד של חלקי התנאי של החוק הראשון. עבור החוקים העוקבים, הערך $FF מוצב באופן אוטומטי לתוך A, כאשר ההוראה מגלה את תו הסימן $FE בין חלק ה- then האחרון של החוק הקודם, והאיבר הראשון בחלק התנאי של חוק חדש.

 

ההוראה LDAA #$FF מאפסת את ביט V יחד עם איתחול A ל- $FF. זה מתאים לדרישות האיתחול של הוראת REV לאפס את ביט V כמו גם לאתחל את A ל-  $FF. ברגע שמתחילה הוראת REV, הערך של ביט V מנוהל אוטומטית כאשר מתגלים התווים המפרידים $FE.

 

הדרישה האחרונה לאיפוס כל המוצאים הפאזיים ל- $00, היא חלק מהאלגוריתם MAX. בכל פעם שאיבר בחלק then של חוק מתייחס למוצא פאזי, מוצא פאזי זה מושווה לערך האמת של החוק הנוכחי. אם ערך האמת הנוכחי גדול יותר, הוא נכתב במקום (על) הערך הקודם של המוצא הפאזי. אחרי שהוערכו כל החוקים, המוצא הפאזי מכיל את ערך האמת עבור חוק הכי אמת (most-true) שאיזכר מוצא פאזי זה.

 

אחרי שמסתיים ביצוע הוראת REV, A יחזיק את ערך האמת עבור החוק האחרון שברשימת החוקים. ביט V צריך להיות 1, היות והאלמנט האחרון שלפני מציין הסיום $FF, היה צריך להיות איבר בחלק ה- then. אם ביט V הוא אפס לאחר ביצוע REV, זה יכול להצביע על כך שרשימת החוקים נבנתה לא כהלכה.

 

האלגוריתם של הוראת REV: 

1.                      קרא בית ב (0,X) – האלמנט הראשון ברשימת החוק. בדרך כלל זה יהיה

 איבר התנאי הראשון של החוק הראשון.

2.                      X:=X+1. מצביע על האיבר הבא ברשימת החוק.

3.       השהייה פנימית.

4.       כאן נקרא מבוא פאזי או מוצא פאזי, תלוי באיזה חלק של החוק

נמצאים, מלבד אם מגיעים לתווי ההפרדה $FE ו- $FF. תהליך הקריאה משתמש באוגר מצביע Y לכתובת הבסיסית ובבית הקודם שנקרא בחוק זה (Rx) כהיסט ללא סימן (חיובי) מ- Y. המבוא הפאזי או המוצא הפאזי שנקרא כאן, ישמש אותנו בצעד 6.0 או 6.1. ה- Rx שנקרא קודם לכן משמש כהיסט  מ- Y עבור קריאה זו, וגם ערכו נבדק לראות האם הוא תו הפרדה ($FE).  אם הוא אכן $FE, וביט V היה 1, זה מצביע על מעבר מעיבוד חלק התוצאה (then) של חוק אחד לתחילת העיבוד של חלק התנאי של החוק הבא. במעבר זה, צובר A מאותחל ל- $FF בכדי להיות מוכן לפעולת min למציאת הערך המבוא הפאזי הקטן ביותר. בנוסף לכך, אם Rx ערכו $FE, ביט V הופך את ערכו בכדי להצביע על השינוי מתנאי לתוצאה או מתוצאה לתנאי. 

5.                      כאן נקרא בית חדש של החוק ממיקום (0,X), ואז יקודם X (X=X+1),

אלא אם הגענו לסיום ערכו של Rx הוא $FF (מה שמסמן את סיום רשימת החוק). לא נשתמש בבית חדש זה עד ביצוע צעד 4 של המעבר הבא דרך הלולאה.

בין צעד 5 לבין 6.x משתמשים בערכו של V בכדי לקבוע באיזה משני המסלולים ללכת. אם V הוא 0, מטפלים במסלול של התנאי והמעבד מתקדם לצעד 6.0. אם V הוא 1, מטופל חלק התוצאה והמעבד ממשיך לצעד 6.1.

6.                      ערך צובר A מושווה עם המבוא הפאזי שנקרא בצעד 4 קודם לכן, והערך

הנמוך מבין שניהם מוצב בצובר A (פעולת min). אם Rx הוא $FE, זהו מעבר בין תנאי החוק לתוצאות החוק, ומדלגים על פעולת ה- min.

6.1 כאן גם ערך צובר A מושווה עם המבוא הפאזי שנקרא בצעד 4 קודם לכן, והערך הגבוה מבין שניהם מוצב בכתובת Rx,Y (פעולת max). אם Rx הוא $FF, זהו סיום החוקים, אחרת חוזרים לצעד 4.

 

הוראת WAV

 

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

 

הוראת WAV מחשבת את סכומי המונה והמכנה ומבצעת מבצעת חישובי ממוצע משוקלל המשמשים לביצוע דהפאזיפיקציה. פסאודו פקודה wavr משמשת לחזרה מפעולת ממוצע משוקלל בפסיקה. WAV מחשבת סכומי המונה והמכנה הבאים:

 

(1)

 

 

כאשר n הוא מספר התוויות (terms), של מוצא המערכת, Si הם המיקומים (מרחקים) הבודדים המתקבלים מבסיס הידע, ו Fi הם המוצאים הפאזיים שמתקבלים מה- RAM. Si ו- Fi הם ערכים בני שמונה ביט. צובר B מחזיק את מונה האיטרציות n. בתוכנית רגילה של לוגיקה עמומה ב- HC12, n הוא שמונה או פחות (למרות שההוראה יכולה לטפל בעד 255). אוגרים זמניים פנימיים מחזיקים את ערכי סכומי הביניים (24 ביט למונה ו- 16 ביט למכנה. החלוקה האחרונה מבוצעת בעזרת הוראת EDIV נפרדת מייד אחרי הוראת WAV. חלוקה זו היא: Y=(Y:D)/X כלומר מחברים אוגרים Y ו- D ומחלקים את מה שמתקבל בתוכן אוגר X. התוצאה נמצאת ב- Y  והשארית ב- D. אם למערכת יש יותר ממוצא מערכת אחד, הוראת WAV מתבצעת פעם אחת עבור כל מוצא מערכת.

 

הכנות מוקדמות לביצוע הוראת WAV

 

לפני ביצוע הוראת WAV צריך להכין את האוגרים X ו- Y וצובר B. אוגר X חייב להכיל את הכתובת של המיקום (singleton) הראשון מרשימת Si מבסיס הידע. אוגר Y חייב להכיל את הכתובת של המוצא הפאזי הראשון של מערכת מוצאים זאת Fi. אוגר B חייב להכיל את מספר התוויות של מוצאי מערכת זו.

 

דוגמא לגרעין היסק

 

בתוכנית הבאה מופיע גרעין היסק פאזי שלם שנכתב בשפת אסמבלי של ה- HC12.  המספרים בסוגריים המרובעות הם מספר המחזורים. הגרעין משתמש בשני מבואות פאזיים עם שבע תוויות לכל אחד, ומוצא מערכת אחד עם שבע תוויות. התוכנית מקומפלת ל- 57 בתים. היא מתבצעת במשך  לערך בתדירות אפיק של 8MHz. אפשר בקלות להרחיב את המבנה הבסיסי למערכת לשימוש כללי עם מספר גדול יותר של מבואות ומוצאים.

 


תוכנית 1: גרעין היסק פאזי למעבד 12HC68

 

 

*

 

 

 

 

 

01

[2]

FUZZIFY:

LDX

#INPUT_MFS

;point at MF definitions

02

[2]

 

LDY

#FUZ_INS

;point at fuzzy input table

03

[3]

 

LDAA

CURRENT_INS

;get first input value

04

[1]

 

LDAB

#7

;7 labels per input

05

[5]

GRAND_LOOP:

MEM

 

;evaluate one MF

06

[3]

 

DBNE

B,GRAD_LOOP

;for 7 labels of 1 input

07

[3]

 

LDAA

CURRENT_INS+1

;get second input value

08

[1]

 

LDAB

#7

;7 labels per input

09

[5]

GRAND_LOOP1:

MEM

 

;evaluate one MF

10

[3]

 

DBNE

B,GRAD_LOOP1

;for 7 labels of 1 input

 

 

 

 

 

 

11

[1]

 

LDAB

#7

;loop count

12

[2]

RULE_EVAL:

CLR

1,Y+

;clr a fuzzy out & inc ptr

13

[3]

 

DBNE

b,RULE_EVAL

;loop to clr all fuzzy outs

14

[2]

 

LDX

#RULE_START

;point at first rule element

15

[2]

 

LDY

#FUZ_INS

;point at fuzzy ins and outs

16

[1]

 

LDAA

#$FF

;init A (and clears V-bit)

17

[3n+4]

 

REV

 

;process the rule list

 

 

 

 

 

 

18

[2]

DEFUZ:

LDY

#FUZ_OUT

;point at fuzzy outputs

19

[1]

 

LDX

#SGLTN_POS

;point at singleton positions

20

[1]

 

LDAB

#7

;7 fuzzy outs per COG output

21

[8b+9]

 

WAV

 

;calculate sums for wtd av

22

[11]

 

EDIV

 

;final divide for wtd av

23

[1]

 

TFR

Y,D

;move result to A:B

24

[3]

 

STAB

COG_OUT

;store system output

 

*

 

 

 

 

 

*****

End

 

 

 

 

 

שורות 1-3 מאתחלות מצביעים ומטעינות את ערך מבוא המערכת לתוך צובר A.

 

שורה 4 מציבה את מניית הלולאה עבור הלולאה בשורות 5 ו- 6.

 

שורות 5 ו-6 מבצעות את לולאת הפאזיפיקציה עבור שבע התוויות של מבוא מערכת אחד. הוראת MEM מוצאת את ערכי y על פונקציית השתייכות טרפזית עבור ערך המבוא הנוכחי, לתווית אחת של המבוא הנוכחי, ואז מאחסנת את התוצאה למבוא הפאזי המתאים. המצביעים ב- X ו- ט מתעדכנים אוטומטית בארבע ואחד, כך שהם מצביעים לפונקציית ההשתייכות הבאה ולמבוא הפאזי הבא בהתאמה.

 

שורה 7 מטעינה את הערך הנוכחי של מבוא המערכת הבא. המצביעים ב- X ו- Y כבר מצביעים למקומות הנכונים כתוצאה מהעדכון האוטומטי של הוראת MEM בשורה 5.

 

שורה 8 מטעינה מחדש את מונה הלולאה.

 

שורות 9 ו- 10 יוצרות לולאה לביצוע פאזיפיקציה של שבע תוויות של מבוא המערכת השני. כאשר התוכנית מגיעה לשורה 11, אוגר מציין Y מצביע על הכתובת הבאה אחרי הכניסה הפאזית האחרונה, שהיא המוצא הפאזי הראשון במערכת זו.

 

שורה 11 מאתחלת את מונה הלולאה לאיפוס שבע המוצאים הפאזיים.

 

שורות 12 ו- 13 יוצרות לולאה לאיפוס כל המוצאים הפאזיים לפני שמתחילה הערכת החוק.

שורה 14 מאתחלת את אוגר מציין X להצביע על האלמנט הראשון ברשימת החוק עבור הוראת REV.

 

שורה 15 מאתחלת את אוגר מציין Y להצביע על המבואות והמוצאים הפאזיים במערכת. רשימת החוק (עבור REV) מבוססת על היסט של 8 ביט מכתובת הבסיס למבואות פאזיים מסויימים או מוצאים פאזיים מסויימים. הערך המיוחד $FE מתפרש על ידי REV כסמן בין תנאי החוק ופעולות החוק.

 

שורה 16 מאתחלת את צובר A לערך הגבוה ביותר בן 8 ביט בהכנות למציאת המבוא הפאזי הקטן ביותר שמיוחס על ידי תנאי של חוק. ההוראה LDAA #$FF גם מאפסת את ביט V באוגר המצב של המעבד, כך שהוראת REV יודעת שהיא מעבדת תנאים. במהלך עיבוד רשימת חוק, ביט V ממותג בכל פעם שמתגלה $FE ברשימה. ביט V מציין האם REV מעבד תנאים או פעולות.

 

שורה 17 מכילה הוראת REV, שהיא לולאה עצמאית לעיבוד אלמנטים עוקבים ברשימת החוק עד שמתגלה התו $FF. עבור מערכת עם 17 חוקים עם שני תנאים ותוצאה אחת, הוראת REV לוקחת 259 מחזורים, אבל היא ניתנת לפסיקה כך שהיא לא גורמת להשהיית פסיקה ארוכה.

 

שורות 18 עד 20 מאתחלות את המצביעים ומונה האיטרציות עבור הוראת WAV.

 

שורה 21 היא תחילת הדה-פאזיפיקציה. הוראת WAV מחשבת סכום מכפלות וסכום משקלים.

 

שורה 22 משלימה את הדה פאזיפיקציה. הוראת EDIV מבצעת חלוקה של 32 ביטים ב- 16 ביטים על תוצאות הביניים מ- WAV לקבלת ממוצע משוקלל.

 

שורה 23 מעבירה את תוצאות EDIV לצובר כפול D.

 

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

 

 


דוגמא לבקרת PID למהירות מנוע DC

(מיועדת לבעלי רקע בבקרת מנועים ע"י PWM )

 

 

המטרה היא לתכנן בקר מנוע מבוסס מיקרוקונטרולר בלוגיקה עמומה (איור 7).

 

 

 

איור 7: ממשק בקר מנוע עם לוגיקה עמומה

 

המפעיל הוא אות ספרתי PWM. ההספק למנוע מבוקר על ידי שינוי ה- duty cycle (DC) של גל ריבועי בתדר של 15KHz לערך. DC מוגדר כאחוז שבו האות נמצא במצב ‘on’ מתוך זמן המחזור כולו. הערך הנקוב של התדר אינו משנה ללוגיקה או לחישוב ה-DC כיוון שמדובר באחוז מזמן המחזור. לעומת זאת קיים לכל מנוע תדר עבודה אופטימלי המאפשר למנוע להוציא הספק מירבי ל- DC נתון. לכן לכל מנוע יש למצוא את תדר העבודה האופטימלי. תדר זה מושפע בעיקר מהתנגדות והשראות סלילי המנוע.

ה- FET-ים שנמצאים ברכיב LMD18201 מספקים זרם למנוע רק כאשר המוצא הספרתי של אות ה- PWM הוא גבוה. קיימות דיודות הגנה ששומרות על האלקטרוניקה מהכא"מ המושרה שנוצר כאשר הזרם ממותג (dI/dt גבוה) לסליל המנוע.

היות ותדירות הגל הריבועי מהירה יותר מתגובת המנוע, הרי שהמנוע מגיב רק ל- DC ולא לחלקים הגבוהים או הנמוכים המסויימים של הגל הריבועי.

מוצא האנקודר הוא תדירות (ביחידות של Hz) היחסית למהירות המנוע (בסל"ד). ניתן למדוד התדירות של אות זה בעזרת מערכת ה- Input Capture. מהירות המנוע היא פונקציה לא לינארית של ההספק המוזן. עקב החיכוך והאינרציה, ישנו תחום הספק שמתחתיו המנוע לא יסתובב.

המערכת שלנו תספור את כמות הפולסים של האנקודר הקיימים בין גלישת שעון (TCNT) אחת לבאה אחריה. משך הזמן שעובר בין שתי גלישות עוקבות הוא במקרה שלנו 8.125ms. במהירות רצויה של 100 סל"ד, מספר הפולסים יהיה 80. הסבר החישוב: אנו מדברים על מנועים שבהם יחס התמסורת הוא 1:30, ועל גלגל האנקודר 200cpr (חורים לסיבוב). היות והאנקודר ממוקם לפני התמסורת הרי שסה"כ יהיו לנו 200 x 30 = 6000 חורים לסיבוב. מספר סיבובי המנוע בשניה אחת יהיה: 100rpm/60spm כלומר 100 סיבובים לדקה חלקי 60 שניות לדקה. ומכאו נקבל rps סיבובים לשניה. מספר הסיבובים ב 8.125ms יהיה rps * 8.125/1000. אם נכפיל נתון זה ב- 6000 (מספר חורי האנקודר לסיבוב אחד), נקבל כ- 80 חורים בזמן של 8.125ms.

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

נניח שאנקודר גלגל ימני מחובר ל- PT0 ואנקודר גלגל שמאלי מחובר ל- PT1. בסיס וקטור הפסיקות הוא הכתובת $0600 ($ מסמן מספר בבסיס 16 – הקסאדצימלי). כתובת פסיקת PT0 רחוקה $2E (46) כתובות מהבסיס. כתובת פסיקת PT1 רחוקה $2C (44) כתובות מהבסיס. כתובת פסיקת גלישת השעון רחוקה $1E (30) כתובות מהבסיס.

מכאן, נתחיל בסימון כתובות שלושת הפסיקות הללו:

תוכנית 2: סימון כתובות הפסיקה

 

int_ base:

Equ

$0600

tch0:

Equ

int_base + $2e

tch1:

Equ

int_base + $2c

tovf:

Equ

int_base + $1e

 

שגרת הפסיקה לספירת פולסי אנקודר ימין תקרא enc_rt, ספירת פולסי אנקודר שמאל תתבצע בשגרת פסיקה בשם enc_lft, ואילו שגרת הפסיקה לביצוע הבקרה בכל פעם שקורית גלישת השעון תקרא ovf_fuz.

 

נכתוב כעת את שגרת איתחול הפסיקות בצורה הבאה:

 

תוכנית 3: שגרת איתחול הפסיקה

 

 

01

int_init:

 

 

 

02

 

movb

#$05, tctl4

* looking for rising edge on port t bits 0 and 1

03

 

movb

#$03, tmsk1

* enable local switches interrupts of pt0 and pt1

04

 

movb

#$80, tmsk2

* enable timer overflow interrupt

05

 

movb

#$00, tios

* make sure that port t is in input capture mode

06

 

ldx

#enc_rt

* load right encoder routine address into x register

07

 

stx

tch0

* update channel 0 interrupt vector to point towards enc_rt interrupt routine

08

 

ldx

#enc_lft

* load left encoder routine address into x register

09

 

stx

tch1

* update channel 1 interrupt vector to point towards enc_lft interrupt routine

10

 

ldx

ovf_fuz

* load timer overflow routine address into x register

11

 

stx

tovf

* update timer overflow interrupt vector to point towards tovf interrupt routine

12

 

movb

#$03, tflg1

* clear flag bits 0 and 1 and wait for rising edges

13

 

movb

#$80, tflg2

* clear overflow flaf bit (msb) in tflg2

14

 

movb

#$00,l_count

* clear counter of right encoder pulses

15

 

movb

#$00,r_count

* clear counter of left encoder pulses

16

 

movb

#$00,old_lerr

* clear value of old left speed error

17

 

movb

#$00,old_rerr

* clear value of old right speed error

18

 

movb

#$00, l_sum

* clear counter of the sum of left speed errors

19

 

movb

#$00, r_sum

* clear counter of the sum of right speed errors

20

 

movb

#80, l_speed

* determine 80 tics as left motor desired speed

21

 

movb

#80, r_speed

* determine 80 tics as right motor desired speed

22

 

cli

 

* activate interrupts global switch

23

 

rts

 

 

 

שורה 1 מכילה את תווית או את שם שגרת איתחול הפסיקה. בשורה שניה אנו מציבים ערך של 01 בביטים 0 ו- 1 ב- tctl4 כלומר המעבד יחכה לקצה עולה (01) בביט 0 של port T (שני הביטים הימניים ב tctl4 מצביעים על כך), באותה צורה הערכים 01 בביטים 2 ו- 3 של tctl4 מצביעים על כך שהמעבד יחכה לקצה עולה בביט 1 של port T.

שורה 3 מציבה ערך 1 בביטים 0 ו- 1 של tmsk1 ובכך מאפשרת פסיקה בביטים המקבילים (0 ו- 1) של portT. אילו מתגים מקומיים. אם נציב ערך אפס באחד מביטים אלו של tmsk1, לא יהיו יותר פסיקות בביט המקביל ב port T, אך בשאר הביטים במידה ופסיקות מאופשרות הן תמשכנה להתקיים.

 

שורה 4 מאפשרת קיום פסיקה בכל פעם שתקרה גלישה בשעון הכללי TCNT.

 

שורה 5 מוודאת שכל הביטים ב- port T יהיו במצב של לכידת מבוא (Input Capture ). למרות שזוהי ברירת המחדל, נוודא בצורה זו שגם אם בטעות ביטים מסוימים הוגדרו כהשוואת מוצא (Output Compare), הם יחזרו להיות מכוונים ללכידת מבוא. יש לשים לב שאם ברצוננו להשתמש בביטים מסויימים כהשוואת מוצא, יש לשנות את הפרמטר המספרי שבפקודה זו.

 

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

 

בשורה 7 אנו שומרים כתובת זו במקום המתאים לביט 0 של port T בוקטור כתובות הפסיקה.

 

בשורות 8 עד 11, אנו שומרים באופן דומה את כתובות שגרות הפסיקה של אנקודר שמאל (pt1) ושל גלישת השעון הכללי (tovf) במקומות המתאימים בוקטור הפסיקה.

 

בשורה 12 אנו מאפסים את הדגלים שקשורים לפסיקה בביטים 0 ו- 1 של port T על ידי איפוס ביטים 0 ו- 1 ב- tflg1. יש לשים לב שביטים שהם דגלים, כתיבת 1 בהם, תגרום לאיפוס (0) שלהם. לכאורה דבר והיפוכו. יש לכך סיבה שמוסברת במדריכים של חברת מוטורולה. ביט שאינו דגל, הכתיבה אליו רגילה ואם נרשום בו 1, הוא יהיה 1.

 

בשורה 13 אנו מאפסים את הדגל הקשור לפסיקת גלישת השעון. גם כאן כתיבת 1 לביט תגרום לו להפוך ל- 0.

 

בשורות 14 ו- 15 אנו מאפסים את המונים של אנקודר ימין ואנקודר שמאל בהתאמה, בכדי שהספירה תתחיל מאפס. יש לשים לב לכך שאנו מניחים כי כתובות המונים הוגדרו קודם לכן באיתחול התוכנית הראשית (כמו לגבי שאר התוויות בתוכנית).

 

בשורות 16 ו- 17 אנו מאפסים את ערך השגיאה הקודמת של מהירות שמאל ומהירות ימין.

 

בשורות 18 ו- 19 אנו מאפסים את מוני ערכי השגיאה המצטברת של מהירויות שמאל וימין בהתאמה.

 

בשורות 20 ו- 21 אנו קובעים את המהירות הרצויה למנוע שמאל ומנוע ימין בהתאמה. בנסיעה ישרה זה יהיה אותו מספר, אולם בסיבוב בקשת נחליף ערך זה באחד או בשני המנועים.

 

בשורה 22 אנו מפעילים את המתג הכללי שמאפשר את קיום כל הפסיקות שהגדרנו.

 

שורה 23 מסמנת את סיום שגרת הפסיקה.

           

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

 

 

 

 

תוכנית 4: שגרת פסיקה לאנקודר ימין

 

01

enc_rt:

 

 

 

02

 

inc

r_count

* increment r_count value for each rising edge (pulse)

03

 

movb

#$01, tflg1

* clear tflg1 bit 0 and be prepared to next pulse

04

 

rti

 

* return to main program

 

השורה הראשונה מכילה את תווית (שם) שגרת הפסיקה לאנקודר ימין.

שורה 2 מגדילה ב- 1 את ערך מונה הפולסים המגיעים מאנקודר ימין.

שורה 3 מאפסת את הדגל בביט 0 של tflg1 המסמן קצה עולה ב- pt0 בכדי להיות מוכן לקצה עולה של הפולס הבא.

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

 

            שגרת הפסיקה לאנקודר שמאל דומה מאוד ואין צורך להסבירה שוב.

 

תוכנית 5: שגרת פסיקה לאנקודר שמאל

 

01

enc_lft:

 

 

 

02

 

inc

l_count

* increment l_count value for each rising edge (pulse)

03

 

movb

#$02, tflg1

* clear tflg1 bit 1 and be prepared to next pulse

04

 

rti

 

* return to main program

 

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

למערכת יהיו המשתנים הבאים:

 

שתי כניסות בקרה:

                        S*        מהירות מנוע רצויה (בפולסי אנקודר במשך זמן של 8.125ms)

                        S         מהירות מנוע נוכחית מוערכת (בפולסי אנקודר במשך זמן של 8.125ms)

משתנה מוצא אחד:

                        V         Duty cycle ערך הנכתב לאוגר pwdty0 (ימין) או pwdty1 (שמאל)

שלושה מבואות קריספיים:

                        E = S* - S¢ השגיאה במהירות המנוע

                        D = dS¢/dt = S¢(n) - S¢(n-1) קצב השינוי במהירות המנוע

                        I = òEdt = E(n) + SE(i) i=1,...,n-1 צבירת שגיאת מהירות המנוע בזמן

מוצא קריספי אחד:

                        DV       שינוי ב- DC (V=V+DV)

 

כעת נבנה את פונקציות ההשתייכות שמגדירות את המצב העכשווי של הכניסות והמוצאים הקריספיים. החישוב של קבוצות השתייכות המבוא נקרא פאזיפיקציה. לבקר פאזי זה נגדיר למען הפשטות חמש עשרה תוויות (terms) לכניסות הקריספיות. (טבלה 1). התוויות הוגדרו בצורה הבאה: האות E מסמנת שגיאה (error), האות D מסמנת נגזרת השגיאה (derivative), האות I מסמנת אינטגרל השגיאה (integral), האות N מסמנת שלילי (negative), האות P מסמנת חיובי (positive), האות B מסמנת גדול (big), האות S מסמנת קטן (small), האותיות ZE מסמנות אפס (zero). כך שלמשל EPB מסמן error positive big.

 

 

 

 

 

טבלה 1: הגדרת תוויות לשלושת המבואות הקריספיים

 

ENB

True אם המנוע מסתובב לאט במידה רבה

ENS

True אם המנוע מסתובב לאט במידה מועטה

EZE

True אם המנוע מסתובב במהירות הנכונה

EPS

True אם המנוע מסתובב מהר במידה מועטה

EPB

True אם המנוע מסתובב מהר במידה רבה

 

 

DNB

True אם המנוע מאיט את מהירותו במידה רבה

DNS

True אם המנוע מאיט מעט את מהירותו

DZE

True אם מהירות המנוע נשארת אותו דבר

DPS

True אם המנוע מאיץ מעט את מהירותו

DPB

True אם המנוע מאיץ את מהירותו במידה רבה

 

 

INB

True אם המנוע ממשיך לצבור מהירות יותר מדי איטית

INS

True אם המנוע ממשיך לצבור מהירות איטית במידה מועטה

INE

 Trueאם המנוע הגיע למהירותו הנכונה

IPS

True אם המנוע ממשיך לצבור מהירות גבוהה במידה מועטה

IPB

True אם המנוע ממשיך לצבור מהירות גבוהה מדי

 

נגדיר חמש תוויות עבור המוצא הקריספי (טבלה 2).

 

טבלה 2: הגדרת תוויות למוצא הקריספי

 

ONB

True אם צריך להפחית את מהירות המנוע במידה רבה

ONS

True אם צריך להפחית את מהירות המנוע במידה מעטה

OZE

True אם מהירות המנוע צריכה להשאר כמות שהיא

OPS

True אם צריך להגדיל את מהירות המנוע במידה מעטה

OPB

True אם צריך להגדיל את מהירות המנוע במידה רבה

 

כעת נכתוב את חלק התוכנית שמכיל את המשתנים הפאזיים. נשים לב כי ההנחייה (directive) ds משמשת לשמירת שטח לא מאותחל. לא נוצר שום קוד על ידי הנחייה זו. היא פשוט מקדמת את ערך מונה מיקום האסמבלר בגודל שמופיע בשדה האופרנד (הפרמטר). לשם שמופיע בשדה התווית מושם הערך שעליו מצביע מונה המיקום לפני שמונה המיקום מקודם. בתוכנית 6, למשתנה speed מושם ערך של $1000, למשתנה acceleration מושם ערך של $1001, למשתנה distance מושם ערך של $1002, למשתנה EPB מושם ערך של $1003 וכו'. קיימת גם אפשרות להשתמש בהנחיית set בכדי לבצע השמה של ערך מונה המיקום למשתנה, שיכול לשמש כעזר להקצאת מיקום והסרתה עבור המשתנים המקומיים בעזרת ההוראה LEAS. אנו לא השתמשנו בזה כאן. 

            יש לשים לב שאנו מניחים כי הקבועים והמשתנים המופיעים בתוכניות שבמאמר זה מוגדרים קודם לכן בתוכנית ראשית. (למשל r_speed     equ   80). מדובר ב:

tctl4, tmsk1, tmsk2, tios, tflg1, tflg2, l_count, r_count, l_sum, r_sum, l_speed, r_speed.

 

 

תוכנית 6: משתנים גלובלים לבקר פאזי

 

 

 

 

01

 

org

$1000

 

 

02

* crisp inputs

 

 

 

 

03

error:

ds

1

 

 

 

04

derivative:

ds

1

 

 

 

05

integral:

ds

1

 

 

 

06

* input membership variables

 

 

07

fuzvar:

ds

0

* inputs

 

 

08

EPB:

ds

1

* speed way too fast

 

 

09

EPS:

ds

1

* speed too fast

 

 

10

EZE:

ds

1

* speed ok

 

 

11

ENS:

ds

1

* speed too slow

 

 

12

ENB:

ds

1

* speed way too slow

 

 

13

DPB:

ds

1

* speed decreasing a lot

 

 

14

DPS:

ds

1

* speed decreasing

 

 

15

DZE:

ds

1

* speed constant

 

 

16

DNS:

ds

1

* speed increasing

 

 

17

DNB:

ds

1

* speed increasing a lot

 

 

18

IPB:

ds

1

* accumulating low speed error a  lot

 

 

19

IPS:

ds

1

* accumulating low speed error

 

 

20

IZE:

ds

1

* average of zero  speed error

 

 

21

INS:

ds

1

* accumulating high speed error

 

 

22

INB:

ds

1

* accumulating high speed error a  lot

 

 

23

 

 

 

 

 

 

 

24

Fuzout:

ds

0

* outputs

 

 

25

OPB:

ds

1

* add a lot of power to the system

 

 

26

OPS:

ds

1

* add some power to the system

 

 

27

OZE:

ds

1

* leave power as is

 

 

28

ONS:

ds

1

* subtract some power from the system

 

 

29

ONB:

ds

1

* subtract a lot of power from the system

 

 

30

BREAK:

ds

1

* apply break?

 

 

31

* input membership variables relative offsets

 

 

32

epb:

equ

0

* speed way too fast

* speed too fast

* speed ok

* speed too slow

* speed way too slow

 

 

33

eps:

equ

1

 

 

34

eze:

equ

2

 

 

35

ens:

equ

3

 

 

36

enb:

equ

4

 

 

37

dpb:

equ

5

* speed decreasing a lot

 

 

38

dps:

equ

6

* speed decreasing

 

 

 

39

dze:

equ

7

* speed constant

 

 

 

40

dns:

equ

8

* speed increasing

 

 

 

41

dnb:

equ

9

* speed increasing a lot

 

 

 

42

ipb:

equ

10

* accumulating low speed error a  lot

 

 

43

ips:

equ

11

* accumulating low speed error

 

 

44

ize:

equ

12

* average of zero  speed error

 

 

45

ins:

equ

13

* accumulating high speed error

 

 

46

inb:

equ

14

* accumulating high speed error a  lot

 

 

47

* output membership variables

 

 

48

opb:

equ

15

* add a lot of power to the system

 

 

49

ops:

equ

16

* add some power to the system

 

 

50

oze:

equ

17

* leave power as is

 

 

51

ons:

equ

18

* subtract some power from the system

 

 

52

onb:

equ

19

* subtract a lot of power from the system

 

 

53

* crisp outputs:

 

 

 

 

 

54

dpower:

ds

1

 

 

 

פונקציית ההשתייכות של השגיאה משורטטת באיור 8.

 

 

 

 

 

 

 

 

 

 

 

 

0     32     64      96        128     160    192     224    255   Error +128

 

 
 

 

 

-128         -64                    0                 64                 127   Error  (tics)  

 

 
 
 
 

 איור 8: פונקציית ההשתייכות של השגיאה

 

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

 

תוכנית 7: הגדרת פונקציית כניסת השגיאה

 

1

 

org

$1200

 

2

* format is point1, point2, slope1, slope2    

3

s_tab

dc.b

192, 255, 8, 0

* EPB

4

 

dc.b

128, 224, 5, 8

* EPS

5

 

dc.b

112, 144, 16, 16

* EZE

6

 

dc.b

32, 128, 8, 5

* ENS

7

 

dc.b

0, 64, 0, 8

* ENB

 

ההנחייה dc.b היא קיצור של define constant byte שמורה להכניס המספרים הבאים כבתים בזכרון החל מהכתובת המוגדרת בהנחיית org. חמשת התוויות (terms) מוגדרות לפי נקודות הקצה והשיפועים שלהן. כזכור השיפועים תמיד חיוביים, שיפוע אינסופי מקבל את הערך אפס והנקודה הראשונה שמופיעה בכל תווית היא הנקודה השמאלית.

פונקציית ההשתייכות של נגזרת השגיאה משורטטת באיור 9.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


השיפועים מופיע על גבי איור 9. בתוכנית 8 מוגדרת פונקציית כניסת נגזרת השגיאה לפי איור 9.  התוכנית תכתב באופן רציף מיד אחרי תוכנית 7.

 

תוכנית 8: הגדרת פונקציית כניסת נגזרת השגיאה

 

1

* format is point1, point2, slope1, slope2

2

a_tab

dc.b

224, 255, 16, 0

* DPB

3

 

dc.b

160, 255, 16, 4

* DPS

4

 

dc.b

64, 192, 8, 8

* DZE

5

 

dc.b

0, 96, 4, 16

* DNS

6

 

dc.b

0, 32, 0, 16

* DNB

 

פונקציית ההשתייכות של אינטגרל (סכימת) השגיאה משורטטת באיור 10.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 

איור 10: פונקציית ההשתייכות של סכימת השגיאה

 

חישוב השיפועים מופיע על גבי איור 10. בתוכנית 9 מוגדרת פונקציית כניסת סכימת השגיאה לפי איור 10.  התוכנית תכתב באופן רציף מיד אחרי תוכנית 8.

 

תוכנית 9: הגדרת פונקציית כניסת סכימת השגיאה

 

 

1

* format is point1, point2, slope1, slope2

2

i_tab

dc.b

224, 255, 16, 0

* IPB

3

 

dc.b

192, 255, 16, 8

* IPS

4

 

dc.b

32, 224, 4, 4

* IZE

5

 

dc.b

0, 64, 8, 16

* INS

6

 

dc.b

0, 32, 0, 16

* INB

 

המוצאים כאן לא מופיעים בצורת פונקצית השתייכות כמו במקרה הקלאסי של לוגיקה עמומה שבה המוצא הוא זה בעל דרגת ההשתייכות הגבוהה ביותר (max). כאן מבצעים איחוד של מוצאים פאזיים גולמיים למוצא מספרי מאוחד תוך שימוש במספרים בודדים (singletons). מספר singleton עבור משתנה לשוני הוא ערך יחיד שמושם למשתנה מוצא אם הכללים מייצרים משתנה לשוני זה ברמת ביטחון של 1, וכל שאר המשתנים מקבלים דרגת בטחון של אפס. למשל, המספר singleton עבור חם מאוד יכול להיות 100, המספר singleton עבור חם יכול להיות 95, זה שעבור פושר יכול להיות 90 וכו'. בהוראת WAV מתבצע ממוצע משוקלל (משוואה 1) של מספרי ה- singleton (Si) ל- n מוצאים כאלו, לפי רמת בטחון מוצא פאזי (Fi).  באיור 11 מופיעות תוויות המוצא הפאזי ומימוש מוצא קריספי.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


איור 11: המוצא הקריספי בתהליך הדה פאזיפיקציה

 

משתנה ההשתייכות הפאזי עבור המוצא, מגדיר את המוצא הקריספי, המספר שיש להוסיף ל- duty cycle כפונקציה של ערך ההשתייכות. אם למשל התווית ONS היתה אמת (255) ושאר הארבע היו שקר (0), אז השינוי במוצא היה -60. (איור 8).

באופן כללי, מחשבים את המוצא הקריספי כממוצע משוקלל של תוויות השתייכות פאזיות בצורה הבאה (משוואה 2):

 

(2)        DU=(decrease a lot * (-128) + some decrease * (-60) + same * 0 + some increase * (60) + increase a lot * (127))/( decrease a lot + some decrease + same + some increase + increase a lot)

 

בדוגמה שלנו אם אחד ממשתני הכניסה מכיל את האותיות NB הרי שהמוצא יהיה OPB. אם אחד ממשתני הכניסה מכיל את האותיות PB הרי שהמוצא יהיה ONB. אחרת, אם אחד ממשתני הכניסה מכיל את האותיות NS הרי שהמוצא יהיה OPS, ואילו אם אחד ממשתני הכניסה מכיל את האותיות PS הרי שהמוצא יהיה ONS. אם כל המשתנים מכילים את הערך ZE הרי שהמוצא יהיה OZE. תוכנית 10 מכילה את ההגדרות של החוקים הפאזיים.

 

תוכנית 10: הגדרות של החוקים הפאזיים

 

1.   

rules:

dc.b

enb,dnb,inb,$FE,opb,$FE

* if ENB and DNB and INB then OPB

2.   

 

dc.b

enb,dnb,ins,$FE,opb,$FE

* if ENB and DNB and INS then OPB

3.   

 

dc.b

enb,dns,inb,$FE,opb,$FE

* if ENB and DNS and INB then OPB

4.   

 

dc.b

enb,dns,ins,$FE,opb,$FE

* if ENB and DNS and INS then OPB

5.   

 

dc.b

ens,dnb,inb,$FE,opb,$FE

* if ENS and DNB and INB then OPB

6.   

 

dc.b

ens,dnb,ins,$FE,opb,$FE

* if ENS and DNB and INS then OPB

7.   

 

dc.b

enb,dze,inb,$FE,opb,$FE

* if ENB and DZE and INB then OPB

8.   

 

dc.b

enb,dze,ins,$FE,opb,$FE

* if ENB and DZE and INS then OPB

9.   

 

dc.b

enb,dze,ize,$FE,opb,$FE

* if ENB and DZE and IZE then OPB

10.               

 

dc.b

enb,dns,ize,$FE,opb,$FE

* if ENB and DNS and IZE then OPB

11.               

 

dc.b

eze,dnb,inb,$FE,opb,$FE

* if EZE and DNB and INB then OPB

12.               

 

dc.b

eze,dnb,ins,$FE,opb,$FE

* if EZE and DNB and INS then OPB

13.               

 

dc.b

eze,dns,inb,$FE,opb,$FE

* if EZE and DNS and INB then OPB

14.               

 

dc.b

epb,dpb,ipb,$FE,onb,$FE

* if EPB and DPB and IPB then ONB

15.               

 

dc.b

epb,dpb,ips,$FE,onb,$FE

* if EPB and DPB and IPS then ONB

16.               

 

dc.b

epb,dps,ipb,$FE,onb,$FE

* if EPB and DPS and IPB then ONB

17.               

 

dc.b

epb,dps,ips,$FE,onb,$FE

* if EPB and DPS and IPS then ONB

18.               

 

dc.b

eps,dpb,ipb,$FE,onb,$FE

* if EPS and DPB and IPB then ONB

19.               

 

dc.b

eps,dpb,ips,$FE,onb,$FE

* if EPS and DPB and IPS then ONB

20.               

 

dc.b

eps,dps,ipb,$FE,onb,$FE

* if EPS and DPS and IPB then ONB

21.               

 

dc.b

eps,dps,ips,$FE,onb,$FE

* if EPS and DPS and IPS then ONB

22.               

 

dc.b

epb,dze,ipb,$FE,onb,$FE

* if EPB and DZE and IPB then ONB

23.               

 

dc.b

epb,dze,ips,$FE,onb,$FE

* if EPB and DZE and IPS then ONB

24.               

 

dc.b

epb,dze,ize,$FE,onb,$FE

* if EPB and DZE and IZE then ONB

25.               

 

dc.b

epb,dps,ize,$FE,onb,$FE

* if EPB and DPS and IZE then ONB

26.               

 

dc.b

eze,dpb,ipb,$FE,onb,$FE

* if EZE and DPB and IPB then ONB

27.               

 

dc.b

eze,dpb,ips,$FE,onb,$FE

* if EZE and DPB and IPS then ONB

28.               

 

dc.b

eze,dps,ipb,$FE,onb,$FE

* if EZE and DPS and IPB then ONB

29.               

 

dc.b

eze,dps,ips,$FE,onb,$FE

* if EZE and DPS and IPS then ONB

30.               

 

dc.b

ens,dns,ins,$FE,ops,$FE

* if ENS and DNS and INS then OPS

31.               

 

dc.b

ens,dns,ize,$FE,ops,$FE

* if ENS and DNS and IZE then OPS

32.               

 

dc.b

ens,dze,ins,$FE,ops,$FE

* If ENS and DZE and INS then OPS

33.               

 

dc.b

ens,dze,ize,$FE,ops,$FE

* If ENS and DZE and IZE then OPS

34.               

 

dc.b

eze,dns,ins,$FE,ops,$FE

* if EZE and DNS and INS then OPS

35.               

 

dc.b

eze,dns,ize,$FE,ops,$FE

* if EZE and DNS and IZE then OPS

36.               

 

dc.b

eze,dze,ins,$FE,ops,$FE

* if EZE and DZE and INS then OPS

37.               

 

dc.b

eze,dze,ize,$FE,oze,$FE

* if EZE and DZE and IZE then OZE

38.               

 

dc.b

eps,dps,ips,$FE,ons,$FE

* if EPS and DPS and IPS then ONS

39.               

 

dc.b

eps,dps,ize,$FE,ons,$FE

* if EPS and DPS and IZE then ONS

40.               

 

dc.b

eps,dze,ips,$FE,ons,$FE

* if EPS and DZE and IPS then ONS

41.               

 

dc.b

eps,dze,ize,$FE,ons,$FE

* if EPS and DZE and IZE then ONS

42.               

 

dc.b

eze,dps,ips,$FE,ons,$FE

* if EZE and DPS and IPS then ONS

43.               

 

dc.b

eze,dps,ize,$FE,ons,$FE

* if EZE and DPS and IZE then ONS

44.               

 

dc.b

eze,dze,ips,$FE,ons,$FE

* if EZE and DZE and IPS then ONS

45.               

 

dc.b

$FF

 

 

נשים לב שבסיום רשימת תוויות הכניסה (בין רשימת תוויות הכניסה לרשימת תווית המוצא) מפריד המספר השמור $FE. בסיום רשימת המוצא מופיע גם כן המספר השמור $FE. בסיום הרשימה כולה מופיע המספר השמור $FF.

נגדיר כעת את מספרי ה singleton עבור ביצוע תהליך ה- defuzzification. זה מופיע בטבלה 3.

 

טבלה 3: מספרי singleton עבור תהליך הדה פאזיפיקציה שממיר את השתייכות המוצא למוצא קריספי

 

 

תויות מוצא פאזי

singleton ערך מספר

ONB

-128

ONS

-60

OZE

0

OPS

+60

OPB

+128

 

כעת נכתוב התוכנית לקביעת ה- Duty cycle בכל מנוע. זה מופיע בתוכנית 11.


תוכנית 11: תוכנית פסיקת גלישת השעון לקביעת ערך duty cycle של מנועים שמאל וימין תוך שימוש בהוראות לוגיקה עמומה של מעבד 68hc912d60a

 

1.       

ovf_fuz:

 

 

 

2.       

addsingleton:

dc.b

255,188,128,68,0

 

3.       

*                  128 subtructed +127  60  0  -60  -128

4.       

 

ldaa

l_speed

* load desired speed (in tics/8.125ms) for left motor

5.       

 

suba

l_count

* subtract the actual speed (tics) from the desired one for left motor and find left speed error

6.       

 

staa

l_error

* save current left motor error

7.       

 

ldx

#s_tab

 

8.       

 

ldy

#fuzvar

 

9.       

 

mem

 

* calculate EPB

10.   

 

mem

 

* calculate EPS

11.   

 

mem

 

* calculate EZE

12.   

 

mem

 

* calculate ENS

13.   

 

mem

 

* calculate ENB

14.   

 

ldaa

l_error

* load current left motor error

15.   

 

suba

old_lerr

* subtract the previous left speed error from the current one and find the derivative (tics)

16.   

 

ldx

#a_tab

 

17.   

 

mem

 

* calculate DPB

18.   

 

mem

 

* calculate DPS

19.   

 

mem

 

* calculate DZE

20.   

 

mem

 

* calculate DNS

21.   

 

mem

 

* calculate DNB

22.   

 

ldaa

l_error

* load acca with current left speed error

23.   

 

adda

l_sum

* add all errors and find left speed  integral value

24.   

 

bvc

l_i_calc

* if overflow occurred assign maximum value of 240 to acca

25.   

 

ldaa

#240

 

26.   

l_i_calc:

ldx

#i_tab

 

27.   

 

mem

 

* calculate IPB

28.   

 

mem

 

* calculate IPS

29.   

 

mem

 

* calculate IZE

30.   

 

mem

 

* calculate INS

31.   

 

mem

 

* calculate INB

32.   

 

ldab

#5

* five output labels

33.   

cloop:

clr

1,y+

* clear OPB, OPS, OZE, ONS, ONB

34.   

 

dbne

b,cloop

 

35.   

 

ldx

#rules

 

36.   

 

ldy

#fuzvar

 

37.   

 

ldaa

#$ff

 

38.   

 

rev

 

* prepare outputs from rules and inputs

39.   

 

ldy

#fuzout

 

40.   

 

ldx

#addsingleton

* prepare for crisp output

41.   

 

ldab

#5

 

42.   

 

wav

 

* find crisp output

43.   

 

ediv

 

 

44.   

 

tfr

y,d

 

45.   

 

subb

#128

* find final DU for left duty

46.   

 

stab

dpower

 

47.   

 

addb

pwdty1

* calculate new duty value

48.   

 

bvc

ldtychk

* if overflow occurred, assign max or min values

49.   

 

ldab

dpower

 

50.   

 

bmi

lmindty

* overflow of low value, so assign min duty

51.   

 

movb

#240, pwdty1

* overflow of high value, so assign max duty

52.   

 

jmp

lhskping

* update left old error and integral values

53.   

lmindty:

movb

#40, pwdty1

 

54.   

 

jmp

lhskping

 

55.   

ldtychk:

cmpb

#240

* if value is more than 240, force 240

56.   

 

blo

llowchk

 

57.   

 

movb

#240, pwdty1

 

58.   

 

jmp

lhskping

 

59.   

llowchk:

cmpb

#40

* if value is less than 40, force 40

60.   

 

bhi

lputdc

 

61.   

 

movb

#40, pwdty1

 

62.   

 

jmp

lhskping

 

63.   

lputdc:

stab

pwdty1

* otherwise assign new duty value to pwdty1 (left motor speed)

64.   

lhskping:

movb

l_error,old_lerr

* update old error value

65.   

 

ldaa

l_error

* update left integral value

66.   

 

adda

l_sum

 

67.   

 

bvc

l_integ

 

68.   

 

ldaa

l_error

 

69.   

 

bmi

l_minsum

 

70.   

 

movb

#240, l_sum

* keep max value at 240

71.   

 

jmp

rht_chk

 

72.   

l_minsum:

movb

#40, l_sum

* keep min value at 40

73.   

 

jmp

rt_chk

 

74.   

l_integ:

stab

l_sum

 

75.   

rt_chk

ldaa

r_speed

* load desired speed (in tics/8.125ms) for right motor

76.   

 

suba

r_count

* subtract the actual speed (tics) from the desired one for right motor and find right speed error

77.   

 

staa

r_error

* save current right motor error

78.   

 

ldx

#s_tab

 

79.   

 

ldy

#fuzvar

 

80.   

 

mem

 

* calculate EPB

81.   

 

mem

 

* calculate EPS

82.   

 

mem

 

* calculate EZE

83.   

 

mem

 

* calculate ENS

84.   

 

mem

 

* calculate ENB

85.   

 

ldaa

r_error

* load current right motor error

86.   

 

suba

old_rerr

* subtract the previous right speed error from the current one and find the derivative (tics)

87.   

 

ldx

#a_tab

 

88.   

 

mem

 

* calculate DPB

89.   

 

mem

 

* calculate DPS

90.   

 

mem

 

* calculate DZE

91.   

 

mem

 

* calculate DNS

92.   

 

mem

 

* calculate DNB

93.   

 

ldaa

r_error

* load acca with current right speed error

94.   

 

adda

r_sum

* add all errors and find right speed  integral value

95.   

 

bvc

r_i_calc

* if overflow occurred assign maximum value of 240 to acca

96.   

 

ldaa

#240

 

97.   

r_i_calc:

ldx

#i_tab

 

98.   

 

mem

 

* calculate IPB

99.   

 

mem

 

* calculate IPS

100.           

 

mem

 

* calculate IZE

101.           

 

mem

 

* calculate INS

102.           

 

mem

 

* calculate INB

103.           

 

ldab

#5

* five output labels

104.           

cloop:

clr

1,y+

* clear OPB, OPS, OZE, ONS, ONB

105.           

 

dbne

b,cloop

 

106.           

 

ldx

#rules

 

107.           

 

ldy

#fuzvar

 

108.           

 

ldaa

#$ff

 

109.           

 

rev

 

* prepare outputs from rules and inputs

110.           

 

ldy

#fuzout

 

111.           

 

ldx

#addsingleton

* prepare for crisp output

112.           

 

ldab

#5

 

113.           

 

wav

 

* find crisp output

114.           

 

ediv

 

 

115.           

 

tfr

y,d

 

116.           

 

subb

#128

* find final DU for left duty

117.           

 

stab

dpower

 

118.           

 

addb

pwdty0

* calculate new duty value

119.           

 

bvc

rdtychk

* if overflow occurred, assign max or min values

120.           

 

ldab

dpower

 

121.           

 

bmi

rmindty

* overflow of low value, so assign min duty

122.           

 

movb

#240, pwdty0

* overflow of high value, so assign max duty

123.           

 

jmp

rhskping

* update right old error and integral values

124.           

rmindty:

movb

#40, pwdty0

 

125.           

 

jmp

rhskping

 

126.           

rdtychk:

cmpb

#240

* if value is more than 240, force 240

127.           

 

blo

rlowchk

 

128.           

 

movb

#240, pwdty0

 

129.           

 

jmp

rhskping

 

130.           

rlowchk:

cmpb

#40

* if value is less than 40, force 40

131.           

 

bhi

rputdc

 

132.           

 

movb

#40, pwdty0

 

133.           

 

jmp

rhskping

 

134.           

rputdc:

stab

pwdty0

* otherwise assign new duty value to pwdty0 (right motor speed)

135.           

rhskping:

movb

r_error,old_rerr

* update old right error value

136.           

 

ldaa

r_error

* update right integral value

137.           

 

adda

r_sum

 

138.           

 

bvc

r_integ

 

139.           

 

ldaa

r_error

 

140.           

 

bmi

r_minsum

 

141.           

 

movb

#240, r_sum

* keep max value at 240

142.           

 

jmp

sium

 

143.           

r_minsum:

movb

#40, r_sum

* keep min value at 40

144.           

 

jmp

sium

 

145.           

r_integ:

stab

r_sum

 

146.           

sium:

movb

#$00, l_count

* clear left counter for next loop

147.           

 

movb

#$00, r_count

* clear right counter for next loop

148.           

 

movb

#$03, tflg1

* clear flags

149.           

 

movb

#$80, tflg2

* clear TCNT overflow flag

150.           

 

rti

 

* go out until next TCNT overflow

 

ההערות שבגוף התוכנית מסבירות את הנעשה בה. לכן אעבור על התוכנית באופן כללי.

 

 שורה 1 מכילה את שם שגרת הפסיקה. שגרה זו תתבצע כל 8.125 ms שזה הזמן בין גלישה אחת של השעון לזו שבאה אחריה.

 

בשורה 2, מופיעים ערכי ה singleton לפונקציית השתייכות המוצא.

 

שורות 4 עד 74 מטפלות במציאת ההפרש שיש להוסיף לduty של מנוע שמאל בעקבות נתון המהירות הנוכחית (tics/8.125ms) וביצוע ניתוח pid בפאזי. שורות 4 ו- 5 מוצאות את השגיאה, שורות 7-13 משמשות לחישוב דרגת ההשתייכות של מבוא פרופורצית השגיאה, שורות 14 עד 21 משמשות לחישוב דרגת ההשתייכות של מבוא נגזרת השגיאה, ושורות 22 עד 31 משמשות לחישוב דרגת ההשתייכות של מבוא אינטגרל השגיאה.

 

שורות 32 עד 34 דואגות לאיפוס תוויות המוצא, שורות 35 עד 38 מבצעות את החוקים הפאזיים על הכניסות הפאזיות שהתקבלו מהוראות mem בשורות 7 עד 31.

 

שורות 39 עד 43 דואגות למציאת המוצא הקריספי של האיטרציה הנוכחית למנוע שמאל. בשורה 43 מתבצעת הוראת ediv בכדי לקבל הנתון ב-Y והשארית ב- D. בשורה 44 אנו מעבירים את Y ל- D בכדי שהתוצאה תהיה ב- D. אנו מתחשבים ב- 8 ביטים הנמוכים     (LSB), הנמצאים בצובר B. בשורה 45 מפחיתים 128 מהתוצאה בכדי לקבל גם ערכים שליליים ולהתאים התוצאה לתחום המבוקש. התוצאה נשמרת ב- dpower. את התוצאה מחברים למספר שכבר נמצא ב- pwdty1 האוגר שמכיל את ה duty של מנוע שמאל.

 

שורות 48 עד 63 בודקות האם קרתה גלישה. אם כן מכניסים ל- pwdty1 ערכי קיצון 240 או 40, לפי כיוון הגלישה. אם לא קרתה גלישה נבדק ערכו החדש של pwdty1. אם הוא בתחום שבין 240 לבין 255, ערכו מושם למקסימום המותר, 240. אם הוא בתחום שבין 0 ל- 40, ערכו מושם למינימום המותר 40. אחרת נשמר ערכו החדש ב pwdty1. בשורות 63 עד 74 מעודכנים ערכי old_lerr (השגיאה הקודמת), והאינטגרל (l_sum) תוך שמירה על ערכי המינימום והמקסימום המותרים.

 

בצורה דומה מתעדכן ערכו של pwdty0 של מנוע ימין בשורות 75 עד 145. בשורות 146 עד 149 מאופסים המונים של אנקודר מנוע ימין ואנקודר מנוע שמאל, וכמו כן מאופסים הדגלים של קצוות האנקודרים העולים, ושל גלישת השעון.

 

שורה 150 מסמנת את סיום שגרת פסיקת הגלישה והחזרת השליטה לתוכנית הראשית.




מעוניין לדעת כיצד לשלוט על מנועים טוב יותר?

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

כל הזכויות שמורות לאסף פוניס, גיא יונה ואלי קולברג ©
אין להעתיק תכנים מאתר זה ללא רשות בכתב ממנהלי האתר

אתר זה נצפה באופן מיטבי ברזולוציית 1024X768