2001/05/03 【ソフトウエア編TOPに戻る】
ここでは、DCモーターの速度制御をするのに欠かせないPWMについて触れてみたいと思います。これをしないとロボットが思うように動きません。いよいよTekuRobo工作室の本題に入っていきます。(大げさ!)
106−1.PWMとは
PWMとはパルス幅変調(Pulse Width Modulation)方式と呼ばれる手法です。なんのこっちゃ?という感じですが、大したことはありません。モーターの電源を高速で入れたり切ったりすることを繰り返すだけです。なんでそんなことでモーターの速度制御が出来るの?とも思いますが、ちゃんと出来ます。
小学生に、「モーターの速さを変えるにはどうしらいい?」と聞くと、「電池の数を増やす!減らす!」という答えが返ってきそうです。つまり、直列に繋ぐ乾電池の数で、モーターに掛ける電圧を増減させるー!と言うのです。
普通に考えるとこの答えは正解ですが、一定の電源電圧を供給している場合、モーターに掛ける電圧だけを変化させるには、抵抗やレギュレータなどで電圧を下げなければなりません。つまり、余計な電力を消費することによって、モーター電圧を可変させるわけです。これでは効率が悪いし、マイコンからの制御にも向いていません。そこで、PWM方式の登場です。

先ほど、PWMでは高速でモーター電源の入り切り(ON/OFF)を繰り返す、と説明しました。ON/OFFを繰り返すにもちょっと工夫が必要で、ONにする時間とOFFにする時間の比を変えてあげるのです。この比をデューティー比といいます。上の図の左側では、デューティー比が高いほどONになっている期間(オレンジ色の部分)が長く、デューティー比がゼロではずっとOFFのままである様子を示しています。
モーターにこういうタイミングで電源を与えてあげると、あたかもアナログ的に電源電圧を可変してあげたかのように、速度の制御が可能になります。これがPWMによる制御です。
必要な期間しか電源をONにしないので、不要な電力を消費することもありませんし、パルス幅だけで制御できるため、マイコンには扱いやすい方式です。
ただし注意が必要なのが、パルスを与える周期です。つまり、何秒おきにON/OFFを繰り返すか、を最適に設定してあげないといけません。例えば、周期を10秒に設定したとすると、デューティー比が5の場合、5秒ON/5秒OFFを繰り返すことになります。これでは、何の役にも立ちません。ON/OFFを繰り返すといっても、モーターがスムースに回転し続けなければ意味がありません。モーターにはそれぞれ固有の慣性力があり、回転中に電源をOFFにした場合、慣性力によってどれくらいの期間回転を続けるか、の特性があります。PWM制御を行なう場合、この慣性力が働く期間で周期を設定してあげないとスムースな速度制御が出来ません。大体、数百Hz〜数KHzくらいの周期が最適のようです。具体的には、あとで色々と試して決めます。
106−2.PWMのテストプログラムでモーターを動かす
AKI-H8/3048F CPUボードでは、ITU0〜4を使って5チャンネル分のPWM信号を得ることが出来ます。今回のテストプログラムでは、ITU0からPWM信号を出力させて、DCモーター駆動回路を経由して実際に、モーターを動かしてみます。
ITU0のPWM出力は、PIOポートAチャンネルのBit2と端子を共用しているため、開発キットのポートAを外部に出力しているコネクタを、DCモーター駆動回路に接続します。
H8-3048/F CPUでは、ITUによって以下のようなタイミングでPWM波形を出力します。

GRBをカウンタクリア要因に設定した場合、カウンタ値がGRAを過ぎてからGRBに達するまでの期間、パルスが出力されます。なので、GRBでパルス周期を設定し、GRAでデューティー比を設定することが出来ます。なお、GRA > GRB の関係となるように値を設定すると、デューティー比が0(ゼロ)、つまりパルス出力されない状態とすることができます。
下のプログラムはポート4のスイッチSW1〜4を押すことによって、それぞれ設定された速度でモーターが回転します。プログラム上では、それぞれのスイッチに以下のデューティー比を設定してあります。
| スイッチ | デューティー比 |
| SW1 | 0.1 |
| SW2 | 0.5 |
| SW3 | 0.7 |
| SW4 | 0.9 |
つまり、SW1が一番遅く回転し、SW4が一番早く回転します。
ソースプログラムは、ここをクリックするとダウンロードできます。(pwmtest1.c)
また、ハードウエアについては、電子回路編 3.AKI-H8開発キットの回路の[13]PORTA 接続コネクタおよび、4.DCモーター駆動回路を参照して下さい。
なお、スタートアップオブジェクトは、今回割込みを利用していないので、startup.marで結構です。(ちなみに割込み対応のstartup2.marでも問題なく動作します)
|
/****************************************/ |
106−3.テストプログラムpwmtest1.cの説明
このプログラムは、特に関数を分けていません。全てmain関数の中だけで処理しています。
■3048f.hのヘッダファイルを読み込む
#include <3048f.h>
■ITUタイマーモードの設定
ITU.TMDR.BIT.PWM0 = 1; /* ITU0 PWMモード */
ITU.TMDRは、ITU5チャンネル分のPWM動作のON/OFFを設定するレジスタです。その他、ロータリエンコーダを使う場合の設定も行ないますが、今回は使用しません。TMDRとはタイマーモードレジスタのことで、以下の意味を持ちます。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| --- | MDF | FDIR | PWM4 | PWM3 | PWM2 | PWM1 | PWM0 |
Bit7は未使用です。
MDFおよびFDIRはロータリエンコーダを使用するときに設定します。今回は使用しません。
PWM4〜PWM0は、対応するBitを1に設定すると、その対応するITUのTIOCA出力がPWM出力として動作します。今回はPWM0だけをPWMとして動作させるため、Bit0だけを1にします。
なので、 ITU.TMDR.BIT.PWM0=1; とします。
■ITUタイマーコントロールレジスタおよびGRA,GRBの設定
ITU0.TCR.BYTE = 0x43; /* GRBコンペアマッチ clock 1/8 */
ITU0.GRA = 0xFFFE;
/* GRAを65534に設定
*/
ITU0.GRB = 0xFFFD;
/* GRBを65533に設定
*/
ITU.TSTR.BIT.STR0 = 0; /* カウント停止状態
*/
TCR(タイマーコントロールレジスタ)の設定方法については、103.タイマーで正確な時間稼ぎをするのページを参照して下さい。今回は、以下の設定にしています。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| --- | CCLR1 | CCLR0 | CKEG1 | CKEG0 | TPSC2 | TPSC1 | TPSC0 |
| 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
カウンタクリア要因をGRBとする。 CCLR1 = 1, CCLR0 = 0
カウンタはクロックの立ち上がりエッジでカウントする。 CKEG1,2 = 0
カウンタは内部クロックφ/8でカウントする。 TPSC2 = 0, TPSC1,0 = 1
設定値は0100 0011なので、16進数で43Hです。なので、ITU0.TCR.BYTE = 0x43; です。
また、GRBをカウンタクリア要因とすると、GRA > GRB に設定した時、PWM出力はデューティー比が0(ゼロ)になり、モーターが停止状態になるため、
ITU0.GRA = 0xFFFE;
/* GRAを65534に設定 */
ITU0.GRB = 0xFFFD;
/* GRBを65533に設定 */
という値を初期値として設定しておきます。
ITU.TSTR.BIT.STR0 = 0; /* カウント停止状態 */
では、カウンタを停止状態にしてあり、PWM出力を止めています。
■PIOポートの設定
PA.DDR = 0xff;
/* portA出力に設定
*/
P4.DDR = 0x00;
/* port4入力に設定 操作用sw1〜4*/
P4.PCR.BYTE = 0xff;
/* port4プルアップon
*/
PA.DR.BIT.B3 = 0;
/* portA bit3を0固定とする */
ITU.TSTR.BIT.STR0 = 1; /* カウント開始
*/
ポートAを出力に設定し、ポート4を入力に設定しています。ポートAのBit2はPWM0の出力端子としてパルス動作しますが、DCモーター駆動回路へはBit3とペアで制御信号を与えてあげる必要があり、Bit3は常に0(ゼロ)でないとモーターは動作しないので、PA.DR.BIT.B3 = 0; としてあります。DCモーター駆動用ICの動作表を下記に記します。
| VIN1 | VIN2 | OUT1 | OUT2 | モード |
| 1 | 1 | L | L | ブレーキ |
| 0 | 1 | L | H | 正転 |
| 1 | 0 | H | L | 逆転 |
| 0 | 0 | ハイインピーダンス | ストップ | |
今回、VIN1入力にPWMのパルス信号を与え、VIN2は0固定とします。なので、モーター動作は「逆転」のPWM動作となります。この、VIN2を0に固定するのがPA.DR.BIT.B3 = 0;ということになります。(4.DCモーター駆動回路も参照してみて下さい。)
設定部の最後にITU.TSTR.BIT.STR0 = 1;としてカウントを開始させ、PWM0のパルス出力をさせています。
■スイッチによるモーター駆動動作
while(1){ } で無限ループを作っています。で、ループの中で、各スイッチに対応させたPWM動作の設定を変化させています。
ここでは、ITU0.GRAの値を変化させることによって、PWMのデューティー比を変えています。
ITU0.GRA = 0xE665; /* GRAを58981に設定 */ デューティー比
0.1
ITU0.GRA = 0x7FFF; /* GRAを32767に設定 */ デューティー比
0.5
ITU0.GRA = 0x4CCC; /* GRAを19660に設定 */ デューティー比
0.7
ITU0.GRA = 0x1999; /* GRAを6553に設定 */ デューティー比 0.9
ITU0.GRA = 0xFFFE; /* GRAを65534に設定 */ デューティー比 0
このように、ITUによってPWM波形を出力させると、GRAの値を変化させてあげるだけで、簡単にモーターの速度制御ができます。今回はVIN1にだけPWM波形を入力し、VIN2は0に固定したため、片方向のみのモーター制御でした。正転/逆転の制御を行なうためには、更に工夫が必要となりますが、今回の原理さえ分かってしまえば簡単に対応できます。
とりあえず今回は、基本動作のご紹介でした。