3.13. יצירת אות אנלוגי עם PWM ומסנן RC

ה-ADC קורא מתחים על פין. ההפך – ייצור מתח ביניים בין 0 V ל-Vcc על פין – קשה יותר, מכיוון שמוצא GPIO יודע רק כיצד להניע את שני הפסים שלו. התחליף הסטנדרטי הוא להחליף את הפין בין הפסים במהירות מספקת כך שהמתח הממוצע הוא מה שמעניין אתכם.

3.13.1. אפנון רוחב פולס (PWM)

אות מאופנן ברוחב פולס (PWM) הוא גל ריבועי בתדר קבוע אשר זמן-הגובה שלו – החלק מכל מחזור המבלה ב-Vcc במקום באדמה – נקבע בתוכנה. אותו חלק הוא מחזור הפעולה (duty cycle). המתח הממוצע של צורת הגל הוא מחזור הפעולה כפול Vcc:

V_avg = duty × Vcc

מחזור פעולה של 25 % מתמצע ל-Vcc / 4; מחזור פעולה של 50 % ל-Vcc / 2; מחזור פעולה של 75 % ל-3 × Vcc / 4.

Three square-wave traces stacked vertically, each at the same frequency. The top wave is high for 25 % of each period and low for 75 %. The middle wave is high and low for half the period each. The bottom wave is high for 75 % and low for 25 %.

PWM במחזורי פעולה של 25 %, 50 % ו-75 %. המתח הממוצע עוקב אחר מחזור הפעולה.

התדר נקבע בעת תצורת ה-PWM; מחזור הפעולה הוא מה שהתוכנה משנה תוך כדי תנועה. המחלקה machine.PWM עוטפת ערוץ טיימר חומרתי שמייצר את צורת הגל ללא עזרת המעבד – לאחר התצורה, האות ממשיך בתדר ובמחזור הפעולה שנבחרו עד שמשתנה.

3.13.2. המחלקה machine.PWM

בנו מופע של PWM עם הפין ועם תדר ומחזור פעולה התחלתיים:

from machine import PWM, Pin

pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)

זה מתחיל גל ריבועי של 20 kHz במחזור פעולה של 50 % על P7. שתי מתודות משנות את המוצא תוך כדי תנועה:

pwm.duty_u16(16384)   # change to 25 % (16384 / 65535)
pwm.freq(5_000)       # change to 5 kHz

duty_u16() מקבלת מספר שלם לא-מסומן בן 16 סיביות הממפה את 0 ל“תמיד נמוך“ ואת 65535 ל“תמיד גבוה“. freq() קובעת את תדר הנשא בהרץ.

הערה

כל ערוץ PWM על אותו טיימר חומרתי חולק את תדרו. קריאה ל-freq() על ערוץ אחד משנה כל ערוץ אחר המחובר לאותו טיימר. השתמשו בערוצים של טיימרים שונים כאשר מוצאים חייבים לרוץ בתדרים שונים.

קראו ל-deinit() כדי לשחרר את ערוץ הטיימר כאשר המוצא כבר אינו נדרש.

3.13.3. מיצוע באמצעות מסנן RC מעביר-נמוכים

PWM גולמי אינו מתח חלק; הוא גל ריבועי שהממוצע שלו הוא מה שאנו רוצים. כדי לחלץ את אותו ממוצע, העבירו את ה-PWM דרך מסנן מעביר-נמוכים – אותו שילוב של נגד-וקבל ששימש לביטול ריטוט מתגים ב-ביטול ריטוט (Debouncing).

A PWM pin connects through a series resistor R to an output node. A capacitor C from that node to ground completes the low-pass filter; the smoothed voltage appears at V_out.

PWM דרך מסנן RC מעביר-נמוכים: הקבל ממצע את הגל הריבועי למתח DC הפרופורציוני למחזור הפעולה.

תדר החיתוך של המסנן – הגבול בין תדרים שהוא מעביר לבין אלו שהוא חוסם – נקבע על ידי אותו מכפלת RC שנתנה את קבוע הזמן עבור מעגל ביטול הריטוט:

f_c = 1 / (2π × R × C)

כדי שהמסנן יחלץ מתח DC נקי מכניסת PWM, תדר החיתוך חייב להיות נמוך בהרבה מתדר ה-PWM עצמו. רכיב ה-DC (תדר 0) עובר ללא שינוי; ההרמוניה היסודית של ה-PWM (בתדר ה-PWM) מוחלשת בערך ב-f_c / f_PWM. יחס של 1 / 200 חותך את האדווה השיורית במוצא ל-0.5 % בערך מתנודת הכניסה.

נקודת התחלה סבירה עבור ערך-יעד המשתנה לאט:

  • תדר PWM של f_PWM = 20 kHz – הרבה מעל לתחום השמע, וקל לטיימר לייצר אותו בנקיות.

  • ערכי מסנן R = 1.6 , C = 1 µF – הנותנים f_c = 1 / (2π × 1.6 × 1 µF) 100 Hz.

דיכוי פי 200 בנשא מצמצם את התנודה המלאה של ה-PWM לכדי Vcc / 200 בערך של אדווה שיורית ב-V_out – בערך 16 mV ב-3.3 V.

שתי הערות מעשיות:

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

  • לוקח לקבל בערך 5 × R × C 8 ms להתייצב כאשר מחזור הפעולה משתנה; V_out מפגר אחר הגדרת מחזור הפעולה במידה זו. עבור ערך-יעד שצריך להתעדכן מהר יותר, העלו את תדר החיתוך (R או C קטנים יותר) וקבלו יותר אדווה.