PWM-Ausgangsfrequenz ansteuern

8

Nach vielen Stunden erfolglosen Suchens und Lesens hatte ich immer noch kein vollständiges Verständnis dafür, wie und warum bestimmte Frequenzen vom Hardware-PWM-Pin des RPi ausgegeben werden sollten, ohne die "Blackbox" eines anderen zu verwenden.

Es scheint ziemlich viele ungenaue oder unvollständige Informationen zu den Einzelheiten sowie zu den verschiedenen verwendeten Begriffen zu geben - "Taktteiler", "Arbeitszyklus", "PWM-Bereich" und den PWM-Daten selbst und wie sie sich alle beziehen zusammen, um eine bestimmte Frequenz auszugeben - in meinem Fall, um bestimmte Audiofrequenzen aus einem Piezo-Echolot herauszutreiben.

Neil
quelle

Antworten:

14

Ich habe endlich ein vollständiges (ish) Verständnis von der bcm2835.h-Treiber-Header-Datei erhalten, also dachte ich, ich würde meine eigene Frage für andere posten und beantworten.

Die relevanten Bits aus dem Header:

PWM

Der BCM2835 unterstützt Hardware-PWM auf einer begrenzten Teilmenge von GPIO-Pins. Diese bcm2835-Bibliothek bietet Funktionen zum Konfigurieren und Steuern der PWM-Ausgabe an diesen Pins.

Der BCM2835 enthält 2 unabhängige PWM-Kanäle (0 und 1), von denen jeder mit einer begrenzten Teilmenge von GPIO-Pins verbunden ist. Die folgenden GPIO-Pins können mit den folgenden PWM-Kanälen verbunden werden:

  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

Damit ein GPIO-Pin einen Ausgang von seinem PWM-Kanal ausgeben kann, muss er auf die oben angegebene Alt-Funktion eingestellt sein. Beachten Sie sorgfältig, dass aktuelle Versionen des Raspberry Pi nur einen dieser Pins (GPIO 18 = RPi-Pin 1-12) in den E / A-Headern freigeben. Daher ist dies der einzige E / A-Pin im RPi, der für PWM verwendet werden kann. Außerdem muss ALT FUN 5 eingestellt sein, um die PWM-Ausgabe zu erhalten.

Beide PWM-Kanäle werden von demselben PWM-Takt angesteuert, dessen Taktgeber mit variiert werden kann bcm2835_pwm_set_clock(). Jeder Kanal kann separat mit aktiviert werden bcm2835_pwm_set_mode(). Die durchschnittliche Ausgabe des PWM-Kanals wird durch das Verhältnis von DATA / RANGE für diesen Kanal bestimmt. Verwenden Sie bcm2835_pwm_set_range()diese Option , um den Bereich und bcm2835_pwm_set_data()die Daten in diesem Verhältnis festzulegen

Jeder PWM-Kanal kann entweder im Balanced- oder im Mark-Space-Modus ausgeführt werden. Im symmetrischen Modus sendet die Hardware eine Kombination von Taktimpulsen, die insgesamt DATA-Impulse pro RANGE-Impulse ergibt. Im Mark-Space-Modus setzt die Hardware den Ausgang für DATA-Taktimpulse auf HIGH, gefolgt von LOW für RANGE-DATA-Taktimpulse.

Der PWM-Takt kann eingestellt werden, um die PWM-Impulsbreiten zu steuern. Der PWM-Takt wird von einem 19,2-MHz-Takt abgeleitet. Sie können jeden Teiler einstellen, aber einige gebräuchliche werden von der bereitgestelltbcm2835PWMClockDivider

Angenommen, Sie möchten einen Gleichstrommotor mit PWM bei etwa 1 kHz betreiben und die Drehzahl in Schritten von 1/1024 von 0/1024 (gestoppt) bis 1024/1024 (voll eingeschaltet) steuern. In diesem Fall können Sie den Taktteiler auf 16 und den BEREICH auf 1024 einstellen. Die Impulswiederholungsfrequenz beträgt 1,2 MHz / 1024 = 1171,875 Hz.

bcm2835PWMClockDividerGibt den Teiler an, der zum Generieren des PWM-Takts aus dem Systemtakt verwendet wird. Die folgenden Abbildungen geben den Teiler, die Taktperiode und die Taktfrequenz an. Die geteilte Taktung basiert auf der nominalen PWM-Basistaktrate von 19,2 MHz. Die für jeden Teiler angezeigten Frequenzen wurden durch Messung bestätigt

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;

Zusammenfassend:

  1. Wenn Sie Hardware-PWM möchten - Sie stecken mit Pin 12 (BCM18) fest, verwenden andere GPIO-Pins Software-PWM.

  2. Wahrscheinlich müssen Sie den PWM-Modus für die meisten Anwendungsfälle und aus Gründen der Vernunft wie oben beschrieben auf "Mark-Space" -Modus einstellen.

  3. In diesem Modus wird die Dauer, in der jeder 'Impuls' HOCH gegen NIEDRIG ist, durch das Verhältnis der PWM-Daten zum PWM-Bereich bestimmt - dies ist unabhängig von der PWM-Taktrate.

  4. Der PWM-Bereich ist effektiv die "Auflösung" oder Anzahl möglicher "Teilungen" jedes Impulses. Je mehr Teilungen vorhanden sind, desto höher ist die Auflösung und desto mehr Zustände können für eine bestimmte Impulsbreite codiert werden.

  5. Das "Tastverhältnis" ist das Verhältnis von PWM-Daten zu PWM-Bereich, ausgedrückt als Prozentsatz. Ein PWM-Bereich von 10 mit PWM-Daten von 8 ist ein Arbeitszyklus von 80%.

  6. Die PWM-Taktrate ist eine Potenz von zwei Teilern. Ihre gewählte Taktrate für PWM muss also sein, divisor & (divisor -1) == 0obwohl die 12 gültigen Werte oben aufgeführt sind.

  7. Das Teilen der PWM-Taktfrequenz durch die gewünschte Ausgangsfrequenz ergibt den Impulsbereichswert.

  8. Da ich Audio codierte und einen Piezo-Echolot verwendete, benötigte ich ein Tastverhältnis von 50%, um die Piezo-Schwingung und damit die Lautstärke zu maximieren. Der PWM-Datenwert ist daher immer die Hälfte des PWM-Bereichswerts - 50% HIGH 50% LOW.

Um Ihre erforderliche Frequenz zu berechnen, wählen Sie einen Taktteiler, der für Ihre Anwendung sinnvoll ist - ich habe 16 gewählt, was 1,2 MHz entspricht. Damit:

Die Note von A ist 440 Hz, F # ist 370 Hz, C # ist 277 Hz

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;

Sie können den PWM-Bereich ganz einfach um ein Vielfaches nach oben und unten verschieben - Bereich * 2 verringert ihn um eine Oktave, Bereich * 0,5 erhöht ihn um eine Oktave.

Wenn Sie ein Servo mit beispielsweise 50 Hz fahren möchten, gilt dieselbe Bereichsberechnung:

PWM Range = PWM frequency / Desired Output Frequency

(Der maximale PWM-Bereichswert gemäß einigen Beiträgen beträgt anekdotisch 4096 - meiner Erfahrung nach trifft dies nicht zu, da das Spielen eines C # wie oben einen PWM-Bereich von 4332 ergibt, der wie erwartet funktioniert.)

Wie die meisten Dinge ist es einfach, wenn Sie wissen wie.

~ N.

Neil
quelle
3
Beachten Sie, dass das Bit "nur Pin 12" für 26-Pin-Modelle gilt. Die 40-Pin-Modelle haben drei weitere (13, 18 und 19), aber es gibt immer noch nur 2 Taktkanäle und die Pins sind fest mit dem einen oder anderen verbunden (Pin 12 und 18 sind Kanal 0, 13 und 19 sind Kanal) 1); Gemäß den oben angegebenen Dokumenten können Sie mit libbcm2835 beide Kanäle und alle vier Pins konfigurieren. Die dazugehörigen ALT-Funktionen unterscheiden sich für jeden Pin. Hier gibt es eine Tabelle, von der ein Großteil direkt aus dem Broadcom SoC-Datenblatt entnommen wurde. Die durchgestrichenen Einträge gelten nur für 40-Pin-Modelle.
Goldlöckchen
7

Bei neueren Pis (mit dem 40-poligen Erweiterungsheader und dem Rechenmodul) kann GPIO 12/13/18/19 verwendet werden, um Hardware-PWM-Signale bereitzustellen.

Die PWM-Taktquelle muss nicht der 19,2-MHz-Kristall sein, Pigpio verwendet die 500-MHz-PLLD.

Eine einfache Befehlszeilenmethode zum Festlegen einer Hardware-PWM-Frequenz finden Sie unter http://abyz.me.uk/rpi/pigpio/pigs.html#HP

joan
quelle