Guidare la frequenza di uscita PWM


8

Dopo molte ore di ricerche e letture infruttuose, non avevo ancora una completa comprensione di come e perché emettere frequenze specifiche dal pin PWM hardware su RPi senza usare la 'blackbox' di qualcun altro.

Sembra che ci siano un bel po 'di informazioni inesatte o incomplete sui dettagli, così come i vari termini usati - "orologio divisore", "duty cycle", "PWM range" e i dati PWM stessi, e come si relazionano tutti insieme per emettere una frequenza specifica - nel mio caso per scacciare frequenze audio specifiche da un ecoscandaglio piezoelettrico.

Risposte:


14

Finalmente ho ottenuto una comprensione completa (ish) dal file di intestazione del driver bcm2835.h, quindi ho pensato di pubblicare e rispondere alla mia domanda per gli altri.

I bit rilevanti dell'intestazione:

PWM

BCM2835 supporta PWM hardware su un sottoinsieme limitato di pin GPIO. Questa libreria bcm2835 fornisce funzioni per la configurazione e il controllo dell'uscita PWM su questi pin.

Il BCM2835 contiene 2 canali PWM indipendenti (0 e 1), ognuno dei quali è collegato a un sottoinsieme limitato di pin GPIO. I seguenti pin GPIO possono essere collegati ai seguenti canali PWM:

  GPIO PIN    RPi pin  PWM Channel    ALT FUN
  12                    0             0
  13                    1             0
  18          1-12      0             5
  19                    1             5
  40                    0             0
  41                    1             0
  45                    1             0
  52                    0             1
  53                    1             1

Affinché un pin GPIO emetta output dal suo canale PWM, deve essere impostato sulla funzione Alt indicata sopra. Nota attentamente che le versioni attuali di Raspberry Pi espongono solo uno di questi pin (GPIO 18 = RPi Pin 1-12) sulle intestazioni IO, e quindi questo è l'unico pin IO sull'RPi che può essere usato per PWM. Inoltre, deve essere impostato su ALT FUN 5 per ottenere l'uscita PWM.

Entrambi i canali PWM sono gestiti dallo stesso clock PWM, il cui clock dvider può essere variato usando bcm2835_pwm_set_clock(). Ogni canale può essere abilitato separatamente con bcm2835_pwm_set_mode(). L'uscita media del canale PWM è determinata dal rapporto DATA / RANGE per quel canale. Utilizzare bcm2835_pwm_set_range()per impostare l'intervallo e bcm2835_pwm_set_data()per impostare i dati in quel rapporto

Ogni canale PWM può funzionare in modalità Bilanciata o Mark-Space. In modalità Bilanciata, l'hardware invia una combinazione di impulsi di clock che si traduce in un totale di impulsi DATA per impulsi RANGE. In modalità Mark-Space, l'hardware imposta l'uscita HIGH per gli impulsi di clock DATA, seguito da LOW per gli impulsi di clock RANGE-DATA.

L'orologio PWM può essere impostato per controllare la larghezza degli impulsi PWM. Il clock PWM è derivato da un clock a 19.2MHz. È possibile impostare qualsiasi divisore, ma alcuni comuni sono forniti dabcm2835PWMClockDivider

Ad esempio, supponiamo che tu voglia guidare un motore DC con PWM a circa 1kHz e controllare la velocità con incrementi di 1/1024 da 0/1024 (fermo) a 1024/1024 (pieno acceso). In tal caso, è possibile impostare il divisore di clock su 16 e RANGE su 1024. La frequenza di ripetizione dell'impulso sarà 1,2 MHz / 1024 = 1171,875 Hz.

bcm2835PWMClockDividerSpecifica il divisore utilizzato per generare l'orologio PWM dall'orologio di sistema. Le figure seguenti mostrano il divisore, il periodo e la frequenza di clock. Il clock diviso si basa su una frequenza di clock di base PWM nominale di 19,2 MHz. Le frequenze mostrate per ciascun divisore sono state confermate dalla misurazione

typedef enum
{
    BCM2835_PWM_CLOCK_DIVIDER_2048  = 2048,    /*!< 2048 = 9.375kHz */
    BCM2835_PWM_CLOCK_DIVIDER_1024  = 1024,    /*!< 1024 = 18.75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_512   = 512,     /*!< 512 = 37.5kHz */
    BCM2835_PWM_CLOCK_DIVIDER_256   = 256,     /*!< 256 = 75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_128   = 128,     /*!< 128 = 150kHz */
    BCM2835_PWM_CLOCK_DIVIDER_64    = 64,      /*!< 64 = 300kHz */
    BCM2835_PWM_CLOCK_DIVIDER_32    = 32,      /*!< 32 = 600.0kHz */
    BCM2835_PWM_CLOCK_DIVIDER_16    = 16,      /*!< 16 = 1.2MHz */
    BCM2835_PWM_CLOCK_DIVIDER_8     = 8,       /*!< 8 = 2.4MHz */
    BCM2835_PWM_CLOCK_DIVIDER_4     = 4,       /*!< 4 = 4.8MHz */
    BCM2835_PWM_CLOCK_DIVIDER_2     = 2,       /*!< 2 = 9.6MHz, fastest you can get */
    BCM2835_PWM_CLOCK_DIVIDER_1     = 1        /*!< 1 = 4.6875kHz, same as divider 4096 */
} bcm2835PWMClockDivider;

In sintesi:

  1. Se vuoi PWM hardware - sei bloccato con il pin 12 (BCM18), altri pin GPIO useranno il software PWM.

  2. Probabilmente dovrai impostare la modalità PWM sulla modalità "Mark-Space" per la maggior parte dei casi d'uso e ragioni di sanità mentale come descritto sopra.

  3. In questa modalità, la durata in cui ciascun 'impulso' è ALTO rispetto a BASSO è determinata dal rapporto tra i dati PWM e l'intervallo PWM, indipendentemente dalla velocità di clock PWM.

  4. La gamma PWM è effettivamente la "risoluzione" o il numero di possibili "divisioni" di ciascun impulso. Più divisioni maggiore è la risoluzione e quindi più stati codificabili per una data larghezza di impulso.

  5. Il 'duty cycle' è il rapporto tra i dati PWM e l'intervallo PWM espresso in percentuale. Una gamma PWM di 10 con dati PWM di 8 è un duty cycle dell'80%.

  6. La velocità di clock PWM è una potenza di due divisori. Quindi la velocità di clock selezionata per PWM deve essere divisor & (divisor -1) == 0Sebbene i 12 valori validi siano elencati sopra.

  7. Dividendo la frequenza di clock PWM per la frequenza di uscita desiderata si ottiene il valore della gamma di impulsi.

  8. Mentre stavo codificando l'audio e usando un ecoscandaglio piezoelettrico, avevo bisogno di un ciclo di lavoro del 50% per massimizzare l'oscillazione piezoelettrica e quindi il volume. Il valore dei dati PWM è quindi sempre la metà del valore dell'intervallo PWM - 50% ALTO 50% BASSO.

Per calcolare la frequenza richiesta, scegli un divisore di clock che abbia senso per la tua applicazione: ho scelto 16, che equivale a 1,2 Mhz. Così:

La nota di A è 440Hz, F # è 370Hz, C # è 277Hz

PWMClock = 16; // 1.2Mhz

const A4_RANGE = 1.2e6 / 440;  // 1.2Mhz/440Hz
A4Data = A4_RANGE / 2;

const F4S_RANGE = 1.2e6 / 370;  // 1.2Mhz/370Hz
F4SData = F4S_RANGE / 2;

const C4S_RANGE = 1.2e6 / 277;  // 1.2Mhz/277Hz
C4SData = C4S_RANGE / 2;

Puoi facilmente spostare l'intervallo PWM su e giù per le ottave in multipli - l'intervallo * 2 lo porterà giù di un'ottava, l'intervallo * 0,5 lo porterà su di uno.

Se si desidera guidare un servo a 50Hz, lo stesso calcolo della portata è valido:

PWM Range = PWM frequency / Desired Output Frequency

(Il valore massimo dell'intervallo PWM secondo alcuni post aneddoticamente è 4096 - nella mia esperienza questo non è vero nel suonare un C # come sopra dà un intervallo PWM di 4332 che funziona come previsto.)

Come la maggior parte delle cose - è facile quando sai come.

~ N


3
Si noti che il bit "solo pin 12" si applica ai modelli a 26 pin. I modelli a 40 pin ne hanno altri tre (13, 18 e 19), ma ci sono ancora solo 2 canali di clock e i pin hanno un'associazione cablata con l'uno o l'altro (i pin 12 e 18 sono il canale 0, 13 e 19 sono il canale 1); secondo i documenti sopra citati libbcm2835 ti permetterà di configurare entrambi i canali e tutti e quattro i pin. Le funzioni ALT per farlo differiscono per ciascun pin; c'è una tabella qui, gran parte della quale viene sollevata direttamente dalla scheda tecnica SoC Broadcom. Le voci barrate sono solo sui modelli a 40 pin.
Riccioli d'oro

7

Sui Pis recenti (quelli con l'intestazione di espansione a 40 pin e il modulo di calcolo) GPIO 12/13/18/19 può essere utilizzato per fornire segnali PWM hardware.

La sorgente di clock PWM non deve necessariamente essere il cristallo a 19,2 MHz , pigpio utilizza il PLLD a 500 MHz.

Per un semplice metodo da riga di comando per impostare una frequenza PWM hardware, consultare http://abyz.me.uk/rpi/pigpio/pigs.html#HP

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.