3.13. Analoog genereren met PWM en een RC-filter

De ADC leest spanningen op een pin. Het tegenovergestelde – een tussenliggende spanning produceren tussen 0 V en Vcc op een pin – is moeilijker, omdat een GPIO-uitgang alleen weet hoe hij zijn twee rails moet aansturen. De standaard vervanging is om de pin snel genoeg tussen de rails te schakelen zodat de gemiddelde spanning is waar het je om gaat.

3.13.1. Pulsbreedtemodulatie

Een pulsbreedtegemoduleerd (PWM) signaal is een blokgolf op een vaste frequentie waarvan de hoogtijd – het deel van elke cyclus dat op Vcc wordt doorgebracht in plaats van aarde – in software wordt ingesteld. Dat deel is de duty cycle. De gemiddelde spanning van de golfvorm is de duty cycle maal Vcc:

V_avg = duty × Vcc

Een duty cycle van 25 % middelt naar Vcc / 4; een duty cycle van 50 % naar Vcc / 2; een duty cycle van 75 % naar 3 × Vcc / 4.

Drie blokgolfsporen verticaal gestapeld, elk op dezelfde frequentie. De bovenste golf is hoog gedurende 25 % van elke periode en laag gedurende 75 %. De middelste golf is hoog en laag gedurende elk de helft van de periode. De onderste golf is hoog gedurende 75 % en laag gedurende 25 %.

PWM bij 25 %, 50 % en 75 % duty cycle. De gemiddelde spanning volgt de duty cycle.

De frequentie wordt ingesteld wanneer de PWM wordt geconfigureerd; de duty cycle is wat software ter plekke verandert. De klasse machine.PWM omhult een hardware timer-kanaal dat de golfvorm genereert zonder hulp van de CPU – eenmaal geconfigureerd gaat het signaal door op de gekozen frequentie en duty cycle totdat het wordt gewijzigd.

3.13.2. De klasse machine.PWM

Construeer een PWM-instantie met de pin en een initiële frequentie en duty:

from machine import PWM, Pin

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

Dat start een blokgolf van 20 kHz bij 50 % duty op P7. Twee methoden veranderen de uitgang ter plekke:

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

duty_u16() neemt een unsigned 16-bit geheel getal dat 0 afbeeldt op “altijd laag” en 65535 op “altijd hoog”. freq() stelt de draaggolffrequentie in hertz in.

Notitie

Elk PWM-kanaal op dezelfde hardware timer deelt zijn frequentie. Het aanroepen van freq() op één kanaal verandert elk ander kanaal dat aan die timer is gekoppeld. Gebruik kanalen van verschillende timers wanneer uitgangen op verschillende frequenties moeten draaien.

Roep deinit() aan om het timer-kanaal vrij te geven wanneer de uitgang niet langer nodig is.

3.13.3. Middelen met een RC-laagdoorlaatfilter

Ruwe PWM is geen vloeiende spanning; het is een blokgolf waarvan het gemiddelde is wat we willen. Om dat gemiddelde te extraheren, stuur je de PWM door een laagdoorlaatfilter – dezelfde weerstand-en-condensator-combinatie die wordt gebruikt voor het ontdenderen van schakelaars in Ontdenderen (debouncing).

Een PWM-pin verbindt via een serieweerstand R met een uitgangsknooppunt. Een condensator C van dat knooppunt naar aarde voltooit het laagdoorlaatfilter; de gladgestreken spanning verschijnt op V_out.

PWM door een RC-laagdoorlaatfilter: de condensator middelt de blokgolf tot een gelijkspanning die evenredig is met de duty cycle.

De afsnijfrequentie van het filter – de grens tussen frequenties die het doorlaat en die het blokkeert – wordt bepaald door hetzelfde RC-product dat de tijdconstante gaf voor het ontdendercircuit:

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

Om het filter een schone gelijkspanning te laten extraheren uit een PWM-ingang, moet de afsnijfrequentie veel lager zijn dan de PWM-frequentie zelf. De gelijkstroomcomponent (frequentie 0) gaat ongewijzigd door; de grondharmonische van de PWM (op de PWM-frequentie) wordt verzwakt met ongeveer f_c / f_PWM. Een verhouding van 1 / 200 reduceert de resterende rimpel aan de uitgang tot ongeveer 0.5 % van de ingangsuitslag.

Een redelijk startpunt voor een langzaam veranderend instelpunt:

  • PWM-frequentie f_PWM = 20 kHz – ruim boven audio, en gemakkelijk voor de timer om schoon te genereren.

  • Filterwaarden R = 1.6 , C = 1 µF – wat f_c = 1 / (2π × 1.6 × 1 µF) 100 Hz geeft.

De 200×-onderdrukking bij de draaggolf reduceert de volle uitslag van de PWM tot ongeveer Vcc / 200 resterende rimpel op V_out – ongeveer 16 mV bij 3,3 V.

Twee praktische opmerkingen:

  • De uitgangsimpedantie van het filter is ruwweg R. Elke stroomafwaartse belasting die stroom trekt, maakt van R en de belasting een deler die V_out onder het ideale gemiddelde trekt, precies zoals de deler op de Analoog lezen met de ADC-pagina. Voed een ADC-pin of een hoogohmige buffer, geen belasting die milliampères afvoert.

  • De condensator heeft ongeveer 5 × R × C 8 ms nodig om te stabiliseren wanneer de duty cycle verandert; V_out loopt zoveel achter op de duty-instelling. Voor een instelpunt dat sneller moet updaten, verhoog de afsnijfrequentie (kleinere R of C) en accepteer meer rimpel.