Contrôler la fréquence PWM du matériel

21

J'utilise la sortie PWM matérielle avec le câblagepi. Il fournit la fonction pwmSetClock qui devrait permettre de changer la fréquence. ( https://projects.drogon.net/raspberry-pi/wiringpi/functions/ ). Je crois que puisque la valeur par défaut est de 200 Mhz, le réglage du diviseur sur 200000000 devrait rendre une LED connectée au flash de sortie de manière visible, mais ce n'est pas le cas.

Cela peut-il être changé?

user1217949
la source
1
Je fais des tests avec le matériel PWM, et il ne semble pas avoir de fréquence fiexd. Il variait en fonction de la largeur d'impulsion définie pwmWrite(). Pas quelque chose à quoi je m'attendrais
TheMeaningfulEngineer

Réponses:

25

J'ai récemment eu des raisons de commencer à expérimenter moi-même avec PWM, et j'ai constaté que (comme l'a souligné l'un des commentaires) la fréquence semble varier avec le rapport cyclique - bizzare, non? Il s'avère que Broadcom a implémenté un PWM "équilibré" afin de rendre les impulsions PWM activées et désactivées aussi uniformément réparties que possible. Ils donnent une description de l'algorithme et quelques discussions supplémentaires à la page 139 de leur fiche technique: http://www.element14.com/community/servlet/JiveServlet/downloadBody/43016-102-1-231518/Broadcom.Datasheet.pdf

Donc, ce que vous voulez vraiment, c'est mettre le PWM en mode espace de marque, ce qui vous donnera le PWM traditionnel (et facilement prévisible) que vous recherchez:

pwmSetMode(PWM_MODE_MS);

Le reste de la réponse suppose que nous sommes en mode espace de marque.

J'ai également fait quelques essais avec la plage de valeurs autorisée pour pwmSetClock()et pwmSetRange(). Comme indiqué dans l'une des autres réponses, la plage valide pour pwmSetClock()semble aller de 2 à 4095, tandis que la plage valide pour pwmSetRange()est jusqu'à 4096 (je n'ai pas essayé de trouver une limite inférieure).

La plage et l'horloge (un meilleur nom est probablement un diviseur) affectent toutes deux la fréquence. La plage affecte également la résolution.Par conséquent, bien qu'il soit possible d'utiliser des valeurs très faibles, il existe une limite pratique au niveau auquel vous souhaiterez probablement descendre. Par exemple, si vous avez utilisé une plage de 4, vous pourriez obtenir des fréquences plus élevées, mais vous ne pourrez régler le rapport cyclique que sur 0/4, 1/4, 2/4, 3/4 ou 4/4.

L'horloge PWM du Raspberry Pi a une fréquence de base de 19,2 MHz. Cette fréquence, divisée par l'argument de pwmSetClock(), est la fréquence à laquelle le compteur PWM est incrémenté. Lorsque le compteur atteint une valeur égale à la plage spécifiée, il revient à zéro. Alors que le compteur est inférieur au rapport cyclique spécifié, la sortie est élevée, sinon la sortie est faible.

Cela signifie que si vous souhaitez définir le PWM pour avoir une fréquence spécifique, vous pouvez utiliser la relation suivante:

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

Si vous utilisez les valeurs maximales autorisées pour pwmSetClock()et pwmSetRange(), vous vous retrouverez avec la fréquence PWM matérielle minimale réalisable de ~ 1,14 Hz. Cela donnera certainement un scintillement visible (plus d'un flash, vraiment) à une LED. J'ai confirmé l'équation ci-dessus avec un oscilloscope, et elle semble tenir. La limite de fréquence supérieure sera affectée par la résolution dont vous avez besoin, comme décrit ci-dessus.

Kerry
la source
Concernant la borne inférieure sur pwmRange: je l'ai correctement mise à 2 (pour obtenir un rapport cyclique de 50%).
Ted Pudlik
de quelle source savez-vous que l'horloge pwm a une fréquence de 19,2 mhz?
thi gg
10

Selon cette formule:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange

Nous pouvons définir pwmClock=1920et pwmRange=200obtenir pwmFrequency=50Hz:

50 Hz = 19.2e6 Hz / 1920 / 200

Je le teste sur 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º)

Remarque: Mon servo attend un signal de 50 Hz .

kev
la source
comment en arrivez-vous à: 'gpio pwmr 200 # 0,1 ms par unité'
mxlian
50 Hz ---> 20 ms par cycle. 20 ms / 200 unités =
0,1 ms
5

Ceci est le code que j'utilise. J'essaie de voir ce qui va changer à mesure que je change les paramètres.

#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,342 kHz

pwmSetClock (2); -> 4,81 MHz

pwmSetClock (3); -> 3,19 MHz

pwmSetClock (4); -> 2,398 MHz

pwmSetClock (5); -> 1,919 MHz

pwmSetClock (6); -> 1,6 MHz

pwmSetClock (7); -> 1,3 MHz

pwmSetClock (8); -> 1,2 MHz

pwmSetClock (9); -> 1,067 MHz

pwmSetClock (10); -> 959 kHz

pwmSetClock (11); -> 871 kHz

pwmSetClock (20); -> 480 kHz

pwmSetClock (200); -> 48 kHz

pwmSetClock (500); -> 19 kHz

pwmSetClock (1000); -> 9,59 kHz

pwmSetClock (2000); -> 4,802 kHz

pwmSetClock (4000); -> 2,401 kHz

pwmSetClock (5000); -> 10,58 kHz

D'après ce que j'ai testé, il semble que le diviseur passe de 2 à un nombre inférieur à 5000. Je suppose que cela a quelque chose à voir avec la représentation binaire de ces nombres qui sont directement définis dans le registre. Une fois que la représentation binaire des nombres a plus de bits que le registre ne peut en prendre, elle prend simplement les premiers bits et interprète les nombres de cette façon. C'est pourquoi l'étrange comportement survient lorsque l'on passe de 4000 à 5000.

TheMeaningfulEngineer
la source
1
Comment changer le cycle de service?
noufal
Comment avez-vous mesuré les fréquences?
Seanny123