3.13. Analoge Spannungen mit PWM und einem RC-Filter erzeugen¶
Der ADC liest Spannungen an einem Pin. Das Gegenteil – eine Zwischenspannung zwischen 0 V und Vcc an einem Pin zu erzeugen – ist schwieriger, da ein GPIO-Ausgang nur weiß, wie er seine beiden Versorgungsschienen ansteuert. Der übliche Ersatz besteht darin, den Pin so schnell zwischen den Schienen umzuschalten, dass die durchschnittliche Spannung das ist, worauf es ankommt.
3.13.1. Pulsweitenmodulation¶
Ein pulsweitenmoduliertes (PWM-)Signal ist eine Rechteckschwingung mit fester Frequenz, deren High-Zeit – der Anteil jedes Zyklus, der bei Vcc statt bei Masse verbracht wird – in der Software festgelegt wird. Dieser Anteil ist das Tastverhältnis. Die durchschnittliche Spannung des Signalverlaufs ist das Tastverhältnis mal Vcc:
V_avg = duty × Vcc
Ein Tastverhältnis von 25 % ergibt im Mittel Vcc / 4; ein Tastverhältnis von 50 % ergibt Vcc / 2; ein Tastverhältnis von 75 % ergibt 3 × Vcc / 4.
PWM mit 25 %, 50 % und 75 % Tastverhältnis. Die durchschnittliche Spannung folgt dem Tastverhältnis.¶
Die Frequenz wird beim Konfigurieren der PWM festgelegt; das Tastverhältnis ist das, was die Software im laufenden Betrieb ändert. Die Klasse machine.PWM kapselt einen Hardware-Timerkanal, der den Signalverlauf ohne Mithilfe der CPU erzeugt – einmal konfiguriert, läuft das Signal mit der gewählten Frequenz und dem gewählten Tastverhältnis weiter, bis es geändert wird.
3.13.2. Die Klasse machine.PWM¶
Erzeugen Sie eine PWM-Instanz mit dem Pin sowie einer anfänglichen Frequenz und einem Tastverhältnis:
from machine import PWM, Pin
pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)
Das startet eine 20-kHz-Rechteckschwingung mit 50 % Tastverhältnis an P7. Zwei Methoden ändern den Ausgang im laufenden Betrieb:
pwm.duty_u16(16384) # change to 25 % (16384 / 65535)
pwm.freq(5_000) # change to 5 kHz
duty_u16() nimmt eine vorzeichenlose 16-Bit-Ganzzahl entgegen, die 0 auf „immer low“ und 65535 auf „immer high“ abbildet. freq() legt die Trägerfrequenz in Hertz fest.
Bemerkung
Jeder PWM-Kanal am selben Hardware-Timer teilt sich dessen Frequenz. Der Aufruf von freq() an einem Kanal ändert jeden anderen Kanal, der an diesem Timer hängt. Verwenden Sie Kanäle unterschiedlicher Timer, wenn Ausgänge mit verschiedenen Frequenzen laufen müssen.
Rufen Sie deinit() auf, um den Timerkanal freizugeben, wenn der Ausgang nicht mehr benötigt wird.
3.13.3. Mitteln mit einem RC-Tiefpassfilter¶
Rohe PWM ist keine glatte Spannung; sie ist eine Rechteckschwingung, deren Mittelwert wir wollen. Um diesen Mittelwert zu extrahieren, leiten Sie die PWM durch einen Tiefpassfilter – dieselbe Widerstands-Kondensator-Kombination, die zum Entprellen von Schaltern in Entprellen verwendet wird.
PWM durch einen RC-Tiefpassfilter: Der Kondensator mittelt die Rechteckschwingung zu einer Gleichspannung, die proportional zum Tastverhältnis ist.¶
Die Grenzfrequenz des Filters – die Grenze zwischen den Frequenzen, die er durchlässt, und denen, die er blockiert – wird durch dasselbe Produkt RC bestimmt, das die Zeitkonstante für die Entprellschaltung lieferte:
f_c = 1 / (2π × R × C)
Damit der Filter eine saubere Gleichspannung aus einem PWM-Eingang extrahieren kann, muss die Grenzfrequenz deutlich niedriger sein als die PWM-Frequenz selbst. Der Gleichanteil (Frequenz 0) passiert unverändert; die Grundharmonische der PWM (bei der PWM-Frequenz) wird um etwa f_c / f_PWM gedämpft. Ein Verhältnis von 1 / 200 reduziert die Restwelligkeit am Ausgang auf etwa 0.5 % des Eingangshubs.
Ein vernünftiger Ausgangspunkt für einen sich langsam ändernden Sollwert:
PWM-Frequenz
f_PWM = 20 kHz– deutlich oberhalb des Hörbereichs und für den Timer leicht sauber zu erzeugen.Filterwerte
R = 1.6 kΩ,C = 1 µF– ergebenf_c = 1 / (2π × 1.6 kΩ × 1 µF) ≈ 100 Hz.
Die 200-fache Unterdrückung beim Träger reduziert den vollen Hub der PWM auf etwa Vcc / 200 Restwelligkeit an V_out – rund 16 mV bei 3,3 V.
Zwei praktische Hinweise:
Die Ausgangsimpedanz des Filters entspricht in etwa
R. Jede nachgeschaltete Last, die Strom zieht, macht ausRund der Last einen Teiler, derV_outunter den idealen Mittelwert zieht – genau wie der Teiler auf der Seite Analoge Werte mit dem ADC einlesen. Speisen Sie einen ADC-Pin oder einen hochohmigen Puffer, nicht eine Last, die Milliampere aufnimmt.Der Kondensator braucht etwa
5 × R × C ≈ 8 ms, um sich einzuschwingen, wenn sich das Tastverhältnis ändert;V_outhinkt der Tastverhältniseinstellung um diese Zeit hinterher. Für einen Sollwert, der schneller aktualisiert werden muss, erhöhen Sie die Grenzfrequenz (kleineresRoderC) und nehmen Sie mehr Welligkeit in Kauf.