Frequência PWM de hardware de controle

21

Eu estou usando a saída PWM de hardware com a fiaçãopi. Ele fornece a função pwmSetClock que deve permitir alterar a frequência. ( https://projects.drogon.net/raspberry-pi/wiringpi/functions/ ). Acredito que, como o padrão é 200 Mhz, a configuração do divisor para 200000000 deve fazer um LED ligado à saída piscar visivelmente, mas esse não é o caso.

Isso pode ser alterado?

user1217949
fonte
1
Estou fazendo alguns testes com o hardware PWM, e ele não parece ter uma frequência fiexd. Variava com base na largura de pulso definida pwmWrite(). Não é algo que eu esperaria acontecer
TheMeaningfulEngineer

Respostas:

25

Recentemente, tive algum motivo para começar a experimentar o PWM e descobri que (como apontado por um dos comentários) a frequência parece variar com o ciclo de trabalho - bizzare, certo? Acontece que a Broadcom implementou PWM "equilibrado" para tornar os pulsos PWM ligados e desligados o mais uniformemente distribuídos possível. Eles fornecem uma descrição do algoritmo e mais algumas discussões na página 139 da folha de dados: http://www.element14.com/community/servlet/JiveServlet/downloadBody/43016-102-1-231518/Broadcom.Datasheet.pdf

Então, o que você realmente deseja é colocar o PWM no modo de espaço de marca, que fornecerá o PWM tradicional (e facilmente previsível) que você está procurando:

pwmSetMode(PWM_MODE_MS);

O restante da resposta assume que estamos no modo de espaço de marca.

Também experimentei a faixa de valores permitida para pwmSetClock()e pwmSetRange(). Conforme observado em uma das outras respostas, o intervalo válido para pwmSetClock()parece variar de 2 a 4095, enquanto o intervalo válido pwmSetRange()é de até 4096 (não tentei encontrar um limite inferior).

O intervalo e o relógio (um nome melhor é provavelmente divisor) afetam a frequência. O intervalo também afeta a resolução; portanto, embora seja possível usar valores muito baixos, há um limite prático para o quão baixo você provavelmente desejará ir. Por exemplo, se você usou um intervalo de 4, poderá obter frequências mais altas, mas só poderá definir o ciclo de trabalho para 0/4, 1/4, 2/4, 2/4, 3/4 ou 4/4.

O relógio Raspberry Pi PWM tem uma frequência base de 19,2 MHz. Essa frequência, dividida pelo argumento to pwmSetClock(), é a frequência na qual o contador PWM é incrementado. Quando o contador atinge um valor igual ao intervalo especificado, ele é redefinido para zero. Enquanto o contador for menor que o ciclo de trabalho especificado, a saída é alta, caso contrário, a saída é baixa.

Isso significa que, se você desejar definir o PWM para ter uma frequência específica, poderá usar o seguinte relacionamento:

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

Se você usar os valores máximos permitidos para pwmSetClock()e pwmSetRange(), terá a frequência PWM mínima possível de hardware de ~ 1,14 Hz. Isso certamente dará uma cintilação visível (mais um flash, na verdade) a um LED. Confirmei a equação acima com um osciloscópio, e parece que isso vale. O limite de frequência superior será afetado pela resolução necessária, conforme descrito acima.

Kerry
fonte
Em relação ao limite inferior no pwmRange: eu o configurei com sucesso para 2 (para obter um ciclo de trabalho de 50%).
Ted Pudlik
de qual fonte você sabe que o relógio pwm tem uma frequência de 19,2 mhz?
thi gg
10

De acordo com esta fórmula:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange

Podemos definir pwmClock=1920e pwmRange=200obter pwmFrequency=50Hz:

50 Hz = 19.2e6 Hz / 1920 / 200

Eu testo em 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: Meu servo espera um sinal de 50Hz .

kev
fonte
como você vem para: 'GPIO pwmr 200 # 0,1 ms por unidade'
mxlian
50Hz ---> 20ms por ciclo. 20ms / 200 unidades = 0,1ms por unidade
mxlian
5

Este é o código que estou usando. Estou tentando ver o que mudará à medida que altero as configurações.

#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.81MHz

pwmSetClock (3); -> 3.19MHz

pwmSetClock (4); -> 2.398MHz

pwmSetClock (5); -> 1.919MHz

pwmSetClock (6); -> 1.6MHz

pwmSetClock (7); -> 1.3MHz

pwmSetClock (8); -> 1,2 MHz

pwmSetClock (9); -> 1.067MHz

pwmSetClock (10); -> 959kHz

pwmSetClock (11); -> 871kHz

pwmSetClock (20); -> 480kHz

pwmSetClock (200); -> 48kHz

pwmSetClock (500); -> 19kHz

pwmSetClock (1000); -> 9,59kHz

pwmSetClock (2000); -> 4.802kHz

pwmSetClock (4000); -> 2.401kHz

pwmSetClock (5000); -> 10,58kHz

Pelo que testei, parece que o divisor passa de 2 para um número menor que 5000. Eu acho que tem algo a ver com a representação binária daqueles números que estão sendo diretamente definidos no registro. Uma vez que a representação binária dos números possui mais bits do que o registro pode suportar, apenas os primeiros bits e os interpretam dessa maneira. É por isso que o comportamento estranho ocorre quando passa de 4000 para 5000.

TheMeaningfulEngineer
fonte
1
Como eu mudaria o ciclo de serviço?
Noufal
Como você mediu as frequências?
Seanny123