回答:
私はようやくbcm2835.hドライバーヘッダーファイルから完全に理解できるようになったので、他の人のために自分の質問を投稿して答えようと思いました。
ヘッダーからの関連ビット:
PWM
BCM2835は、GPIOピンの限られたサブセットでハードウェアPWMをサポートします。このbcm2835ライブラリは、これらのピンのPWM出力を構成および制御するための関数を提供します。
BCM2835には2つの独立したPWMチャネル(0と1)が含まれており、それぞれがGPIOピンの限られたサブセットに接続されています。次のGPIOピンは、次の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
GPIOピンがPWMチャネルから出力を放出するには、上記のAlt関数に設定する必要があります。Raspberry Piの現在のバージョンでは、IOヘッダーでこれらのピンの1つ(GPIO 18 = RPiピン1〜12)しか公開されていないため、これがPWMに使用できるRPiの唯一のIOピンであることに注意してください。さらに、PWM出力を取得するには、ALT FUN 5に設定する必要があります。
両方のPWMチャネルは同じPWMクロックで駆動され、そのクロック分周器はを使用して変更できます
bcm2835_pwm_set_clock()
。を使用して、各チャネルを個別に有効にすることができますbcm2835_pwm_set_mode()
。PWMチャネルの平均出力は、そのチャネルのDATA / RANGEの比率によって決まります。bcm2835_pwm_set_range()
範囲bcm2835_pwm_set_data()
を設定し、その比率でデータを設定するために使用し ます各PWMチャネルは、平衡モードまたはマークスペースモードで実行できます。平衡モードでは、ハードウェアはRANGEパルスごとに全体的なDATAパルスになるクロックパルスの組み合わせを送信します。Mark-Spaceモードでは、ハードウェアは、DATAクロックパルスの出力をHIGHに設定し、RANGE-DATAクロックパルスの出力をLOWに設定します。
PWMクロックは、PWMパルス幅を制御するように設定できます。PWMクロックは19.2MHzクロックから生成されます。任意の分周器を設定できますが、いくつかの一般的な分周器は
bcm2835PWMClockDivider
たとえば、DCモーターを約1kHzのPWMで駆動し、速度を0/1024(停止)から1024/1024(フルオン)まで1/1024刻みで制御するとします。その場合、クロック分周器を16に設定し、RANGEを1024に設定します。パルス繰り返し周波数は1.2MHz / 1024 = 1171.875Hzになります。
bcm2835PWMClockDivider
システムクロックからPWMクロックを生成するために使用される分周器を指定します。以下の図は、分周器、クロック周期、およびクロック周波数を示しています。分周されたクロックは、19.2MHzの公称PWMベースクロックレートに基づいています。各分周器に示された周波数は測定によって確認されています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;
要約すれば:
ハードウェアPWMが必要な場合-ピン12(BCM18)で立ち往生している場合、他のGPIOピンはソフトウェアPWMを使用します。
上記のように、ほとんどのユースケースと健全性の理由から、おそらくPWMモードを「Mark-Space」モードに設定する必要があります。
このモードでは、各「パルス」がHIGH対LOWである期間は、PWMデータのPWM範囲に対する比率によって決定されます。これは、PWMクロック速度に関係ありません。
PWM範囲は、事実上、各パルスの「分解能」または考えられる「分割」の数です。分割数が多いほど解像度が高くなり、特定のパルス幅でエンコード可能な状態が多くなります。
「デューティサイクル」は、PWMデータのPWM範囲に対する比率で、パーセンテージで表されます。PWMデータが8で10のPWM範囲は、80%のデューティサイクルです。
PWMクロック速度は、2の除数の累乗です。したがって、PWMに選択したクロック速度はdivisor & (divisor -1) == 0
、12個の有効な値が上記にリストされていますが、
PWMクロック周波数を目的の出力周波数で除算すると、パルス範囲の値が得られます。
オーディオをエンコードし、ピエゾサウンダを使用していたため、ピエゾ振動を最大化してボリュームを最大化するには、50%のデューティサイクルが必要でした。したがって、PWMデータ値は常にPWM範囲値の半分-50%HIGH 50%LOWです。
必要な周波数を計算するには、アプリケーションに適したクロック除数を選択します。私は16を選択しました。これは1.2Mhzに相当します。そう:
Aのノートは440Hz、F#は370Hz、C#は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;
PWM範囲は、オクターブ単位で簡単に上下にシフトできます。範囲* 2で1オクターブ下がり、範囲* 0.5で1オクターブ下がります。
たとえば50Hzでサーボを駆動したい場合、同じ範囲の計算が当てはまります。
PWM Range = PWM frequency / Desired Output Frequency
(いくつかの投稿によると、最大PWM範囲の値は4096です。私の経験では、C#を上記のように再生すると、PWM範囲4332が期待どおりに機能するため、これは当てはまりません。)
ほとんどの場合と同様に、方法を知っていれば簡単です。
〜N
最近のPi(40ピン拡張ヘッダーと計算モジュールを備えたもの)では、GPIO 12/13/18/19を使用してハードウェアPWM信号を提供できます。
PWMクロックソースは19.2MHzクリスタルである必要はありません。pigpioは500MHz PLLDを使用します。
ハードウェアPWM周波数を設定する簡単なコマンドライン方法については、http://abyz.me.uk/rpi/pigpio/pigs.html#HPを参照してください