114.ステッピングモータを動かす
2003/07/18 【ソフトウエア編TOPに戻る】
今回はステッピングモータを動かして見ましょう。ステッピングモータはパルスモータとも呼ばれ、名前の通りパルス信号を与えることによって決められたステップ単位で回転するモータのことです。トルクはあまり大きくなく、安定して高速で回転することが苦手で、振動が大きいのが特徴です。特に与えるパルス信号の周期があまり短いと、ロータが付いていくことが出来なくなって正常に回転しなくなる脱調という現象が起きてしまいます。つまり、機嫌を取りながら動かす必要があるモータなのです...。
始めに短所ばかりを挙げてしまいました。なんでそんなモータを使うんだ?と言われそうですが、これらの短所を補うほどの多くの利点もあります。
ひとつに、回転角度と回転速度が与えるパルス信号の回数と周期によって決定するということです。つまり、定格負荷内であれば、フィードバック制御なしで思った通りの動きをしてくれるという点です。また、静止トルクが得られます。通電状態(励磁状態)で特定の端子に信号を与えっぱなしにすると比較的大きな静止トルクが得られ、通電しない状態(無励磁状態)でも小さいながら静止トルクがあります。そして、パルスの供給を止めるとピタッとその場で正確に停止します。なので、正確な回転角度制御に適します。また、分類としてはブラシレスモータに属するため、機械的な接触子がなくて長寿命です。
手ごろで小さなサイズのステッピングモータでは、回転トルクが数百g・cm程度とあまり大きくなく、1ステップあたりの最小回転角度も2〜7度程度もあってあまり高い精度は得られませんが、ギヤードタイプのステッピングモータを利用することによって、これらの問題はある程度までは解決することがでるのではないかと期待しています。
今回はサンプルとして3種類のプログラムをご紹介しましょう。
1.wait()関数で単純に駆動パルスを作る方法
2.TPC(タイミングパルスコントローラ)で駆動パルスを作る方法
3.TPCとDMAC(ダイレクトメモリアクセスコントローラ)の組合せで駆動パルスを作る方法
です。
114−1.ステッピングモータの動かし方
今回実験で使用するステッピングモータは以下の2つです。いずれも秋月電子通商の通販で購入しました。
■写真左側 多摩川精機製 TS3103N124
2相ユニポーラ型 ステップ数200(1.8度) 駆動電圧(12V) コイル電流140mA コイル抵抗86Ω/相 | ■写真右側 FDK製 J28A534T
2相ユニポーラ型 ステップ数48(7.5度) 駆動電圧(5V) コイル電流220mA コイル抵抗 18Ω/相 |
気になるトルクですが、いずれもそのものズバリのデータシートが入手できず,正確なところはお伝えできませんが、写真左の大きな方は数Kg・cm、写真右の小さな方は数百g・cm程度と思います。(結構いい加減ですが...) バックラッシュ(軸のガタ)は全くありません。
ステッピングモータの動作原理については省略させて頂きます。メーカーのサイトなどに技術解説が紹介されていますので、そちらをご覧下さい。ここでは、代表的なユニポーラ型ステッピングモータを動かす方法について、簡単にご紹介しましょう。
ステッピングモータはDCモータと違って、ケース側に巻き線コイルがあり、これをステータと呼んでいます。一方回転する方はロータと呼ばれています。 ステータ側はXとXによるコイルと、YとYによるコイルの2つのコイルからなります。ユニポーラ型では、それぞれのコイルの中間点からタップが立っていて、そこから電源を供給してX、X、Y、Yに対して決まった順番に電流を流すことによってロータを回転させるための磁化を行います。これを励磁(レイジ)と呼んでいます。 なので、ユニポーラ型ステッピングモータでは、通常左図のように6本のケーブルが出ています。ただし、今回実験で使用するTS3103N124などは、+DC端子が共通になっており、5本ケーブルになっています。 |
ロータを回転させるための励磁の方法にはいくつかの種類があります。いずれもパルス信号で+DC端子からその他の各端子(相)に対して電流を流します。下の各タイミングチャートでは、パルスが出力されている状態(ハイ状態)に、それぞれの端子に対して電流が流れていることを示します。
■1. 1−1相励磁
これは一番簡単な励磁方法です。X→Y→X→Yの順番に電流を流して行きます。ひとつのパルスを与えるたびに、決められたステップ角だけ回転します。励磁の順番を逆にしてY→X→Y→Xの順に電流を流すと逆向きに回転します。
1−1相励磁は最も単純なパターンで分かり易いのですが、トルクが小さくてあまり安定性が良くなく、実用ではほとんど利用されていません。
■2. 2−2相励磁
これは各相のパルス幅が1−1相励磁の2倍の幅となり、次の相と1パルス分ずつずらしながら同時に励磁します。1−1相励磁と同様に、X→Y→X→Yの順で正転、Y→X→Y→Xの順で逆転します。
1−1相励磁に比べて回転が安定し、高いトルクが得られますので良く利用されますが、消費電力は2倍必要です。
■3. 1−2相励磁
これは、各相のパルス幅を3とし、次の相とは2パルス分だけずらして励磁していく方法です。良く見ると1−1相励磁と2−2相励磁を交互に繰り返しているのと同じことをしています。
この励磁方法は1パルス幅ごとに回転する角度が1−1相励磁と2−2相励磁に比べて半分になるという特徴(ハーフステップ動作)があります。
【先頭に戻る】
114−2.手動で動かして見る
上記のパルス波形などを見ていると、4個のパルスを使って何やら難しそうに思えますが、そんなことはありません。ただ動かすだけなら簡単に動かすことができます。試しにステッピングモータを手動で動かして見ましょう。今回、実験用に以下の基板を作って見ました。
基板には電源用とステッピングモータ用のコネクタの他に、左からX→Y→X→Yの各押しボタンスイッチがついています。スイッチは手持ちのものを使ったため、LEDは使用していません。
回路図を見て頂くとわかりますが、ステッピングモータの+DC端子に電源をつなぎ、X、Y、X、Yの各端子にスイッチを付けてグランドに接続できるようにしているだけのものです。下の写真は実験風景です。
コネクタに電源とステッピングモータを接続し、左から順に1つずつ押しボタンを押して行くと、ひとつ押すたびに1ステップずつモータが回転して行きます。逆に、右から順に押して行くと、今度は逆回転を始めます。 この時の動作が1−1励磁ということになります。 試しにどれかひとつの押しボタンを押しっぱなしにすると、軸を手で廻そうとしても廻らないくらいの静止トルクが発生していることが分かります。
|
実際に動かして見ると、ステッピングモータはいとも簡単に動いてしまうことが分かりましたね。
【先頭に戻る】
消防車が行われますか
114−3.ステッピングモータドライブ回路
では次に、手動ではなくマイコンからの制御でステッピングモータを回転させるためのテスト回路を組んでみましょう。上記の手動の回路で押しボタンスイッチを使っていた部分を、パワートランジスタに置き換えるだけです。
トランジスタは実際にはダーリントン構造の2SD1572を利用しています。コレクタから電源に接続されているダイオードはステッピングモータのコイルによる逆起電力を逃がして回路を保護するためのもので、1S1885などを利用します。電源の電解コンデンサはノイズ対策で、とりあえず100μ25V程度のものにしています。CN1がマイコンからパルス信号を入力するためのコネクタです。CN2はステッピングモータを接続するためのコネクタで、配線をTS3103N124に合わせてあります。
下の写真がテスト基板の出来上がりです。
では、いよいよAKI-H8でステッピングモータを動かして見ましょう。
【先頭に戻る】
114−4.ステッピングモータ駆動プログラム その1 steptest1.c
このプログラムは、最も簡単にステッピングモータを動かすためのプログラムです。2−2相励磁を行うパルスパターンをwait()関数を使って作っています。ついでにボリュームでパルスの周期を可変できるようにしています。1パルスあたり1mS〜256mSの周期で可変できます。
ここをクリックするとソースプログラムをダウンロードできます。steptest1.c
なお、今回はベストテクノロジーのGDL(GCC Developer Lite版)で記述しています。
/**************************************************/ #include <3048.h> /* メイン関数 ****************************************/ int ad_data; // A/D変換結果用変数 PA.DDR = 0xFF; // portA出力に設定 while(1){ /* 2−2相励磁パルス出力 */ PA.DR.BYTE = 0x03; PA.DR.BYTE = 0x06; PA.DR.BYTE = 0x0C; PA.DR.BYTE = 0x09; |
このプログラムは、特に解説が必要な部分はありません。過去のPIO関連の記事やAD変換関連の記事を参照して頂ければすぐに分かると思いますが、要点だけをご説明します。
■ヘッダファイルの読み込み
#include
今回は、自作のmyfunc.hというヘッダファイルを読み込んで、指定時間待機するwait()という関数を使うための下準備をしています。 myfunc.hについては、151.自分の関数をヘッダファイルにするを参照して下さい。
■パラレルポートの初期化
PA.DDR = 0xFF; //portA出力に設定
P1.DDR = 0xFF; //port1出力に設定
ここでは、PIOポートのPAとP1を出力bitに設定しています。PAはステッピングモータを動作させるための出力として利用し、P1はパルスの出力状況をLEDでモニタするための出力として利用します。
■関数とAD変換機能の初期化
timer_init(); //wait関数タイマー初期化
AD.CSR.BYTE = 0x30; //SCAN MODE CH0
timer_init();はwait()関数を使うために、ITU0チャンネルの初期化を行っています。また、AD.CSR.BYTE = 0x30;はチャンネル0のAD変換入力をスキャンモードで連続的に取り込むための初期化処理です。
■AD変換値の取り込みとデータ処理
while(AD.CSR.BIT.ADF == 0){} // 0CHの変換終了を待つ
ad_data = AD.DRA>>8; // A/D変換値の取り込み
P1.DR.BYTE = ad_data; // モニター用出力
ここでは、チャンネル0から取り込んだAD変換値を8bit下位にシフトさせ、上位8bit分の変換値だけを取り込んでいます。なので、ボリュームを右から左に廻した場合、0〜255の値を取り出すことができるようになります。その後、P1.DR.BYTE = ad_data;で取り込んだ値でモニター用のLEDを点灯させています。
■2−2相励磁パターンの出力
PA.DR.BYTE = 0x03;
wait(ad_data+1);
PA.DR.BYTE = 0x06;
wait(ad_data+1);
PA.DR.BYTE = 0x0C;
wait(ad_data+1);
PA.DR.BYTE = 0x09;
wait(ad_data+1);
この部分は、PAから0x03→0x06→0x0C→0x09と連続して出力させることによって、下の表のように2−2相励磁のパルスパターンを出力しています。
Y | X | Y | X | |
0x03 | 0 | 0 | 1 | 1 |
0x06 | 0 | 1 | 1 | 0 |
0x0C | 1 | 1 | 0 | 0 |
0x09 | 1 | 0 | 0 | 1 |
パルスを出力している期間はwait(ad_data+1);によって決まります。なので、AD変換で取り込んだ値によって1mS〜256mSの期間で可変できることになります。
【先頭に戻る】
114−5.ステッピングモータ駆動プログラム その2 steptest2.c
次は、H8でパルスパターンを出力するための専用のコントローラ機能を利用してみましょう。TPC(タイミングパターンコントローラ)機能です。TPCはITU(インテリジェントタイマーユニット)とペアで使います。ITUのGRAなどでコンペアマッチによる割り込みが発生すると、あらかじめNDR(ネクストデータレジスタ)に書き込んでおいたデータが、PAもしくはPBから出力されるという機能です。ITUの割込み処理内で、次のNDRのデータを更新することによって、基本的にはどんなパターンのパルス信号でも正確な周期で出力させることが可能になります。
ここをクリックするとソースプログラムをダウンロードできます。steptest2.c
なお、今回もベストテクノロジーのGDL(GCC Developer Lite版)で記述しています。
/**************************************************/ #include <3048.h> int ad_data; // A/D変換結果用変数 /* メイン関数 ****************************************/ EI; // 割り込みマクロ cnt = 0; 我々は、牛からどのような製品を得るのですか PA.DDR = 0xFF; // portA出力に設定 ITU0.TCR.BYTE = 0x23; // GRAコンペアマッチ clock 1/8 PA.DR.BYTE = 0x03; // PA出力初期化 ITU.TSTR.BIT.STR0 = 1; // カウント開始 while(1){ /* ITU0A割り込み処理******************************/ cnt++; // cntの数を1つ増やす //2−2相励磁パターン出力 while(AD.CSR.BIT.ADF == 0){} // 0CHの変換終了を待つ |
前出のsteptest1.cのプログラムと違う部分を中心にご説明します。
■ITU0チャンネルの初期化
ITU0.TCR.BYTE = 0x23; // GRAコンペアマッチ clock 1/8
ITU0.GRA = 65000; // GRAを65000に設定
ITU0.TIER.BYTE = 0xF9; // ITU0のGRAによるコンペアマッチ割込みを許可*/
TPC(タイミングパターンコントローラ)を利用するためITU0チャンネルを初期化しています。注目はGRAによる割り込みを許可しているところです。この割込みタイミングでTPCの操作を行います。
■TPCの初期化
PA.DR.BYTE = 0x03; // PA出力初期化
TPC.NDERA.BYTE = 0x0F; // 3〜0bitをTPC使用許可
TPC.TPCR.BYTE = 0xF0; // ITU0をトリガとする。
TPC.NDRA1.BYTE = 0x03; // 次の出力データ設定
一連のこの部分がTPC設定の初期化部分です。
PA.DR.BYTE = 0x03; // PA出力初期化
先ず、TPCでパルスパターンを出力するポートPAを、最初の出力データに初期化しています。
TPC.NDERA.BYTE = 0x0F; //3〜0bitをTPC使用許可
NDERAは、ネクストデータイネーブルレジスタのAグループという意味です。つまりポートPAをTPC用のパルスパターン出力に利用するか、しないかをbit単位で設定できます。使用するならばITUの割り込みタイミングでNDRA(ネクストデータレジスタAグループ)に書き込まれているデータがポートPAの対応するビットにセットされます。今回は下位4ビットだけを使用するので、TPC.NDERA.BYTE = 0x0F;としています。
TPC.TPCR.BYTE = 0xFC; //ITU0をトリガとする。
TPCRはTPC出力コントロールレジスタで、TPC出力を変化させるためのトリガを選択するレジスタです。ところでTPCには0〜3の4グループあり、各グループは4bitずつに分かれています。各TPCと実際の出力ポートには以下の関係があります。
グループ番号 | 出力ポート |
グループ0 | PA3〜0 |
グループ1 | PA7〜4 |
グループ2 | PB3〜0 |
グループ3 | PB7〜4 |
今回はグループ0しか使用しませんが、上記のように4グループ分のTPCが独立したタイミングで出力させることができるのです。
で、TPCRのレジスタですが、以下の意味があります。
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
G3CMS1 | G3CMS0 | G2CMS1 | G2CMS0 | G1CMS1 | G1CMS0 | G0CMS1 | G0CMS0 |
G3CMS1,0 :グループ3のTPC出力を変化させるトリガを選択する。
G2CMS1,0 :グループ2のTPC出力を変化させるトリガを選択する。
G1CMS1,0 :グループ1のTPC出力を変化させるトリガを選択する。
G0CMS1,0 :グループ0のTPC出力を変化させるトリガを選択する。
つまり各グループ毎に2bitずつ割り当てられてごり、全てのグループで以下の意味を持ちます。
1 | 0 | 意味 |
0 | 0 | 出力トリガをITU0のコンペアマッチとする。 |
0 | 1 | 出力トリガをITU1のコンペアマッチとする。 |
1 | 0 | 出力トリガをITU2のコンペアマッチとする。 |
1 | 1 | 出力トリガをITU3のコンペアマッチとする。 |
今回はグループ0のTPCをITU0のコンペアマッチ割込みで更新したいので、
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
G3CMS1 | G3CMS0 | G2CMS1 | G2CMS0 | G1CMS1 | G1CMS0 | G0CMS1 | G0CMS0 |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
としています。なので、TPC.TPCR.BYTE = 0xF0; です。ここではG1CMS0と1のビットも0にしています。その理由は以下の説明に関連しています。
■NDRA(ネクストデータレジスタ)の設定。
TPC.NDRA1.BYTE = 0x03; //次の出力データ設定
NDRAは、グループ0とグループ1のTPCに出力させたい次のデータを格納しておくための8bitのレジスタです。NDRAのアドレスは、TPCRで設定した出力トリガの要因によって2種類に分かれます。
1.TPC出力ブループ0と1の出力トリガ要因が同じ場合
レジスタアドレス → FFA5
逆引きランプはどこにありますか?
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
NDR7 | NDR6 | NDR5 | NDR4 | NDR3 | NDR2 | NDR1 | NDR0 |
今回はこの事例に該当します。この場合、Cコンパイラ上はNDRA1と指定します。
2.TPC出力ブループ0と1の出力トリガ要因が違う場合
レジスタアドレス → FFA5
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
NDR7 | NDR6 | NDR5 | NDR4 | - | - | - | - |
上位4bit、グループ1用のネクストデータを設定するレジスタになります。Cコンパイラ上はNDRA1と指定します。
レジスタアドレス → FFA7
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | - | - | - | NDR3 | NDR2 | NDR1 | NDR0 |
上位4bit、グループ0用のネクストデータを設定するレジスタになります。Cコンパイラ上はNDRA2と指定します。
■ITU割り込み処理内でパルスパターンの設定
void int_imia0(void){
cnt++; // cntの数を1つ増やす
if (cnt > 3) cnt = 0;
//2−2相励磁パターン出力
switch(cnt){
case 0: TPC.NDRA1.BYTE = 0x03;
break;
case 1: TPC.NDRA1.BYTE = 0x06;
break;
case 2: TPC.NDRA1.BYTE = 0x0C;
break;
case 3: TPC.NDRA1.BYTE = 0x09;
break;
}
ITU0チャンネルのGRAコンペアマッチで発生した割り込み処理内で、NDRAに次の出力データを設定している部分です。cntというグローバル変数をキーとして、4パターンを繰り返し出力する処理をしています。
■ITU割り込み処理内でAD変換と変換値の処理
while(AD.CSR.BIT.ADF == 0){} // 0CHの変換終了を待つ
ad_data = AD.DRA>>8; // A/D変換値の取り込み
P1.DR.BYTE = ad_data; // モニタ出力
ITU0.GRA = 2000 + (ad_data * 240); // 周期の設定
ITU0.TSR.BIT.IMFA = 0; // 割込み検知フラグを戻して再開
この部分は、steptest1.cと同様の処理ですが、周期の設定方法だけが違います。ad_dataの値は0〜255の間で可変されるため、ITU0.GRAの値は2000〜63200の値をとります。ITU0のTCNTのカウントアップ周期は0.5μSになるので、GRAのコンペアマッチ割り込みは1mS〜31.6mSの間で可変されることになります。この周期がステッピングモータを駆動させるためのパルス周期となります。
【先頭に戻る】
114−5.ステッピングモータ駆動プログラム その3 steptest3.c
次は、もうちょっとだけ進んだパルスパターン出力の方法をご紹介しましょう。TPCとDMACの組合せです。DMACとはダイレクトメモリーアクセスコントローラのことで、CPUのソフトウエア処理を介さずに、コントローラが直接メモリー間のデータのやり取りを行う機能です。今回はこの機能を使って、NDRAへのデータの書き込みを、予め決めておいたパターンデータから勝手に行われるという処理をしてみます。
今回使う機能は、DMACの多くの機能から、 ショートアドレスモードの中のリピートモードという機能を利用します。これは、決めておいたメモリエリアの中の複数のデータを順に読み出し、繰り返し指定アドレスに転送するモードです。転送を行うトリガは、ITU0のGRAコンペアマッチ割込みのタイミングです。
ここをクリックするとソースプログラムをダウンロードできます。steptest3.c
なお、今回もベストテクノロジーのGDL(GCC Developer Lite版)で記述しています。
/**************************************************/ #include <3048.h> static char data[4] = {0x03,0x06,0x0C,0x09}; //励磁パターンデータ /* メイン関数 ****************************************/ // EI; //割り込みマクロ int dummy; //ダミー変数 PA.DDR = 0xFF; //portA出力に設定 ITU0.TCR.BYTE = 0x23; //GRAコンペアマッチ clock 1/8 PA.DR.BYTE = 0x00; //PA出力初期化 DMAC0A.MAR = data; //パターンデータ設定 ITU.TSTR.BIT.STR0 = 1; //カウント開始 while(1){ |
今回も前出のsteptest1.cやsteptest2.cプログラムと違う部分を中心にご説明します。
■出力パターンデータの設定
static char data[4] = {0x03,0x06,0x0C,0x09}; //励磁パターンデータ
このパターンデータは、steptest1.cの時にご説明した2−2相励磁パターンを示す4個のデータからなります。これをdata[4]という配列変数に格納して初期化しています。
■パラレルポートの初期化
PA.DDR = 0xFF; //portA出力に設定
P3.DDR = 0x00; //port3入力に設定
今回のプログラムでは、GRAコンペアマッチの周期(パルス出力周期)をP3のポート8bitから入力しています。なので、上記のような設定になります。
■ITU0の初期化
steptest2.cと同じです。
■TPCの初期化
steptest2.cと同じです。
■DMACの初期化
DMAC0A.MAR = data; //パターンデータ設定
DMAC0A.IOAR = 0xA5; //TPCのNDRAレジスタ設定
DMAC0A.ETCR = 0x0404; //DMACのリピート回数をETCRHとETCRLに設定
dummy = DMAC0A.DTCR.BIT.DTE; //DTE bitの読み込み
DMAC0A.DTCR.BYTE = 0x90; //インクリメント,リピート,ITU0A割込み起動
DMACには、DMAC0A,0B,1A,1Bの4チャンネルありますが、今回はDMAC0Aのみを使用します。
DMAC0Aの初期化は、以下の手順で行います。
DMAC0A.MAR = data; //パターンデータ設定
先ず、32bitのMAR(メモリアドレスレジスタ)の設定を行います。これは、転送させたいデータが格納されているメモリ領域の先頭アドレスを指定します。ここではDMAC0A.MAR = data; としていますが、dataとはパターンデータを格納している配列変数data[4]の先頭アドレスを示すポインタとして機能します。なので、MARにdata[4]の配列変数の先頭アドレスが渡されることになります。
DMAC0A.IOAR = 0xA5; //TPCのNDRAレジスタ設定
次に、8bitのIOAR(I/Oアドレスレジスタ)に、データの転送先を示すI/Oアドレスの下位8bitを設定します。今回はNDRAなので、A5になります。ショートアドレスモードなので、上位16bitのアドレス値は、自動的に0xFFFFに設定されます。
DMAC0A.ETCR = 0x0404; //DMACのリピート回数をETCRHとETCRLに設定
次に、16bitのETCR(転送カウントレジスタ)に、転送させたいデータの数を設定します。ただしリピートモードの場合は、上位と下位の8bitずつに分け、両方に同じデータを設定します。今回は、data[4] = {0x03,0x06,0x0C,0x09}; とあるように4種類のデータ転送を繰り返したいので、DMAC0A.ETCR = 0x0404; としています。実際の動作では、上位8bitが転送回数を数えるダウンカウンタとして機能し、カウンタが0になったら下位8bitのデータが再び上位8bitにコピーされてリピートされるという動作になります。なので、リピートモードでは繰り返し転送できるデータの種類は最大でも255までということになります。
dummy = DMAC0A.DTCR.BIT.DTE; //DTE bitの読み込み
これはDTCR(データトランスファコントロールレジスタ)のDTE(データトランスファイネーブル)というbitの値を読み込む処理です。これをしないとDMACが動作しません。
DMAC0A.DTCR.BYTE = 0x90; //インクリメント,リピート,ITU0A割込み起動
DTCR(データトランスファコントロールレジスタ)の設定を行う部分です。レジスタには以下の意味があります。
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DTE | DTSZ | DTID | RPE | DTIE | DTS2 | DTS1 | DTS0 |
DTE:データトランスファイネーブル データ転送を許可(1)、禁止(0)します。
DTSZ:転送されるデータサイズを指定します。バイト(0)、ワード(1)
DTID:データトランスファインクリメント/デクリメント MARで指定したアドレスから次のデータを取り出す時のアドレスの指定方法です。インクリメント(0)→ひとつ次のアドレスへと移動します。デクリメント(1)→ひとつ前のアドレスへと移動します。
RPE:リピートモード リピートモードであることを指定します。リピートモード時(1)、それ以外(0)
DTIE:データトランスファインタラプトイネーブル データ転送が終了したときに割り込みを発生させる(1)、させない(0)を指定します。
DTS2〜0:データ転送の起動要因を指定します。ITUに関連する部分だけを抜粋すると以下の通りとなります。
DTS2 | DTS1 | DTS0 | 説 明 |
0 | 0 | 0 | ITU0のコンペアマッチA割込みで起動 |
0 | 0 | 1 | ITU1のコンペアマッチA割込みで起動 |
0 | 1 | 0 | ITU2のコンペアマッチA割込みで起動 |
0 | 1 | 1 | ITU3のコンペアマッチA割込みで起動 |
以上の条件を今回に当てはめると以下の通りとなります。
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DTE | DTSZ | DTID | RPE | DTIE | DTS2 | DTS1 | DTS0 |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
なので、DMAC0A.DTCR.BYTE = 0x90;となります。
■TCNTのカウントを開始して、メインプログラム処理
ITU.TSTR.BIT.STR0 = 1; //カウント開始
while(1){
ITU0.GRA = 2000 + (P3.DR.BYTE * 240); //周期の設定
}
ITU.TSTR.BIT.STR0 = 1;でTCNTのカウントを開始すれば、GRAでコンペアマッチが発生するたびにDMACが起動して、勝手にPAから2−2相励磁のパルスパターンが出力され続けます。
while(1)文の中身では、GRAの値(パルス出力の周期)を設定するための処理がされているだけです。
■割込み処理のプログラム記述は必要なし
さて、何かが足りない気がします。そう、ITUによる割込み処理を行う関数部分がありません。割り込みでDMACが起動されると、割込み処理はCPUが知らないところで行われます。つまり、決められた仕事をハードウエアが勝手に行うのです。なので、CPUから見ると最も効率のよい処理と言えます。
ちなみに、
// EI; //割り込みマクロ
というように、割込みマクロ部分をコメント文にしてしまっても、ちゃんとステッピングモータは回転してくれます。
【先頭に戻る】
さて、今回は「とりあえず」ステッピングモータを廻すことができた、というレベルでしょうか。(^^;
実際に実験で使用したステッピングモータは、2種類ともパルス周期1mSに達する前に脱調に陥り、正常に回転しなくなりました。このことからも、DCブラシモータに比べて全然高速回転には適していないことが分かります。
実際にステッピングモータを安定よく回転させるためには、ドライバ回路側にも様々な工夫が必要です。更にステップごとにカクカクとではなく、より滑らかに廻したいというのであれば、与えるパルス信号を正弦波に近い多段多値の信号にすることによって細かく動かすマイクロステップ法などもあったりします。今回最終的な目的としては、ギヤードのステッピングモータを安定して動作させることなので、やはり安定良く高速回転させ、またパルス周期を細かく自由に制御できる技術の習得が必要でしょう。
そう言えば、今回のサンプルプログラムの中に正転/逆転を切り替える処理が入っていませんでしたが、多分皆さんはすぐに実現できることでしょう。(^^;
ステッピングモータには今回ご紹介したユニポーラ型のほかに、もっと効率の良いバイポーラ型などもあり、興味の湧くところです。 ステッピングモータの関連技術は、今後少しずつ勉強を進めて行くことにします。(^^;
0 件のコメント:
コメントを投稿