ステッピングモータを初期化するためのプログラムをリスト1に示します。
void SpmInit(void) { // P5(0,1:出力/2,3:入力/プルアップなし)(1) // P50 : SP0 CK // P51 : SP0 CW // P52 : SP0 MO P5.DR.BYTE = 0x00; P5.PCR.BYTE = 0x00; P5.DDR = 0x03; // P6(0,1:出力/2〜6:入力) (2) // P60 : SP1 CK // P61 : SP1 CW // P62 : SP1 MO P6.DR.BYTE = 0x00; P6.DDR = 0x03; // P9(0〜2,4:出力/3,5:入力) (3) // P94 : SP0 STOP // P92 : SP1 STOP P9.DR.BYTE = 0x17; P9.DDR = 0x17; // 初期化 (4) P5.DR.BYTE = 0x00; P6.DR.BYTE = 0x00; // 停止 (5) SpmEnable(0, FALSE); SpmEnable(1, FALSE); }
この関数では、H8/3048F-ONEのポートのうち、ステッピングモータが接続されているポート5、ポート6の設定を行っています(1)〜(3)。DR、PCR、DDRについての詳しい解説は第6回「ターゲットボードでLEDを点灯させてみる」の2ページ目をご覧ください。第6回ではポート2について解説していますが、ポート5、6も基本的には同じ構造です。ポート5、6のうち、出力に設定された信号からLowを出力するようにし(4)、SpmEnable()関数でステッピングモータの使用を禁止としています(5)。
SpmEnable()は、ステッピングモータの使用許可/禁止を選択するための関数です。実際の関数は、リスト2のように記述しています。
#define TRUE 1 #define FALSE 0 //------------------------------------------------ // SpmEnable //------------------------------------------------ // [説明] // ステッピングモータをイネーブルします // [入力] // ch :設定するステッピングモータを0,1で指定します // enable :TRUEを指定するとステッピングモータをイネーブルします // :SpmStep関数でステッピングモータが回転します // :FALSEを指定するとステッピングモータはディスエブルされます // [出力] // なし // [戻り値] // なし //------------------------------------------------ void SpmEnable(int ch, int enable) { if(ch == 0){ if(enable) P9.DR.BIT.B4 = 0; // SP Motor 0 Enable else P9.DR.BIT.B4 = 1; // SP Motor 0 Disable } else{ if(enable) P9.DR.BIT.B2 = 0; // SP Motor 1 Enable else P9.DR.BIT.B2 = 1; // SP Motor 1 Disable } }
モータの回転方向を選択する処理は、リスト3のように記述します。引数の値によってCW信号(モータ0ならポート51、モータ1ならポート61)のHigh、Lowを切り替えます。
//---------------------------------------------------------- // SpmSetCw //---------------------------------------------------------- // [説明] // ステッピングモータのCWビットを設定します // CWの設定によりステッピングモータの回転方向が変わります // [入力] // ch :設定するステッピングモータを0,1で指定します // cw :回転方向をTRUE(=1)/FALSE(=0)で指定します // :TRUEのときHighを出力し、正転します // :FALSEのときLowを出力し、逆転します // [出力] // なし // [戻り値] // なし //---------------------------------------------------------- void SpmSetCw(int ch, int cw) { if(ch == 0) { if(cw) P5.DR.BIT.B1 = 1; // SP Motor 0 CW bit High else P5.DR.BIT.B1 = 0; // SP Motor 0 CW bit Low } else { if(cw) P6.DR.BIT.B1 = 1; // SP Motor 1 CW bit High else P6.DR.BIT.B1 = 0; // SP Motor 1 CW bit Low } }
そして、リスト4の処理でモータを1ステップ回転させます。
//---------------------------------------------------------- // SpmStep //---------------------------------------------------------- // [説明] // ステッピングモータを1ステップ回転します // [入力] // ch :回転するステッピングモータを0,1で指定します // [出力] // なし // [戻り値] // なし //---------------------------------------------------------- void SpmStep(int ch) { if(ch == 0) { P5.DR.BIT.B0 = 1; // SP Motor 0 CLK bit High P5.DR.BIT.B0 = 0; // SP Motor 0 CLK bit Low } else { P6.DR.BIT.B0 = 1; // SP Motor 1 CLK bit High P6.DR.BIT.B0 = 0; // SP Motor 1 CLK bit Low } }
この関数の中で、CLK信号を一瞬Highにして、すぐにLowに落としています。PLDはCLK信号がLowからHighになるとモータを1ステップ回転させる信号を出力しますので、この関数を呼んだ回数だけモータが回転することになります。今回のプログラムではCLK信号をHighにした直後にLowに落としていますが、ターゲットシステムによっては若干の待ち時間を設けた方がいい場合もあります。プログラムを動作させるマイコンの動作周波数とPLDの推奨動作条件をよく見比べて、バランスを取るように注意してください。
これまでの関数を使用してステッピングモータを回転させる処理を記述すると、例えばリスト5のようになります。このプログラムをH8/3048F-ONE上で動作させると、ターゲットボードの電源を切るまで延々とステッピングモータが回り続けます。
void main(void) { SpmInit(); // モータ初期化 SpmSetCw(0, TRUE); // モータ0 の回転方向を設定 SpmSetCw(1, TRUE); // モータ1 の回転方向を設定 SpmEnable(0, TRUE); // モータ0 ON SpmEnable(1, TRUE); // モータ1 ON while(1) { SpmStep(0); // モータ0を1ステップ回転 SpmStep(1); // モータ1を1ステップ回転 Wait(100); // ウェイトを入れる } }
モータを1ステップ回転させた後に、ウェイト関数により次のステップまでの待ち時間を設けています。このウェイト関数は第7回で紹介したものを使用しています。
このウェイト時間があまりに短いと、ロータの回転が追い付かず正常に回転しなくなる「脱調」という、ステッピングモータ特有の現象が起きてしまいますので注意してください。SpmStep()関数の部分でも書きましたが、組み込みプログラミングでは、ハードウェアが正しく機能するタイミングについて気を配ってあげるようにしてください。
本連載のターゲットボードでは、マイコンとステッピングモータの間にPLDを挟むことで、CWとCLKを制御するだけでステッピングモータを制御できましたが、ボードによっては(可能性はほとんどないと思われますが)すべての信号がマイコンにつながれていることがあるかもしれません。その場合は、もちろんプログラム側ですべての信号を制御する必要があります。
また、こちらの方が可能性としては高いと思われますが、世の中にはステッピングモータ用のドライバICというものがあり、やはりCWとCLKを制御するだけでモータを動かせます。その場合、もしモータの動作許可/禁止の切り替えを行いたければ、その部分はプログラム側で作る必要があります(つまり、本連載のPLDはドライバIC+動作許可の機能を肩代わりしていることになります)。重ねて書きますが、組み込みのプログラミングを行うときは、ハードウェアがどういう仕様となっているかをよく知る必要があります。
次回は、DCモータ、サーボモータを制御するための技術として、PWM(Pulse Width Modulation)制御について解説します。(次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.