3.13. Generera analoga signaler med PWM och ett RC-filter

ADC:n läser spänningar på ett stift. Det motsatta – att producera en mellanliggande spänning mellan 0 V och Vcc på ett stift – är svårare, eftersom en GPIO-utgång bara vet hur man driver sina två skenor. Den vanliga ersättningen är att växla stiftet mellan skenorna tillräckligt snabbt för att medelspänningen ska vara det du bryr dig om.

3.13.1. Pulsbreddsmodulering

En pulsbreddsmodulerad (PWM) signal är en fyrkantvåg vid en fast frekvens vars höga tid – den andel av varje cykel som tillbringas vid Vcc i stället för jord – ställs in i mjukvaran. Den andelen är arbetscykeln (duty cycle). Vågformens medelspänning är arbetscykeln gånger Vcc:

V_avg = duty × Vcc

En arbetscykel på 25 % ger i medeltal Vcc / 4; en arbetscykel på 50 % ger Vcc / 2; en arbetscykel på 75 % ger 3 × Vcc / 4.

Tre fyrkantvågskurvor staplade vertikalt, var och en vid samma frekvens. Den översta vågen är hög under 25 % av varje period och låg under 75 %. Den mellersta vågen är hög och låg under halva perioden vardera. Den nedersta vågen är hög under 75 % och låg under 25 %.

PWM vid 25 %, 50 % och 75 % arbetscykel. Medelspänningen följer arbetscykeln.

Frekvensen ställs in när PWM:en konfigureras; arbetscykeln är vad mjukvaran ändrar under drift. Klassen machine.PWM omsluter en hårdvarutimerkanal som genererar vågformen utan CPU-hjälp – när den väl konfigurerats fortsätter signalen vid den valda frekvensen och arbetscykeln tills den ändras.

3.13.2. Klassen machine.PWM

Konstruera en PWM-instans med stiftet och en initial frekvens och arbetscykel:

from machine import PWM, Pin

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

Det startar en fyrkantvåg på 20 kHz vid 50 % arbetscykel på P7. Två metoder ändrar utsignalen under drift:

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

duty_u16() tar ett 16-bitars heltal utan tecken som mappar 0 till ”alltid låg” och 65535 till ”alltid hög”. freq() ställer in bärvågsfrekvensen i hertz.

Anteckning

Varje PWM-kanal på samma hårdvarutimer delar dess frekvens. Att anropa freq() på en kanal ändrar alla andra kanaler som är kopplade till den timern. Använd kanaler på olika timrar när utgångar måste köras vid olika frekvenser.

Anropa deinit() för att frigöra timerkanalen när utsignalen inte längre behövs.

3.13.3. Medelvärdesbildning med ett RC-lågpassfilter

Rå PWM är inte en jämn spänning; det är en fyrkantvåg vars medelvärde är det vi vill ha. För att extrahera det medelvärdet, skicka PWM:en genom ett lågpassfilter – samma kombination av resistor och kondensator som används för avstudsning av strömbrytare i Avstudsning.

Ett PWM-stift ansluter genom en serieresistor R till en utgångsnod. En kondensator C från den noden till jord kompletterar lågpassfiltret; den utjämnade spänningen framträder vid V_out.

PWM genom ett RC-lågpassfilter: kondensatorn medelvärdesbildar fyrkantvågen till en likspänning proportionell mot arbetscykeln.

Filtrets brytfrekvens – gränsen mellan de frekvenser det släpper igenom och de det blockerar – bestäms av samma RC-produkt som gav tidskonstanten för avstudsningskretsen:

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

För att filtret ska kunna extrahera en ren likspänning från en PWM-ingång måste brytfrekvensen vara mycket lägre än själva PWM-frekvensen. Likspänningskomponenten (frekvens 0) passerar oförändrad; PWM:ens grundton (vid PWM-frekvensen) dämpas med ungefär f_c / f_PWM. Ett förhållande på 1 / 200 skär ner det kvarvarande rippelet vid utgången till ungefär 0.5 % av insvängningen.

En rimlig utgångspunkt för ett långsamt föränderligt börvärde:

  • PWM-frekvens f_PWM = 20 kHz – väl över ljudfrekvensområdet och lätt för timern att generera rent.

  • Filtervärden R = 1.6 , C = 1 µF – vilket ger f_c = 1 / (2π × 1.6 × 1 µF) 100 Hz.

200×-dämpningen vid bärvågen reducerar PWM:ens fulla svängning till ungefär Vcc / 200 kvarvarande rippel vid V_out – omkring 16 mV vid 3,3 V.

Två praktiska anmärkningar:

  • Filtrets utgångsimpedans är ungefär R. Varje nedströms last som drar ström gör R och lasten till en delare som drar V_out under det ideala medelvärdet, precis som delaren på sidan Läsa analoga värden med ADC:n. Mata ett ADC-stift eller en högimpediant buffert, inte en last som drar milliampere.

  • Kondensatorn tar ungefär 5 × R × C 8 ms på sig att stabilisera sig när arbetscykeln ändras; V_out ligger efter inställningen av arbetscykeln med så mycket. För ett börvärde som behöver uppdateras snabbare, höj brytfrekvensen (mindre R eller C) och acceptera mer rippel.