Controlla la frequenza PWM dell'hardware


21

Sto usando l'uscita PWM hardware con cablaggio. Fornisce la funzione pwmSetClock che dovrebbe consentire di modificare la frequenza. ( https://projects.drogon.net/raspberry-pi/wiringpi/functions/ ). Credo che dato che l'impostazione predefinita è 200 Mhz impostando il divisore su 200000000, un LED collegato all'uscita lampeggi visibilmente, ma non è così.

Questo può essere cambiato?


1
Sto facendo dei test con l'hardware PWM e non sembra avere una frequenza fiexd. Variava in base all'ampiezza dell'impulso impostata pwmWrite(). Non qualcosa che mi aspetterei che accada
TheMeaningfulEngineer,

Risposte:


25

Di recente ho avuto qualche motivo per iniziare a sperimentare PWM da solo, e ho scoperto che (come sottolineato da uno dei commenti) la frequenza sembra variare con il ciclo di lavoro - bizzare, giusto? Si scopre che Broadcom ha implementato PWM "bilanciato" al fine di rendere gli impulsi PWM on e off il più uniformemente distribuiti possibile. Forniscono una descrizione dell'algoritmo e qualche altra discussione a pagina 139 del loro foglio dati: http://www.element14.com/community/servlet/JiveServlet/downloadBody/43016-102-1-231518/Broadcom.Datasheet.pdf

Quindi quello che vuoi davvero è mettere PWM in modalità mark-space, che ti darà il PWM tradizionale (e facilmente prevedibile) che stai cercando:

pwmSetMode(PWM_MODE_MS);

Il resto della risposta presuppone che siamo in modalità mark-space.

Ho anche fatto qualche esperimento con l'intervallo di valori consentito per pwmSetClock()e pwmSetRange(). Come notato in una delle altre risposte, l'intervallo valido per pwmSetClock()sembra andare da 2 a 4095, mentre l'intervallo valido per pwmSetRange()è fino a 4096 (non ho tentato di trovare un limite inferiore).

Il range e il clock (un nome migliore è probabilmente divisore) influenzano entrambi la frequenza. L'intervallo influisce anche sulla risoluzione, quindi sebbene sia possibile utilizzare valori molto bassi, esiste un limite pratico a quanto probabilmente vorrai andare basso. Ad esempio, se si utilizza un intervallo di 4, è possibile ottenere frequenze più elevate, ma sarà possibile impostare il duty cycle solo su 0/4, 1/4, 2/4, 3/4 o 4/4.

L'orologio PWM Raspberry Pi ha una frequenza di base di 19,2 MHz. Questa frequenza, divisa per l'argomento a pwmSetClock(), è la frequenza alla quale viene incrementato il contatore PWM. Quando il contatore raggiunge un valore uguale all'intervallo specificato, si azzera. Mentre il contatore è inferiore al ciclo di lavoro specificato, l'uscita è alta, altrimenti l'uscita è bassa.

Ciò significa che se si desidera impostare PWM su una frequenza specifica, è possibile utilizzare la relazione seguente:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange.

Se si utilizzano i valori massimi consentiti per pwmSetClock()e pwmSetRange(), si otterrà la frequenza PWM hardware minima raggiungibile di ~ 1,14 Hz. Questo darà sicuramente uno sfarfallio visibile (più di un flash, davvero) a un LED. Ho confermato l'equazione di cui sopra con un oscilloscopio e sembra reggere. Il limite di frequenza superiore sarà influenzato dalla risoluzione necessaria, come descritto sopra.


Per quanto riguarda il limite inferiore di pwmRange: l'ho impostato con successo su 2 (per ottenere un duty cycle del 50%).
Ted Pudlik,

da quale fonte sai che l'orologio pwm ha una frequenza di 19.2 mhz?
giovedì

10

Secondo questa formula:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange

Possiamo impostare pwmClock=1920e pwmRange=200ottenere pwmFrequency=50Hz:

50 Hz = 19.2e6 Hz / 1920 / 200

Lo collaudo su alarmpi:

$ pacman -S wiringpi
$ gpio mode 1 pwm
$ gpio pwm-ms
$ gpio pwmc 1920
$ gpio pwmr 200     # 0.1 ms per unit
$ gpio pwm 1 15     # 1.5 ms (0º)
$ gpio pwm 1 20     # 2.0 ms (+90º)
$ gpio pwm 1 10     # 1.0 ms (-90º)

Nota: il mio servo prevede un segnale a 50Hz .


come si arriva a: 'gpio pwmr 200 # 0.1 ms per unità'
mxlian,

50Hz ---> 20ms per ciclo. 20ms / 200 unità = 0.1ms per unità
mxlian il

5

Questo è il codice che sto usando. Sto cercando di vedere cosa cambierà mentre cambio le impostazioni.

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main (void)
{
  printf ("Raspberry Pi wiringPi test program\n") ;

  if (wiringPiSetupGpio() == -1)
    exit (1) ;

  pinMode(18,PWM_OUTPUT);
  pwmSetClock(2);
  pwmSetRange (10) ;
  pwmWrite (18, 5);

for (;;) delay (1000) ;
}

pwmSetClock (1); -> 2.342kHz

pwmSetClock (2); -> 4,81 MHz

pwmSetClock (3); -> 3,19 MHz

pwmSetClock (4); -> 2.398 MHz

pwmSetClock (5); -> 1.919MHz

pwmSetClock (6); -> 1,6 MHz

pwmSetClock (7); -> 1,3 MHz

pwmSetClock (8); -> 1,2 MHz

pwmSetClock (9); -> 1,067 MHz

pwmSetClock (10); -> 959kHz

pwmSetClock (11); -> 871kHz

pwmSetClock (20); -> 480kHz

pwmSetClock (200); -> 48kHz

pwmSetClock (500); -> 19kHz

pwmSetClock (1000); -> 9,59 kHz

pwmSetClock (2000); -> 4.802kHz

pwmSetClock (4000); -> 2.401 kHz

pwmSetClock (5000); -> 10,58 kHz

Da quello che ho testato, sembra che il divisore vada da 2 a un numero inferiore a 5000. Immagino che abbia qualcosa a che fare con la rappresentazione binaria di quei numeri che vengono impostati direttamente nel registro. Una volta che la rappresentazione binaria dei numeri ha più bit di quanti il ​​registro possa prendere, prende solo i primi bit e interpreta i numeri in quel modo. Ecco perché lo strano comportamento arriva quando va da 4000 a 5000.


1
Come cambierei il ciclo di lavoro?
noufal,

Come hai misurato le frequenze?
Seanny123,
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.