2012-03-14 11 views
1

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

私はPWM信号を生成したいと考えています(少数のデジタルGPIOピンを1つ以上とします)。私はおそらく、Pthreadを作成したプログラムを書いて、そのスレッドの適切なsleep()などを使ってデューティサイクルを無限にループさせて、比率を正しく取得します。

これはCPUをひどく壊さないでしょうか?私は周波数が100Hzのマークのまわりのどこかにあると思います。私は前にこのようなことはしていませんが、定数ルーピング、コンテキストスイッチなどがマルチタスキングやCPU使用にはあまり適していないと想像することができます。

この場合のCPUについてのアドバイスと、マルチタスクの使用について教えてください。 FWIW私はシングルコアプロセッサを考えています。私は答えがからあなたのシステムを使用不可能にすることができると感じている'関連する数字は現代のプロセッサに影響を与えるよりも小さい桁である'

Cが最も適切だと思われるのでCとします。

EDIT:ハードウェア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); 
    } 
} 
+0

デューティ・サイクルは、ピンがハイになる時間と信号の周期の比を表し、パーセンテージで示されます。 100Hzは信号周波数であり、10msの周期を有する。 – guga

+1

PWMの特性、特に出力信号の精度と安定性を指定する必要があります。デューティ・サイクルまたはベース周波数のいずれかでPWM信号のジッタを抑えることができますか?ソフトウェアPWMは、多くのタイミングジッタを持っています。 –

+0

趣味目的のためだけに、照明調光器を駆動します。正確さはそれほど重要ではありません。私はジッタが予想されると思います。私が言ったように、学問的な質問ではなく、私は必ず構築するものではありません。 – Joe

答えて

2

可能であれば、ドライバを使用してください。組み込み機器にPWMコントローラがある場合は、それ以外の場合はハードウェアタイマーを使用してPWM間隔を生成し、GPIOピンを駆動してください。

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

+0

それは私が疑ったものです。 – Joe

+0

これらの最新のコントローラーのほとんどは、複数のハードウェアタイマーを搭載しているようですが、割り込み優先順位が高いわけではありません。 linuxについてはわかりませんが、他の組み込みカーネルでは、OSタイマーの設定をハックしてOSタイマーの間隔を100usに減らし、PWMを実行するために割り込みをかけ、10/100割り込みごとにOSスケジューラーのエントリを呼び出します。 –

+1

効率的に書かれた割り込み関数から実行することは、CPU時間にほとんど気づかれません。バッテリーの寿命は別の話です(つまり、スリープモードからの復帰は100x /秒のエネルギーを要します)。タイマー機能に関するデータシートは、多くの人が気づいているより汎用性が高いため、必ずお読みください! – Adriaan

1

より良い方法は、おそらく何らかの種類の割り込み駆動型アプローチを使用することです。私はそれがあなたのシステムに依存すると思うが、IIRC ArduinoはPWMのための割り込みを使用する。

+0

これはユーザー空間で動作しますか? – Joe

+0

'sleep()'はタスクスケジューラを含みます。タスクスケジューラは、プリエンプションやアイドルからの復帰のためにすでにシステムタイマの割り込みを使用しています。 – pmdj

+0

@Joe:これは実装方法によってまったく異なりますが、linuxのユーザ空間割り込み(主にユーザスペースドライバで使用されますが、おそらく他のものにも使用可能です)のサポートがあるようです。 – Leo

2

あなたはこの最終的な目的を明確に述べていませんが、埋め込まれたタグとpthreadsをタグ付けしているので、私はLinuxのバリアントが動作する専用チップを持っていると仮定します。

この場合、PWMがより大きな制御アプリケーションの一部であると仮定しているので、PWM出力を作成する最良の方法は、メインプログラムのループを通ることです。ほとんどのシンプルな組み込みアプリケーション(UIなし)は、メインスレッドのGPIOを定期的に更新して1つのスレッドで実行できます。例えば

InitIOs(); 

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

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

あなたの状況を少し明確にすることができれば、私はあなたにもっと詳細な答えを与える可能性があります。

+0

しかし、 ''してください 'に定義された期間はありません。私はあなたがこのように信頼できるデューティサイクルを作り出す方法を見ていません。 – Joe

+0

あなたの答えをありがとう。私は専用のPWMピンにアクセスすることを前提にしていないので(私は自分自身でPWMドライバコードを書く必要があります)。 – Joe

+0

Joe、 "Do stuff"は任意の時間がかかりますが、それは "Do stuff"の複雑さによります。一般的に言えば、現代のチップは、ほとんどのデューティサイクルがKHzの範囲にあると仮定すると、デューティサイクルよりもはるかに高速ですが、チップは数MHzで動作する可能性があります。つまり、デューティサイクル(デューティサイクルがアナログ信号を大まかにシミュレートしていると、デューティサイクルが完全である必要はない)が懸念される場合、ハードウェアタイマー割り込みを設定して、あらかじめ決められたTickに達するたびに "UpdatePWM()"を呼び出すことができますカウント。これはタイマーを縛る必要があります。 – sberube

1

100Hzと思われるユーザー空間と思われます。典型的なOSタスクスケジューラのタイムスライスも約10msであるため、CPUはすでにその間隔でマルチタスキングされています。あなたはおそらく、睡眠がオーバーランしないように(高い)、高いプロセス優先度(低ニッセン)を使用し、実際の壁の時間を追跡し、ドリフトを避けるためにそのフィードバックに基づいて潜在的に睡眠の値を調整します。また、カーネルがハードウェア上で使用するタイマーが十分に高い解像度を持っていることを確認する必要があります。

RAMが非常に少なく、スワッピングが大量であると、プログラムがディスクにページアウトされる問題が発生する可能性があります。また、カーネルが他のCPU集約的な処理を行っている場合は、これも受け入れられない遅延を招きます。 (他の優先度の低いユーザ空間タスクはokです)周波数定数を維持することが重要な場合は、カーネルでこれを解決する方がよい(またはリアルタイムカーネルを実行する)こともできます。

+0

100HzのPWM周波数とは、エッジを多少の倍数でシフトする必要があることを意味します(8ビット同等のPWMを得るためにも256倍です)。あなたは10msスケジューラのチックをオフにすることはできません - 8ビットの場合、エッジ解像度は〜40usにする必要があります! –

0

割り込み処理とソフトウェアのやりとりが導入するすべての固有のタイミングジッタ(ソフトウェアが割り込みを無効にしたり、プロセッサが長い無停電電源を処理しているなどのPWM割り込みヒットが発生する命令、または別のサービスルーチンがアクティブである)。最新のマイクロコントローラ(ARM-7、ARM Cortex-M、AVR32、MSPなど)は、PWMジェネレータとして生成するか、または専用に設定できるタイマーを備えています。これらは複数の岩石の安定したPWM信号を生成し、一度設定すると動作を続けるためにゼロのプロセッサ入力を必要とします。これらのPWM出力は、アプリケーションによって必要とされるように、2つの信号が重ならないか、またはエッジが同時であるように構成することができます。

OSスリープ機能を使用してPWMエッジ間の時間を設定する場合、これは遅くなります。スリープ機能は、タスクアクティベーション間の最小時間を設定し、タスクスイッチ、優先度の高いスレッドまたは他のカーネル機能の実行によって遅延される時間間隔を設定します。

+0

私が言ったように、汎用ハードウェア上でPWMを実行することについての学問的な練習であり、具体的な何かを実際に試みることはありません。私は "それはひどくうまくいくが、あなたは専門家のハードウェアを使うべきである"という私の答えを得ているようだ。 – Joe

1

スレッドを使用してRTOSでないOSでスリープしても、非常に正確で一貫した結果が得られません。

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

1

タイマーがある場合は、新しいPWMエッジが必要になるたびに割り込みをキックするようにタイマーを設定できます。巧妙なコーディングでは、割り込みハンドラが多くのPWMチャネルのどれを知っているか、またはハイまたはローのエッジが必要かどうかを知って、次の必要なエッジのために自身をスケジュールできるように、これらをキューに入れることができます。

これらのタイマーが十分あれば、PWMチャンネルごとに1つ割り当てることができます。

割り込みレスポンスが低いエンベデッドコントローラでは、これは驚くほど良好な結果をもたらす可能性があります。

関連する問題