Conducción de frecuencia de salida PWM

8

Después de muchas horas de búsqueda y lectura infructuosas, todavía no tenía una comprensión completa de cómo y por qué generar frecuencias específicas desde el pin PWM de hardware en el RPi sin usar el 'blackbox' de otra persona.

Parece haber bastante información inexacta o incompleta sobre los detalles, así como los diversos términos utilizados: 'divisor de reloj', 'ciclo de trabajo', 'rango PWM' y los datos PWM en sí, y cómo se relacionan todos juntos para emitir una frecuencia específica, en mi caso para conducir frecuencias de audio específicas de una sonda piezoeléctrica.

Neil
fuente

Respuestas:

14

Finalmente obtuve una comprensión completa (ish) del archivo de encabezado del controlador bcm2835.h, así que pensé en publicar y responder mi propia pregunta para los demás.

Los bits relevantes del encabezado:

PWM

El BCM2835 admite hardware PWM en un subconjunto limitado de pines GPIO. Esta biblioteca bcm2835 proporciona funciones para configurar y controlar la salida PWM en estos pines.

El BCM2835 contiene 2 canales PWM independientes (0 y 1), cada uno de los cuales se conecta a un subconjunto limitado de pines GPIO. Los siguientes pines GPIO se pueden conectar a los siguientes canales 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

Para que un pin GPIO emita una salida de su canal PWM, debe configurarse con la función Alt que se indicó anteriormente. Tenga en cuenta que las versiones actuales de Raspberry Pi solo exponen uno de estos pines (GPIO 18 = RPi Pin 1-12) en los encabezados IO y, por lo tanto, este es el único pin IO en el RPi que se puede usar para PWM. Además, debe establecerse en ALT FUN 5 para obtener la salida PWM.

Ambos canales PWM están controlados por el mismo reloj PWM, cuyo reloj dvider se puede variar usando bcm2835_pwm_set_clock(). Cada canal se puede habilitar por separado con bcm2835_pwm_set_mode(). La salida promedio del canal PWM está determinada por la relación de DATOS / RANGO para ese canal. Use bcm2835_pwm_set_range()para establecer el rango y bcm2835_pwm_set_data()para establecer los datos en esa proporción

Cada canal PWM puede ejecutarse en modo equilibrado o de marca-espacio. En modo equilibrado, el hardware envía una combinación de pulsos de reloj que da como resultado pulsos de DATOS generales por pulsos de RANGO. En el modo Mark-Space, el hardware establece la salida HIGH para los pulsos de reloj DATA, seguido de LOW para los pulsos de reloj RANGE-DATA.

El reloj PWM se puede configurar para controlar los anchos de pulso PWM. El reloj PWM se deriva de un reloj de 19.2MHz. Puede configurar cualquier divisor, pero algunos son proporcionados porbcm2835PWMClockDivider

Por ejemplo, supongamos que desea conducir un motor de CC con PWM a aproximadamente 1 kHz y controlar la velocidad en incrementos de 1/1024 desde 0/1024 (detenido) hasta 1024/1024 (completamente encendido). En ese caso, puede configurar el divisor del reloj en 16 y el RANGO en 1024. La frecuencia de repetición de pulso será 1.2MHz / 1024 = 1171.875Hz.

bcm2835PWMClockDividerEspecifica el divisor utilizado para generar el reloj PWM a partir del reloj del sistema. Las siguientes figuras muestran el divisor, el período del reloj y la frecuencia del reloj. El reloj dividido se basa en la frecuencia nominal de reloj base PWM de 19.2MHz. Las frecuencias mostradas para cada divisor han sido confirmadas por medición

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;

En resumen:

  1. Si desea hardware PWM, está atrapado con el pin 12 (BCM18), otros pines GPIO utilizarán el software PWM.

  2. Probablemente necesitará configurar el modo PWM en el modo 'Marcar espacio' para la mayoría de los casos de uso y razones de cordura como se describió anteriormente.

  3. En este modo, la duración de que cada "pulso" sea ALTO frente a BAJO está determinada por la relación de los datos PWM con respecto al rango PWM; esto es independientemente de la velocidad del reloj PWM.

  4. El rango PWM es efectivamente la 'resolución' o el número de 'divisiones' posibles de cada pulso. Cuantas más divisiones, mayor será la resolución y, por lo tanto, más estados codificables para un ancho de pulso dado.

  5. El 'ciclo de trabajo' es la relación de datos PWM a rango PWM expresada como un porcentaje. Un rango PWM de 10 con datos PWM de 8 es un ciclo de trabajo del 80%.

  6. La velocidad del reloj PWM es una potencia de dos divisores. Por lo tanto, la velocidad de reloj elegida para PWM debe ser divisor & (divisor -1) == 0Aunque los 12 valores válidos se enumeran arriba.

  7. Al dividir la frecuencia del reloj PWM por la frecuencia de salida deseada se obtiene el valor del rango del pulso.

  8. Cuando estaba codificando audio y usando una sonda piezoeléctrica, necesitaba un ciclo de trabajo del 50% para maximizar la oscilación piezoeléctrica y, por lo tanto, el volumen. El valor de los datos PWM es, por lo tanto, siempre la mitad del valor del rango PWM: 50% ALTO 50% BAJO.

Para calcular su frecuencia requerida, elija un divisor de reloj que tenga sentido para su aplicación: elegí 16, que equivale a 1.2Mhz. Entonces:

La nota de A es 440Hz, F # es 370Hz, C # es 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;

Puede cambiar fácilmente el rango PWM hacia arriba y hacia abajo octavas en múltiplos: el rango * 2 lo bajará una octava, el rango * 0.5 lo tomará uno.

Si desea conducir un servo a unos 50 Hz, el mismo cálculo de rango es válido:

PWM Range = PWM frequency / Desired Output Frequency

(El valor máximo del rango de PWM según algunas publicaciones anecdóticamente es 4096; en mi experiencia, esto no es cierto ya que jugar un C # como se muestra arriba da un rango de PWM de 4332 que funciona como se esperaba).

Como la mayoría de las cosas, es fácil cuando sabes cómo.

~ N

Neil
fuente
3
Tenga en cuenta que el bit "solo pin 12" se aplica a los modelos de 26 pines. Los modelos de 40 pines tienen tres más (13, 18 y 19), pero todavía hay solo 2 canales de reloj y los pines tienen una asociación cableada con uno u otro (los pines 12 y 18 son canales 0, 13 y 19 son canales 1); según los documentos citados anteriormente, libbcm2835 le permitirá configurar ambos canales y los cuatro pines. Las funciones ALT para hacerlo difieren para cada pin; Aquí hay una tabla, gran parte de la cual se extrae directamente de la hoja de datos de Broadcom SoC. Las entradas tachadas son solo en modelos de 40 pines.
Ricitos de oro
7

En Pis reciente (aquellos con el encabezado de expansión de 40 pines y el módulo de cómputo) GPIO 12/13/18/19 se puede usar para proporcionar señales PWM de hardware.

La fuente del reloj PWM no necesita ser el cristal de 19.2MHz , pigpio usa el PLLD de 500MHz.

Para obtener un método simple de línea de comandos para configurar una frecuencia PWM de hardware, consulte http://abyz.me.uk/rpi/pigpio/pigs.html#HP

joan
fuente