איך זה עובד: אנלוגי לדיגיטלי ובחזרה
המחשב לא שומע מוזיקה כמו שאנחנו שומעים, אז איך הביט-בוקס הופך לביטים במחשב, ומה הופך את המספרים בחזרה למוזיקה
המידע שהחושים שלנו קולטים מהעולם האמתי הוא רציף. כשהשמש זורחת בבוקר, עוצמת האור מתגברת באופן "חלק" לגמרי, לא בקפיצות הקטנות של הזריחה במשחק Minecraft. כשאנחנו שותים תה אנחנו יכולים לבקש כפית או שתיים של סוכר, אבל אי אפשר לומר שהמתיקות של התה היא בדיוק 1 או 2. ההתקנים הספרתיים המודרניים – מחשבים, מיקרו-בקרים ועוד – חייבים לכמת את המידע שמגיע מבחוץ ולשים אותו על סקאלות מצומצמות למדי של מספרים בדידים.
ההמרה של מידע רציף לבדיד לשימושן של מערכות ספרתיות נקרא Analog to Digital Conversion (בקיצור ADC), והתהליך ההפוך – זה שמאפשר למחשבים ליצור פלט פיזיקלי רציף-לכאורה, כגון להשמיע מוזיקה או לעמעם את התאורה של המסך – מכונה DAC. איך זה מתבצע בשטח?
לפני שנתחיל, במאמר מוסגר, ראוי לציין שאפילו התפיסה החושית האנושית אינה רציפה במלוא מובן המילה. כדי שנהיה מודעים לשינוי בגובה צליל, עוצמת אור וכדומה, גודל השינוי הזה חייב לעבור רף מסוים שתלוי גם בפיזיולוגיה שלנו, גם בתשומת הלב שלנו וגם בעוצמה ההתחלתית של הקלט. תחום מסקרן זה של חקר התפיסה שייך לפסיכולוגיה הקוגניטיבית ולא לאלקטרוניקה, ולכן נסתפק כאן בקישור לחוק ובר-פכנר הקלאסי. עוד דבר שחשוב לציין הוא שמחשבים מסוגלים לדיוק גבוה מאד: בעזרת תוכנה מתאימה אפשר לחשב מספרים בעלי מאות ואלפי ספרות לפני ואחרי הנקודה. עם זאת, ברוב המקרים דיוק כזה אינו מעשי ואינו דרוש לצורך המרות של מידע פיזיקלי בזמן אמת.
נתחיל בדוגמה מוחשית במיוחד: המרה מאנלוגי-לדיגיטלי של זווית סיבוב. ניקח דיסקית שמסתובבת על ציר ונצבע אותה כמו באיור המאוד לא מדויק הבא:
שני הריבועים האדומים הם חיישנים פשוטים, שכל אחד מהם נותן לנו מתח חשמלי ("1" לוגי) כשיש תחתיו צבע כחול, ולא נותן מתח ("0" לוגי) כשהצבע לבן. החיישנים קבועים במקומם בזמן שהדיסקית מסתובבת. במקרה מימין, שני החיישנים רואים צבע לבן, ולכן הקריאה מהם היא 00. קריאה זו תישאר זהה גם אם נסובב את הדיסקית כמה עשרות מעלות בכיוון השעון. אך אם נסובב מספיק – מאה מעלות, במקרה האמצעי – החיישן הימני יהיה מעל שטח כחול, והקריאה משני החיישנים תהפוך ל-01. במקרה השמאלי (300 מעלות), הקריאה תגיע ל-11. בצורה כזו הסיבוב של הדיסקית על הציר, שהוא פעולה אנלוגית לגמרי, הופך למספר בדיד בין 0 ל-3 בקוד בינארי. כמובן שהרבה מידע הולך לאיבוד בדרך, אם כי זה המחיר שמשלמים בהכרח על המרות ADC.
אגב, הדוגמה למעלה אינה רק לצורכי לימוד. ישנם רכיבים שעובדים בדיוק ככה, או כמעט בדיוק ככה, שמטרתם למדוד זוויות ותנועה של מנועים, מסועים, זרועות רובוטיות ועוד.
עם זאת, כשמדברים על DAC/ADC, הכוונה בדרך כלל להמרה לא של זוויות סיבוב אלא של מתחים חשמליים. את זה אפשר לבצע בכל כך הרבה דרכים שונות, שאפילו רשימת השמות שלהן תמלא לבדה את כל הטור הזה. לכן אתמקד כאן רק בשתי דוגמאות קלות יחסית להבנה. שתיהן זקוקות לרכיב אלקטרוני בסיסי שמשווה מתחים (Comparator). אפילו לרכיב בסיסי כזה יש הרבה מימושים, אז לצורך הדוגמאות שלנו ניקח משווה בעל שתי כניסות (A ו-B) ויציאה אחת (Y). אם המתח ב-A גדול מהמתח ב-B, המתח ב-Y ייצג 1 לוגי. אם A קטן או שווה ל-B, לא יהיה מתח ב-Y, כלומר 0 לוגי.
המרה מבוססת זמן
כאן אנחנו זקוקים לשני רכיבים נוספים: מונה בינארי (מעגל דיגיטלי שמגדיל ב-1 מספר בינארי בכל פעם שמגיע אות משעון המערכת), ורכיב שמחולל גל "שן מסור". כך נראה גל "שן מסור" אידאלי:
עליית המתח בגל הזה היא אנלוגית כשלעצמה, אך היא אינה תלויה בקלט שמגיע מבחוץ ולכן ניתנת להפקה קלה יחסית. המתח מתחיל ב-0 וולט, עולה בקצב אחיד עד לשיא קבוע, ואז צונח לאפס ומתחיל מהתחלה. אנחנו נאפס את המונה הבינארי שלנו בכל פעם שהגל צונח לאפס, ונתזמן את העניינים כך שבין צניחה לצניחה, שעון המערכת "יתקתק" בדיוק 255 פעמים.
כעת, נחבר את הגל המחזורי לכניסה A של משווה מתחים, את הקלט החיצוני לכניסה B, ונמתין לרגע שבו היציאה Y תעבור מ-0 ל-1. כשזה יקרה, סימן שהמתח העולה של הגל חצה את הרף של הקלט החיצוני. נזדרז ונסתכל איזה מספר מופיע לנו באותו רגע במונה הבינארי. המספר הזה יהיה בהכרח בין 0 ל-255, וביחס ישר לזמן שעבר מאז תחילת הספירה – כלומר, ביחס ישר גם למתח החיצוני! במילים אחרות, בהנחה שווידאנו שהמתח החיצוני לא יהיה לעולם גבוה יותר מהמקסימום של הגל, המרנו את הקלט האנלוגי למספר בינארי בן 8 ביטים.
כך זה נראה בשרטוט: המתח החשמלי של גל שן המסור (בשחור) עולה עד שהוא מגיע לרמה של הקלט (קו אדום אופקי). בנקודת זמן זו, היציאה של משווה המתחים מתחלפת מ-0 ל-1, ואז אנחנו מציינים (קו אנכי) את הערך שבמונה הבינארי, שספר לו בינתיים בשקט ברקע.
אחד היתרונות של השיטה הזו הוא שקל מאד להתאים אותה להמרה בכיוון ההפוך, מדיגיטלי לאנלוגי. נניח שמתח חיצוני X הומר במערכת למספר הבדיד 183, ואחרי כמה זמן בא לנו להוציא מהמערכת מתח זהה לזה שנכנס. נתזמן את גל שן המסור ואת המונה הבינארי כפי שעשינו קודם, אבל הפעם נבדוק לא את משווה המתחים אלא את המונה עצמו. כאשר הוא יגיע לערך הרצוי של 183, נוציא כפלט את המתח של הגל באותו רגע. פשוט, נכון?
החיסרון של השיטה הוא, כמובן, שכל מדידה לוקחת זמן. אנחנו תלויים גם בתדר של הגל וגם בשעון המערכת: למעשה, כדי לקבל מדידות מדויקות של מתח חיצוני בערכים של 0-255, נצטרך לחכות בממוצע 128 מחזורי שעון לכל מדידה, וזה המון. אם ננסה להגיע לדגימה ברזולוציה של 16 ביטים, שזה 0 עד 65,535, העיכוב יהפוך למגוחך ממש.
המרה באמצעות קירוב הדרגתי
צורת המרה זו מאנלוגי לדיגיטלי, שקיימת בין השאר במיקרו-בקרים נפוצים, היא קצת מעגלית מכיוון שהיא זקוקה לרכיב DAC (מדיגיטלי לאנלוגי) פנימי, אך כאשר מתגברים על המכשול הזה אפשר לקבל המרת ADC מהירה ומדויקת יחסית גם ברזולוציה גבוהה.
ראשית, שולחים לרכיב ה-DAC הפנימי ערך באמצע הסקאלה, ומשווים את המתח שיוצא ממנו למתח של הקלט. אם הקלט נמוך יותר, שולחים ל-DAC ערך שנמצא בחצי הדרך בין 0 לערך שהיה קודם. לעומת זאת, אם הקלט גבוה יותר ממה שה-DAC נתן, נעביר ל-DAC ערך חדש שהוא בחצי הדרך בין הערך הקודם לבין המקסימום. נמשיך לחלק כך שוב ושוב, עד שנגיע לערך מסוים, שהמשווה ייתן לנו תוצאה שונה מעליו ומתחתיו. זהו הערך הבדיד הקרוב ביותר לקלט החיצוני, והיתרון של השיטה הזו הוא שאפשר להגיע לתוצאה מהר מאד. זה מה שמכונה בעולם התכנות "חיפוש בינארי", או בשפה עממית יותר "אריה במדבר" (ראו בפוסט המצוין בבלוג "לא מדויק").
נמחיש את ההמרה הזו עם דוגמה פשטנית, של טווח הערכים השלמים בין 0 ל-15 (4 ביטים) וקלט שווה ערך ל-11 (אם כי בהתחלה אנחנו כמובן לא יודעים את זה). אנחנו משווים את הקלט לערך באמצע הסקאלה – 8. המשווה אומר לנו שהערך 8 קטן יותר מהקלט, ולכן ננסה שוב עם ערך בין 8 ל-15, זאת אומרת 12. הפעם המשווה יראה שהערך החדש גדול מהקלט, אז נלך למשהו באמצע הדרך בין הערך הנוכחי (12) לזה שהיה לפניו (8), ונבדוק את 10. גם הוא קטן מדי, אז נבדוק את מה שבין 10 לערך שהיה לפניו (12), כלומר 11. התשובה כאן תלויה במימוש הספציפי של המשווה, אם כי בכל מקרה לא נצטרך להתאמץ עוד הרבה כדי לגלות שזה הערך שאנחנו מחפשים.
כאמור, תחום ה-ADC/DAC הוא רחב ומורכב מאד, ולא כיסינו כאן אפילו חלק קטן ממנו. לקריאה נוספת (באנגלית), לחצו כאן.