1

これは学術的な質問ですが (必ずしもそうするつもりはありません)、どのように機能するのか興味があります。私はユーザーランド ソフトウェア (ハードウェアではなく) ソリューションを考えています。

PWM 信号を生成したい (デジタル GPIO ピンの数が少ないが、1 つ以上の場合としましょう)。私はおそらく、Pthread を作成するプログラムを作成し、sleep()そのスレッドで適切な s などを使用してデューティ サイクルを無限にループして、比率を正しくするでしょう。

これは CPU をひどく壊しませんか? 周波数は 100 Hz 前後になると思います。私は以前にこのようなことをしたことがありませんが、一定のループ、コンテキストの切り替えなどはマルチタスクや CPU の使用には適していないと想像できます。

この場合の CPU の使用とマルチタスクに関するアドバイスはありますか? FWIW シングルコア プロセッサを考えています。答えは、「システムが使用できなくなる」から「関連する数値は、最新のプロセッサに影響を与えるよりも桁違いに小さい」までさまざまです。

最も適切と思われるため、C を想定します。

編集:ハードウェアGPIOピンにアクセスできるマシン上のLinuxまたはその他の汎用POSIXオペレーティングシステムを想定しています。

EDIT:スリープでPWMを実装する方法は明らかだと思いました。疑いを避けるために、次のようなものがあります。

while (TRUE)
{
    // Set all channels high
    for (int c = 0; x < NUM_CHANNELS)
    {
        set_gpio_pin(c, 1);
    }

    // Loop over units within duty cycle
    for (int x = 0; x < DUTY_CYCLE_UNITS; x++)
    {   
        // Set channels low when their number is up
        for (int c = 0; x < NUM_CHANNELS)
        {
            if (x > CHANNELS[c])
            {
                set_gpio_pin(c, 0);
            }
        }

        sleep(DUTY_CYCLE_UNIT);
    }
}
4

7 に答える 7

2

これの最終的な目的を明確に述べているわけではありませんが、この組み込みスレッドと pthreads にタグを付けているので、Linux バリアントが実行されている専用チップがあると仮定します。

この場合、PWM 出力を作成する最善の方法はメイン プログラム ループを使用することをお勧めします。これは、PWM がより大きな制御アプリケーションの一部であると想定しているためです。ほとんどの単純な組み込みアプリケーション (UI なし) は、メイン スレッドで GPIO を定期的に更新する単一のスレッドで実行できます。

例えば:

InitIOs();

while(1)
{
   // Do stuff
   UpdatePWM();
}  

そうは言っても、チップの仕様を確認してください。ほとんどの組み込みデバイスには専用の PWM 出力ピン (GPIO としても機能する) があり、デューティ サイクルを設定し、必要に応じてそのデューティ サイクルを更新することでハードウェアで簡単に構成できます。この場合、ハードウェアが作業を行います。

あなたの状況を少し明確にすることができれば、より詳細な回答を提供できる可能性があります。

于 2012-03-14T12:44:35.567 に答える
2

できればドライバーで。組み込みデバイスに PWM コントローラーがある場合は問題ありません。それ以外の場合は、PWM 間隔の生成と GPIO ピンの駆動専用のハードウェア タイマーを使用します。

これをユーザーレベルで行う必要がある場合、プロセス/スレッドを高い優先度に上げて sleep() 呼び出しを使用すると、多くのジッターと不十分なパルス幅範囲が確実に生成されます。

于 2012-03-14T13:18:58.110 に答える
1

スレッドを使用してRTOSではないOSでスリープすると、非常に正確で一貫性のある結果が得られません。

より良い方法は、タイマー割り込みを使用して、ISRでGPIOを切り替えることです。ハードウェアタイマーでハードウェアPWM出力を使用するのとは異なり、このアプローチでは、単一のタイマーを複数の信号やその他の目的に使用できます。ハードウェアPWMよりも多くのジッターが見られ、実際の周波数範囲とパルス分解能はハードウェアで達成可能なものよりはるかに低くなりますが、少なくともジッターはミリ秒ではなくマイクロ秒のオーダーになります。

于 2012-03-14T16:13:22.253 に答える
1

より良い方法は、おそらくある種の割り込み駆動型アプローチを使用することです。システムにもよると思いますが、IIRC Arduino は PWM に割り込みを使用します。

于 2012-03-14T12:27:30.917 に答える
1

タイマーがある場合は、新しい PWM エッジが必要になるたびに割り込みを開始するように設定できます。いくつかの巧妙なコーディングを使用すると、これらをキューに入れることができるため、割り込みハンドラーは、多くの PWM チャネルのどれが必要であるか、および立ち上がりエッジまたは立ち下がりエッジのどちらが必要かを認識し、次に必要なエッジに合わせてスケジュールを設定できます。

これらのタイマーが十分にある場合は、PWM チャネルごとに 1 つ割り当てることができるので、さらに簡単です。

低レイテンシの割り込み応答を備えた組み込みコントローラーでは、これにより驚くほど良い結果が得られます。

于 2012-03-15T11:07:12.387 に答える
1

100Hz は、ユーザー空間から実行できるようです。典型的な OS タスク スケジューラのタイムスライスも約 10 ミリ秒であるため、CPU はすでにその間隔でマルチタスクを実行しています。プロセスの優先順位を高くして (niceness を低く)、スリープが (あまり) オーバーランしないようにし、実際のウォール タイムを追跡して、ドリフトを回避するためにそのフィードバックに基づいてスリープ値を調整する可能性があります。また、カーネルがハードウェアでこれに使用するタイマーの解像度が十分に高いことを確認する必要があります!

RAM が非常に少なく、頻繁にスワップしている場合、プログラムがディスクにページアウトされるという問題が発生する可能性があります。また、カーネルが他の CPU 集中型処理を実行している場合、これによっても許容できない遅延が発生します。(その他、優先度の低いユーザー空間タスクは問題ありません) 頻度を一定に保つことが重要な場合は、これをカーネルで解決する (またはリアルタイム カーネルを実行する) 方がよいでしょう。

于 2012-03-14T13:18:46.990 に答える
0

割り込みサービスとソフトウェアの相互作用が導入する固有のタイミング ジッターのすべてを使用して、ソフトウェアで PWM を実行する理由を理解できません (たとえば、割り込みが無効になっているときに PWM 割り込みがヒットしたり、プロセッサが長い割り込み不可能な命令を処理したり、別の命令を処理したりします)。サービスルーチンがアクティブです)。最近のほとんどのマイクロコントローラー (ARM-7、ARM Cortex-M、AVR32、MSP など) には、生成するように構成できるタイマー、または PWM ジェネレーター専用のタイマーがあります。これらは複数の安定した PWM 信号を生成し、一度設定すると、実行を継続するためにプロセッサ入力を必要としません。これらの PWM 出力は、アプリケーションの必要に応じて、2 つの信号が重複したりエッジが同時に発生したりしないように構成できます。

OS のスリープ機能に依存して PWM エッジ間の時間を設定している場合、これは遅くなります。スリープ機能は、タスクのアクティブ化間の最小時間を設定し、これらの間の時間は、タスクの切り替え、優先度の高いスレッドの存在、または実行中の他のカーネル機能によって遅延されます。

于 2012-03-14T14:10:43.227 に答える