Control de hardware PWM frecuencia


21

Estoy usando la salida PWM de hardware con cableadopi. Proporciona la función pwmSetClock que debería permitir cambiar la frecuencia. ( https://projects.drogon.net/raspberry-pi/wiringpi/functions/ ). Creo que dado que el valor predeterminado es 200 Mhz, configurar el divisor en 200000000 debería hacer que un LED conectado a la salida parpadee visiblemente, pero ese no es el caso.

¿Se puede cambiar esto?


1
Estoy haciendo algunas pruebas con el hardware PWM, y no parece tener una frecuencia fiexd. Varió según el ancho de pulso establecido pwmWrite(). No es algo que esperaría que suceda
TheMeaningfulEngineer

Respuestas:


25

Recientemente tuve alguna razón para comenzar a experimentar con PWM yo mismo, y descubrí que (como lo señala uno de los comentarios) la frecuencia parece variar con el ciclo de trabajo: bizzare, ¿verdad? Resulta que Broadcom implementó PWM "equilibrado" para hacer que los pulsos PWM de encendido y apagado se distribuyan de la manera más uniforme posible. Dan una descripción del algoritmo y un poco más de discusión en la página 139 de su hoja de datos: http://www.element14.com/community/servlet/JiveServlet/downloadBody/43016-102-1-231518/Broadcom.Datasheet.pdf

Entonces, lo que realmente quiere es poner PWM en modo de espacio de marca, que le dará el PWM tradicional (y fácilmente predecible) que está buscando:

pwmSetMode(PWM_MODE_MS);

El resto de la respuesta supone que estamos en modo de espacio de marca.

También experimenté un poco con el rango permitido de valores para pwmSetClock()y pwmSetRange(). Como se señaló en una de las otras respuestas, el rango válido para pwmSetClock()parece ir de 2 a 4095, mientras que el rango válido pwmSetRange()es de hasta 4096 (no intenté encontrar un límite inferior).

El rango y el reloj (un mejor nombre es probablemente divisor) afectan la frecuencia. El rango también afecta la resolución, por lo que si bien es posible usar valores muy bajos, existe un límite práctico para lo bajo que probablemente querrá ir. Por ejemplo, si usó un rango de 4, podría lograr frecuencias más altas, pero solo podrá establecer el ciclo de trabajo en 0/4, 1/4, 2/4, 3/4 o 4/4.

El reloj Raspberry Pi PWM tiene una frecuencia base de 19.2 MHz. Esta frecuencia, dividida por el argumento de pwmSetClock(), es la frecuencia con la que se incrementa el contador PWM. Cuando el contador alcanza un valor igual al rango especificado, se restablece a cero. Mientras que el contador es menor que el ciclo de trabajo especificado, la salida es alta, de lo contrario la salida es baja.

Esto significa que si desea configurar el PWM para que tenga una frecuencia específica, puede usar la siguiente relación:

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

Si usa los valores máximos permitidos para pwmSetClock()y pwmSetRange(), terminará con la frecuencia PWM de hardware mínima alcanzable de ~ 1.14 Hz. Esto ciertamente dará un parpadeo visible (más de un flash, realmente) a un LED. Confirmé la ecuación anterior con un osciloscopio, y parece sostenerse. El límite superior de frecuencia se verá afectado por la resolución que necesita, como se describió anteriormente.


Con respecto al límite inferior en pwmRange: lo configuré con éxito en 2 (para obtener un ciclo de trabajo del 50%).
Ted Pudlik

¿De qué fuente sabe que el reloj pwm tiene una frecuencia de 19.2 mhz?
Jueves

10

De acuerdo con esta fórmula:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange

Podemos configurar pwmClock=1920y pwmRange=200obtener pwmFrequency=50Hz:

50 Hz = 19.2e6 Hz / 1920 / 200

Lo pruebo en 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: Mi servo espera una señal de 50Hz .


¿cómo se llega a: 'gpio pwmr 200 # 0.1 ms por unidad'
mxlian

50Hz ---> 20ms por ciclo. 20ms / 200 unidades = 0.1ms por unidad
mxlian

5

Este es el código que estoy usando. Estoy tratando de ver qué cambiará a medida que cambie la configuración.

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

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

Por lo que probé, parece que el divisor va de 2 a un número menor que 5000. Supongo que tiene algo que ver con la representación binaria de esos números que se establecen directamente en el registro. Una vez que la representación binaria de los números tiene más bits de los que el registro puede tomar, solo toma los primeros bits e interpreta los números de esa manera. Es por eso que el comportamiento extraño se produce al pasar de 4000 a 5000.


1
¿Cómo cambiaría el ciclo de trabajo?
noufal

¿Cómo midiste las frecuencias?
Seanny123
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.