אני מניח שכבר ראיתם את שלט הכפפה שהכנתי למכונית-על-שלט (אם לא, הסרטון נמצא כאן). בפוסט זה אדבר על פתרון קטן וחכם, שאמנם לא אני המצאתי אבל השתמשתי בו כדי לשפר את השליטה במכונית, ואציג את ההקשר הרחב והחשוב הרבה יותר של הפתרון הזה – בעולם האלקטרוניקה בכלל וביישומים "בעולם האמתי" בפרט.
הבעיה: רעש
השליטה בפניה של המכונית ימינה או שמאלה מושגת באמצעות מד תאוצה (Accelerometer), רכיב שמסוגל "לדווח" על זווית ההטיה שלו באמצעות מתח חשמלי משתנה. לצורך העניין, נניח שב-0 מעלות גם המתח הוא 0V, והוא הולך ועולה ככל שהזווית גדלה, עד לערך של 5V עבור הטיה של 90 מעלות. את המתח הזה אנחנו יכולים לקרוא דרך אחד הפינים האנלוגיים של הארדואינו עם הפונקציה analogRead, והיא תחזיר לנו מספר בין 0 ל-1023 שמייצג את טווח המתחים שהוזכר. כלומר, עליה של אחד בערך שמתקבל מ-analogRead פירושה עוד 5 מילי-וולט במתח שמגיע מהרכיב, ואלה מייצגים קצת פחות מעשירית המעלה.
את כפפת השליטה הכנתי כך שכאשר היא במצב נייטרלי, מד התאוצה נמצא בזווית של איפשהו בין 30 ל-60 מעלות. לכאורה, אפשר לקבוע בתוכנה שזווית קטנה מ-30 תגרום לשליחה של פקודת פניה לכיוון אחד, זווית גדולה מ-60 תשלח פקודת פניה לכיוון השני, וכל מה שבין לבין לא ישלח כלום. פשוט, נכון?
אז זהו, שלא. ראשית, היד של המשתמש עלולה לזוז באקראי או לרעוד מעט, ואם זה קורה סביב אחד הגבולות האלה, גם המכונית תגיב ברעידה תזזיתית של הגלגלים הקדמיים. ומה שעוד יותר גרוע, הדיוק של מד התאוצה והדיוק של הקריאה האנלוגית בארדואינו גם הם רחוקים משלמות. בכל מדידה פיזיקלית יש כמות מסוימת של רעש, שגיאות אקראיות שיכולות להגיע מאלף ואחד מקורות בחוץ או במכשיר המדידה עצמו. המשמעות, במקרה שלנו, היא שהקוד בארדואינו יכול להגיע במקרה הטוב לרזולוציה של חצי מעלה, ובשילוב עם הגורם האנושי שהזכרתי קודם, זה אומר שמכונית הצעצוע תפרפר קצת כמעט בכל פעם שנבצע פניה, ואת זה אנחנו לא רוצים.
דרך אחת להיפטר מטעויות אקראיות היא לבצע מספר מדידות ולחשב ממוצע. זה עובד כי סטיות אקראיות מתקזזות, בסופו של דבר, זו עם זו ו"נעלמות". עם זאת, חישוב ממוצע דורש משאבים מהמיקרו-בקר, והוא עדיין לא פותר את בעיית התזוזות של יד המשתמש.
זה שעולה וזה שיורד
נעזוב לרגע את המכונית, ובואו נסתכל על מערכת הקלט הדיגיטלי של הארדואינו. בהסברים הרשמיים אומרים לנו שהפונקציה digitalRead מחזירה לנו אפס ("LOW") כשאין מתח על פין הקלט, ואחד ("HIGH") כשיש. אבל איפה בדיוק עובר הגבול בין LOW ל-HIGH? מה הסף? מה הערך המדויק של המתח שבו זה קורה?
נניח, לצורך הפשטות בלבד, שהערך הרשמי הוא בדיוק באמצע טווח מתחי העבודה של הארדואינו – 2.5 וולט. כמו שאמרנו, בעולם האמתי אנחנו אף פעם לא מקבלים ערכים מדויקים לגמרי, ומתחים עשויים להשתנות בגלל התנהגות הסוללה, קלט ופלט נוספים במערכת ועוד. זאת אומרת, אם המתח הממוצע יהיה מספיק קרוב לערך הסף של 2.5, הקלט שלנו עלול לפרפר בטירוף בין 0 ל-1. במיוחד אם הקלט הזה משפיע ישירות על פעולה כלשהי במערכת, שצורכת בעצמה חשמל ומשנה את המאזן הכללי!
הפתרון המקובל לבעיה הזו הוא מעגל חומרה שנקרא "שמיט טריגר" (Schmitt Trigger), על שם ממציאו, אוטו שמיט. למעגל זה יש קלט אנלוגי, פלט דיגיטלי ושני ספי הפעלה: סף גבוה, שקלט גבוה ממנו גורם לפלט 1, וסף נמוך שקלט נמוך ממנו גורם לפלט 0. ומה קורה אם הקלט נמצא דווקא בין הסף הנמוך לגבוה? לזה קוראים "היסטרזיס" (Hysteresis): למעגל הזה יש מעין "זיכרון", כך שהפלט נשאר כפי שהיה קודם!
הנה דוגמה. נניח שיש לנו פין קלט דיגיטלי עם שמיט טריגר, שהספים שלו הם 2 וולט ו-3 וולט, ונניח שהמתח עליו מתחיל ב-0 ועולה. הפלט ההתחלתי הוא 0, והוא נשאר כזה עד שהמתח מגיע לסף הגבוה של 3 וולט. אז הפלט הופך ל-1, וגם אם המתח מתנדנד בצורה משמעותית, הפלט יישאר אחד כל עוד המתח בתחום ההיסטרזיס ומעלה. רק כשהמתח יורד שוב מתחת ל-2 יתקבל פלט 0, והוא יישאר עד שהמתח יגיע שוב ל-3.
חזרה למכונית
אם הייתי רוצה להשתמש בשמיט טריגר חומרה בשביל המכונית שלי, הייתי בבעיה: צריך אחד בשביל הפניה ימינה (שיחליט בין פקודת פניה ימינה למצב של אין פקודה) ואחד לפניה שמאלה (שיחליט בין פניה שמאלה לאין פקודה) – ולכל אחד מהם צריך מן הסתם ספים לא סטנדרטיים.
במקום זה, פשוט כתבתי קוד לארדואינו שמתפקד כשמיט טריגר כפול. סביב הנקודות הקריטיות (30 ו-60 מעלות) הוגדר טווח היסטרזיס, ובין שני הטווחים האלה שנוצרו נמצא ה"שטח" שאומר לארדואינו לא לשדר שום פקודת פניה. הטווחים מספיק רחבים כדי לספוג כמעט את כל ההפרעות האקראיות, מהמשתמש או מהחומרה, וכך, באמצעות הוספה של מספר פקודות if, חמקתי ממלכודת הרעש ויצרתי שיטה לשליטה טובה ומבוקרת בפניה של המכונית.
בהרבה מאד רכיבים אלקטרוניים מתקדמים יש מעגלי שמיט טרידר, שנועדו לסינון רעשים. למעשה, וזו עובדה שהסתרתי בכוונה מוקדם יותר, גם למיקרו-בקרים הנפוצים יש שמיט טריגר על פיני הקלט הדיגיטלי. ב-ATmega328 של הארדואינו, הסף ה"רשמי" לאות דיגיטלי הוא בסביבות 2.6 וולט (במתח עבודה של 5V), עם שולי בטחון של 0.5 וולט. אם יש לכם ספק כוח עם שליטה מדויקת במתח, תוכלו לבדוק בעצמכם את הערכים שגורמים למעבר מקריאה דיגיטלית של 0 ל-1 ולהיפך… ואל תשכחו לספר על הממצאים בתגובות!
יש דרך לבנות שמיט טריגר מרכיבים אלקטרוניים וללא מיקרו בקר?
בוודאי – חפש בגוגל schmitt trigger circuit 🙂
אחלה פוסט.. מעניין וכתוב מצוין. תודה!