トップページ > dsPIC入門 > dsPICでモーターの制御(5)
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”の略だと分かります。
PWMモジュールをONにして、各種設定をする関数です。引数がやたらと多いです。以下で1つずつ解説します。
PWM信号のベース周期のイメージは、上図の通りです。PWMモジュール内部には時間計測のためのカウンタ(“PTMR”レジスタ) があります。この“period”パラメータの値は、そのカウンタの上限値として設定されます。
フリーランモードかシングルショットモードの時のPWM周波数は、この“period”パラメータの値から、上のように計算されます。 「システムクロック」についてはクロックの設定を参照してください。
アップ・ダウンモードとして動作する時は、アップカウントとダウンカウントの往復の分だけ、単なるアップカウントだけの時に 対して2倍の時間がかかります。よって、周波数を計算するときはフリーランモードの時の式に1/2をかける必要があります。 「システムクロック」についてはクロックの設定を参照してください。
“PTMR”レジスタ(PWMモジュール用に割り当てられているカウンタ)の値が一定値に達すると、PWMモジュールは「スペシャル・イベント・トリガー」 を発生します。この信号はAD変換モジュールにおいてサンプリング開始のトリガー、もしくはAD変換開始のトリガーとして使用できます。 使用しなくてもいいです。 PTMRレジスタがいくつになったらトリガーを発生させるかを設定するのが、このパラメーターです。
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回、デューティサイクルの更新が行われます。
カウンタのインプット・プリスケーラ
割り込みのためのPWMアウトプット・ポストスケーラ
相補パルスモード・独立モードの設定
ここでは解説の都合で、“PWM1L”ピンと“PWM1H”ピンを使用する場合を考えます。
“PWM_MOD1_COMP”に設定すると、PWM1LピンとPWM1Hピンの出力は互いに反転信号となります。(相補PWM:Complementary PWM)
この場合はデットタイムの自動挿入機能を利用することができます。(DeadTime設定関数参照)
お手軽にHブリッジを制御するならこのモードかと…。
“PWM_MOD1_IND”に設定した場合は、PWM1LとPWM1Hは互いの反転信号ではなく、独立した出力になります。
…とはいっても、デューティサイクルの設定は各“H”と“L”のペアで共通となっています。(デューティサイクル設定関数参照)
しかもPWM周期に関してはモジュール内で全て共通となっているわけで、「独立」と言うわりには縛りがキツイ気がします。。。
また、「独立モード」ではデットタイム自動挿入機能は使えません。
各ピンをPWM出力として使うか、I/Oとして使うか
スペシャル・イベントのプリスケーラ
出力を上書きするタイミングの設定
各パラメータ上書き許可
//================================================================================================== //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);
PWMモジュールが発生する割り込みの設定をする関数です。
割り込みの許可・禁止の設定
//=================================================================== //PWMモジュールからの割り込みをOFF ConfigIntMCPWM(PWM_INT_DIS);
おまけです。
//=================================================================== //PWM割り込み関数 //=================================================================== void __attribute__((_interrupt_)) _PWMInterrupt(void) { //フラグクリア IFS2bits.PWMIF = 0; //あとは、処理をズラズラと… }
“DC”は“Duty Cycle”(デューティ・サイクル)の略です。 PWMのパルス幅を変えて、モーターの速度を変化させる時に使う関数です。 PTMRレジスタ(PWM用のカウンタ)の値とデューティサイクル・レジスタの値の関係は OpenMCPWM()の解説の図を参考にしてください。
このパラメータには、普通に「1」・「2」・「3」のいずれかの数字を入れます。 数字に対応したチャンネルのデューティ・サイクルが更新されます。
新しいデューティ・サイクルを入れます。 unsigned int型なので最大値の65536以上には設定できません。要注意です。
また、デューティサイクル設定レジスタとPTMRレジスタの比較回路は、上図のような構成となっています。 デューティサイクルレジスタの1bit目〜15bit目が比較に使用されているため、1ビットずらして設定値 を書き込む必要があります。 2進数演算において1bitの左シフトは、その数値を2倍する演算と同じ結果になります。 よって「デューティは2倍にしておく」と覚えておけば良いかと思います。
以下のマクロを利用します。
//=================================================================== //デューティサイクルの設定 //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); }
“Over Ride”(オーバー・ライド)は「上書きする」という意味ですが…この関数を使うと、 PWMモジュール内のカウンタの値によらず、無理やりPWM出力ピンの出力を“1”か“0”にする ことができます。
用意されているマクロを、以下に列挙します。
各ピンでPWM出力として使うか、自分で設定した定常値とするか各ピンにおける“アクティブ状態”は、自分で設定することができます。 特に、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);
“Dead Time”(デッド・タイム)は、Hブリッジにおいて上段・下段のトランジスタを両方とも OFFにする時間のことをいいます。DeadTimeを入れることでHブリッジに貫通電流が流れないようにできるので、 トランジスタが壊れるのを防ぐこと効果があります。 このDeadTimeの設定をする関数です。また、OverrideMCPWM()関数で出力が上書きされる際にもデットタイムは自動 生成されます。
デットタイムは、6bitカウンタで計測されます。0から63までカウント可能ですが、その中で上限を設定することで 生成されるデットタイムを決めます。
デットタイム・カウンタのプリスケーラデットタイム生成のためのカウンタは、システムクロックでカウントアップされます。このシステムクロックを 分周するプリスケーラを設定します。
//=================================================================== //デットタイム設定 //プリスケーラ1:8、カウント値63(最長時間に設定) SetMCPWMDeadTimeGeneration(PWM_DTAPS8 & PWM_DTA63);
PWMモジュール内に異常を“FLTA”ピンからの入力によって検出し、割り込み処理を発生させます。 フォールト動作入力ピン“FLTA”は、対応するポートのTRISレジスタで入力に設定する必要があります。 何も初期設定しなければ、無効化されたままです。
//=================================================================== //フォールトピンからの入力を有効化 SetMCPWMFaultA(PWM_FLTA1_EN & PWM_FLTA_MODE_LATCH & PWM_OVA1L_INACTIVE & PWM_OVA1H_INACTIVE);
おまけです。
void __attribute__((_interrupt_)) _FLTAInterrupt(void) { //割り込みフラグクリア IFS2bits.FLTAIF = 0; //ここに処理をズラズラと… }
PWMモジュールをOFFにして終了する関数です。