トップページ > dsPIC入門 > dsPICでモーターの制御(5)

PWMモジュールの使い方

 

モーター制御PWMモジュールについて


DCモーターの可変速制御に便利なPWMモジュールです。2チャンネル分のPWM出力を使えば、 手製のHブリッジを制御することができます。デットタイムを自動挿入してくれるので、 それなりに便利です。 3チャンネル分のPWMピンがあるのは、3相PWM用モーターを回す ためです。

C30コンパイラには、PWMモジュールのために用意された便利な関数がそろっています。 これらの関数を使用するには“pwm.h”をインクルードする必要があります。 また、他のモジュールを使用するときと同様に、デバイスファイルもMPLAB上で プロジェクトに追加する必要があります。 なお、このページではdsPIC30F4012 に基づいてPWMモジュールを解説します。PWMモジュールはdsPICの種類によって 機能の差が大きくなっています。 ベースの部分はこのページの内容で把握できますが、 デバイスの性能を十分に発揮させるために 使用デバイスのデータシートも参考にしてください。

用意されている関数一覧

※PWMモジュールの正式名称は、“Motor Control PWM”(モーターコントロール・PWM)モジュールです。 よって、関数名のアタマに“MC”と付いているのは“Motor Control”の略だと分かります。

 

OpenMCPWM()関数

void OpenMCPWM( unsigned int period, unsigned int sptime, unsigned int config1, unsigned int config2, unsigned int config3)

PWMモジュールをONにして、各種設定をする関数です。引数がやたらと多いです。以下で1つずつ解説します。


・unsigned int period : PWM周期(周波数)を指定します。

PWM信号のベース周期のイメージは、上図の通りです。PWMモジュール内部には時間計測のためのカウンタ(“PTMR”レジスタ) があります。この“period”パラメータの値は、そのカウンタの上限値として設定されます。

フリーランモードかシングルショットモードの時のPWM周波数は、この“period”パラメータの値から、上のように計算されます。 「システムクロック」についてはクロックの設定を参照してください。


アップ・ダウンモードとして動作する時は、アップカウントとダウンカウントの往復の分だけ、単なるアップカウントだけの時に 対して2倍の時間がかかります。よって、周波数を計算するときはフリーランモードの時の式に1/2をかける必要があります。 「システムクロック」についてはクロックの設定を参照してください。


 

・unsigned int sptime : AD変換モジュールと同期する時に使います。

“PTMR”レジスタ(PWMモジュール用に割り当てられているカウンタ)の値が一定値に達すると、PWMモジュールは「スペシャル・イベント・トリガー」 を発生します。この信号はAD変換モジュールにおいてサンプリング開始のトリガー、もしくはAD変換開始のトリガーとして使用できます。 使用しなくてもいいです。 PTMRレジスタがいくつになったらトリガーを発生させるかを設定するのが、このパラメーターです。


・unsigned int config1 : PWMモジュールの基本設定をします。

PWMモジュールのON・OFFやPWMのためのカウンタの設定など、基本動作の設定です。
以下に用意されているマクロを列挙します。

PWMモジュールのON・OFF

CPUアイドル時の動作

PWMカウンタの動作

 

“PWM_MOD_FREE”または“PWM_MOD_SING”を選択した場合のカウンタの動作を上図に示します。
この場合はカウンタはアップカウントのみを行います。“PWM_MOD_FREE”として設定した場合は「フリーラン・モード」 と呼ばれるモードになります。このモードでは決められた周期のパルス波形を継続して出力します。 普通にHブリッジを制御するときはこれで十分かと思います。
“PWM_MOD_SING”として設定した場合は「シングルショット・モード」と呼ばれるモードになります。 シングルショット・モードでは、1パルスだけ出力した後にすべてのPWMピンが非アクティブ状態になります。 1パルス出力後に割り込みが発生するので、PWM割り込み関数内で次の処理を決めて、再度OpenMCPWM()関数を呼ぶ… という使い方が一般的だと思います。

 

“PWM_MOD_UPDN”または“PWM_MOD_DBL”を選択した場合のカウンタの動作を上図に示します。
この場合はカウンタがアップ&ダウンカウント動作を行います。よってPWM周期は2倍となります。 “PWM_MOD_UPDN”に設定した場合は「アップダウン・モード」と呼ばれるモードになります。 また、“PWM_MOD_DBL”を選択した場合は「ダブルアップデート・モード」と呼ばれるモードになります。
アップダウン・モードでは継続してパルス波形が出力されますが、デューティサイクルの更新は アップカウントを開始する直前、PTMRレジスタが“0”になった時に行われます。 1周期ごとにデューティサイクルの更新が行わることになります。
それに対してダブルアップデート・モードではデューティサイクルの更新が PTMRレジスタの値が“0”の時、および最大値に達したときに行われます。 つまり1周期の間に2回、デューティサイクルの更新が行われます。

カウンタのインプット・プリスケーラ

システムクロックを分周して、PTMRレジスタのカウントアップ(ダウン)クロックとします。 このクロック信号を分周するためのプリスケーラ値を設定します。

割り込みのためのPWMアウトプット・ポストスケーラ

PWMの割り込みは、PWM出力信号のダウン・エッジで発生します。 このダウン・エッジを検出する際、カウンタを通して割り込み発生信号を分周することができます。 割り込み頻度を調節したい時に使います。


・unsigned int config2 : 各チャンネルごとの動作モードを設定します。

相補パルスモード・独立モードの設定

ここでは解説の都合で、“PWM1L”ピンと“PWM1H”ピンを使用する場合を考えます。
“PWM_MOD1_COMP”に設定すると、PWM1LピンとPWM1Hピンの出力は互いに反転信号となります。(相補PWM:Complementary PWM) この場合はデットタイムの自動挿入機能を利用することができます。(DeadTime設定関数参照) お手軽にHブリッジを制御するならこのモードかと…。

“PWM_MOD1_IND”に設定した場合は、PWM1LとPWM1Hは互いの反転信号ではなく、独立した出力になります。 …とはいっても、デューティサイクルの設定は各“H”と“L”のペアで共通となっています。(デューティサイクル設定関数参照) しかもPWM周期に関してはモジュール内で全て共通となっているわけで、「独立」と言うわりには縛りがキツイ気がします。。。
また、「独立モード」ではデットタイム自動挿入機能は使えません。

各ピンをPWM出力として使うか、I/Oとして使うか


・unsigned int config3 : その他もろもろの設定をします。

スペシャル・イベントのプリスケーラ

スペシャル・イベント・トリガー発生のタイミングを調節するために使います。 sptime引数の値と組み合わせて使います。

出力を上書きするタイミングの設定

OverrideMCPWM()関数によってPWM出力ピンの状態を変更する際、その値が反映される タイミングを決定します。“PMW_OSYNC_PWM”に設定した場合、出力ピン状態の更新はPWM出力の1周期ごと (アップダウンカウントモードの場合は半周期ごと)に行われます。この場合、 PWM出力が細かいノイズを含むことを防ぐことができます。

“PWM_OSYNC_TCY”に設定すると、普通にシステムクロックに同期して更新されます。

各パラメータ上書き許可

基本的に“PWM_UEN”にしておきます。特別に設定値を固定しておきたい場合は“PWM_UDIS”を指定します。


・ソースコード記述例

 
 //==================================================================================================
 //PWMのパラメータを作る

 //“preiod”にはPWM周期を設定。今回は1[kHz]で。
 unsigned int preiod=311;

 //スペシャルイベント・トリガーは使いません。適当な値を入れておきます。
 unsigned int sptime=1000;

 //基本設定。
 //PWMモジュールON、継続動作、割り込み用プリスケーラ1:1、入力プリスケーラ1:64、フリーランモード
 unsigned int PWM_config1= PWM_EN & PWM_IDLE_CON & PWM_OP_SCALE1 & PWM_IPCLK_SCALE64& PWM_MOD_FREE;

 //各ピンの動作設定。(一般的なHブリッジ用の設定をイメージ…)
 //PWM1LとPWM1Hのペア、PWM2LとPWM2Hのペアを相補モードで使用します。PWM3xは汎用IOとして使用。
 unsigned int PWM_config2 = PWM_MOD1_COMP & PWM_MOD2_COMP & PWM_PEN1L & PWM_PEN1H & PWM_PEN2L & PWM_PEN2H & PWM_PDIS3L & PWM_PDIS3H;

 //その他もろもろ。
 //パラメータ上書き許可、PWM出力同期、スペシャルイベントトリガー用プリスケーラ1:1(使わない…)
 unsigned int PWM_config3= PWM_UEN & PWM_OSYNC_PWM & PWM_SEVOPS1;
 

//==================================================================================================
 //PWMモジュールON 
 OpenMCPWM(preiod, sptime,PWM_config1, PWM_config2, PWM_config3);
上へ
 

ConfigIntMCPWM()関数

void ConfigIntMCPWM(unsigned int config)

PWMモジュールが発生する割り込みの設定をする関数です。

・unsigned int config

割り込みの許可・禁止の設定


・ソースコード記述例

 //===================================================================
 //PWMモジュールからの割り込みをOFF
 ConfigIntMCPWM(PWM_INT_DIS);

割り込み関数の記述例

おまけです。

 //===================================================================
 //PWM割り込み関数
 //===================================================================
 void __attribute__((_interrupt_)) _PWMInterrupt(void)
 {
  //フラグクリア
  IFS2bits.PWMIF = 0;

  //あとは、処理をズラズラと…
 
 }
上へ
 

SetDCMCPWM()関数

void SetDCMCPWM(unsigned int dutycyclereg, unsigned int dutycycle, char updatedisable)

“DC”は“Duty Cycle”(デューティ・サイクル)の略です。 PWMのパルス幅を変えて、モーターの速度を変化させる時に使う関数です。 PTMRレジスタ(PWM用のカウンタ)の値とデューティサイクル・レジスタの値の関係は OpenMCPWM()の解説の図を参考にしてください。

・unsigned int dutycyclereg

このパラメータには、普通に「1」・「2」・「3」のいずれかの数字を入れます。 数字に対応したチャンネルのデューティ・サイクルが更新されます。

・unsigned int dutycycle

新しいデューティ・サイクルを入れます。 unsigned int型なので最大値の65536以上には設定できません。要注意です。

また、デューティサイクル設定レジスタとPTMRレジスタの比較回路は、上図のような構成となっています。 デューティサイクルレジスタの1bit目〜15bit目が比較に使用されているため、1ビットずらして設定値 を書き込む必要があります。 2進数演算において1bitの左シフトは、その数値を2倍する演算と同じ結果になります。 よって「デューティは2倍にしておく」と覚えておけば良いかと思います。

・char updatedisable

以下のマクロを利用します。


・ソースコード記述例

 //===================================================================
 //デューティサイクルの設定
 //PWM1H,1Lについての設定。
 //デューティサイクルは50カウント分(2倍の値を入れる!)
 //上書き許可。
 
 SetDCMCPWM(1,100,PWM_UEN);

・デューティサイクルをパーセンテージで決める関数

おまけです。

 //===================================================================
 //setDuty() 周期に対するパーセント値でデューティを設定
 //“L”ピンのアクティブ・デューティが基準
 //第一引数は設定するチャンネル、第二引数はデューティ比[%]
 //===================================================================
 void setDuty(int channel,int percent)
 {
  //最初に引数“percent”をチェック
  if(percent>100 || percent<0)
  {
   return;
  }
  
  //新しいデューティ・カウントを作る
  int duty = 2 * PTPER * (100 - percent) /100;

  //新しいデューティ・カウントをチェック
  if(duty>65536)
  {
   return;
  }

  //登録
  SetDCMCPWM(channel,duty,PWM_UEN);
 }
上へ
 

OverrideMCPWM()関数

void OverrideMCPWM(unsigned int config)

“Over Ride”(オーバー・ライド)は「上書きする」という意味ですが…この関数を使うと、 PWMモジュール内のカウンタの値によらず、無理やりPWM出力ピンの出力を“1”か“0”にする ことができます。

・unsigned int config

用意されているマクロを、以下に列挙します。

各ピンでPWM出力として使うか、自分で設定した定常値とするか
上で“POUT”の方を選んだとき、その出力状態

各ピンにおける“アクティブ状態”は、自分で設定することができます。 特に、PチャネルFETとNチャネルFETを両方用いたHブリッジの場合は、 Pチャネル側が負論理(“0”出力がアクティブ状態)です。そんな時に自分で論理を設定できる機能を利用すると便利です。 設定方法はFBORPORレジスタのコンフィグのページ参照です。


ソースコード記述例

 //===================================================================
 //Hブリッジで、実際にモーターを回転させる時のイメージで…


 //PWM1は、普通にPWM出力
 //PWM2は、定常出力。Pチャネル側(PWM2H)非アクティブ、Nチャネル側(PWM2L)をアクティブ
 //PWM3は、使わない…(とりあえず非アクティブ)

 unsigned int new_state = PWM_GEN_1L & PWM_GEN_1H & PWM_POUT_2L & PWM_POUT_2H & PWM_POUT_3L & PWM_POUT_3H; 
 new_state &= PWM_POUT2L_ACT & PWM_POUT2H_INACT & PWM_POUT3L_INACT & PWM_POUT3H_INACT;

 //登録
 OverrideMCPWM(new_state);
上へ
 

SetMCPWMDeadTimeGeneration()関数

void SetMCPWMDeadTimeGeneration (unsigned int config)

“Dead Time”(デッド・タイム)は、Hブリッジにおいて上段・下段のトランジスタを両方とも OFFにする時間のことをいいます。DeadTimeを入れることでHブリッジに貫通電流が流れないようにできるので、 トランジスタが壊れるのを防ぐこと効果があります。 このDeadTimeの設定をする関数です。また、OverrideMCPWM()関数で出力が上書きされる際にもデットタイムは自動 生成されます。

・unsigned int config

用意されているマクロを以下に列挙します。

デットタイム・カウンタの上限値

デットタイムは、6bitカウンタで計測されます。0から63までカウント可能ですが、その中で上限を設定することで 生成されるデットタイムを決めます。

デットタイム・カウンタのプリスケーラ

デットタイム生成のためのカウンタは、システムクロックでカウントアップされます。このシステムクロックを 分周するプリスケーラを設定します。


・ソースコード記述例

 //===================================================================
 //デットタイム設定

 //プリスケーラ1:8、カウント値63(最長時間に設定)
 SetMCPWMDeadTimeGeneration(PWM_DTAPS8 & PWM_DTA63);
上へ
 

SetMCPWMFaultA()関数

void SetMCPWMFaultA(unsigned int config)

PWMモジュール内に異常を“FLTA”ピンからの入力によって検出し、割り込み処理を発生させます。 フォールト動作入力ピン“FLTA”は、対応するポートのTRISレジスタで入力に設定する必要があります。 何も初期設定しなければ、無効化されたままです。

・unsigned int config


ソースコード記述例

 //===================================================================
 //フォールトピンからの入力を有効化

 SetMCPWMFaultA(PWM_FLTA1_EN & PWM_FLTA_MODE_LATCH & PWM_OVA1L_INACTIVE & PWM_OVA1H_INACTIVE);

PWMフォールト割り込み関数

おまけです。


 void __attribute__((_interrupt_)) _FLTAInterrupt(void)
 {
  //割り込みフラグクリア
  IFS2bits.FLTAIF = 0;

  //ここに処理をズラズラと…
 }
上へ
 

CloseMCPWM()関数

void CloseMCPWM(void)

PWMモジュールをOFFにして終了する関数です。

上へ



戻る