ステッピングモータ (12 相励磁 ) 低速なステッピングモータ制御モジュールを紹介します. 用途としては, エアコンの風向制御をイメージしていただければよいと思います. ソフトウェア制御のため, ハードはドライバICのみでOKです. <12 相励磁 > 1 < 仕様 > 指定位置への移動動作 ( 高速動作 ) 指定範囲内での往復動作( 低速動作 ) 動作開始時と動作停止時には一定時間の停止パルスを出力して, 位置の安定化を図る. 動作中の指示変更時は, 動作方向が同じならば, そのまま動作を継続逆方向への動作ならば, 一旦停止パルスを出力 高速動作/ 低速動作とも, 動作速度は変更可能 1パルスの励磁時間はメインルーチンの実行間隔とする (1ms 単位 ). <ステッピングモータの動作イメージ> 4 2 3 相番号 コイル4 コイル3 コイル2 コイル1 0 1 2 3 4 5 6 7 励磁パターンを順次変更していくと力の向きが変わり, 回転できる < マイコン出力波形 > H: < 動作範囲 > 上限 往復範囲 下限
< 動作マトリクス > 停止 REQ 固定位置 REQ 往復 REQ 停止 () 現在位置と同じなら無視異なれば停止パルス中へ 停止パルス中へ 停止 ( 固定位置 ) 現在位置と同じなら無視異なれば停止パルス中へ 停止パルス中へ 停止パルス中 ( 停止パルス終了後 ) ( 停止パルス終了後動作 ) ( 停止パルス終了後動作 ) 下方範囲外動作中停止パルス中へ高速動作継続高速動作継続 範囲内動作中 ( 方向 ) 停止パルス中へ停止パルス中へ往復低速動作継続 範囲内動作中 (+ 方向 ) 停止パルス中へ停止パルス中へ往復低速動作継続 上方範囲外動作中停止パルス中へ高速動作継続高速動作継続 ;***** ポート定義 ***** P_STM1.BTEQU 0,p1 ; (O) P_STM2.BTEQU 1,p1 ; (O) P_STM3.BTEQU 2,p1 ; (O) P_STM4.BTEQU 3,p1 ; (O) I/O ポートは出力モードで初期化しておいて下さい ;***** STM ***** ZMSSTG:.BLKB 1 ; STG 番号 ZMBCMD:.BLKB 1 ; コマンド ; 00: 停止 ; 01: 固定位置リクエスト ; 02: 往復リクエスト ZMBDIR:.BLKB 1 ; 方向フラグ ; 00: + 方向 ; 01: 方向 ZMBSTP:.BLKW 1 ; 停止パルス ZMCSTP:.BLKW 1 ; 停止パルスカウンタ ZMBPOS:.BLKW 1 ; 現在位置 ZMBPSK:.BLKW 1 ; 固定位置 ZMBPSL:.BLKW 1 ; 往復下限位置 ZMBPSH:.BLKW 1 ; 往復上限位置 ZMBV:.BLKB 1 上限 ; 速度カウンタ値 (ZMBVL or ZMBVH をコピー ) ZMCV:.BLKB 1 ; 速度カウンタ (ZMBV をコピーして動作 ) ZMBVL:.BLKB 1 ; 低速カウント値 ZMBVH:.BLKB 1 ; 高速カウント値 ROM 領域の初期値を RAM 領域にコピーして使用 プログラムを書き換えないで位置 / 速度をメモリファインダーで変更しながら評価するため
;***** STMモジュール初期化 ***** M_INI: MOV.W Q_MBPSK,ZMBPSK ; 固定位置 MOV.W Q_MBPSL,ZMBPSL ; 往復下限 MOV.W Q_MBPSH,ZMBPSH ; 往復上限 MOV.B Q_MBVL,ZMBVL ; 低速移動パルス時間初期値 MOV.B Q_MBVH,ZMBVH ; 高速移動パルス時間初期値 MOV.W Q_MBSTP,ZMBSTP ; 停止パルス時間初期値 Q_MBPSK:.WORD 100 ; 固定位置 Q_MBPSL:.WORD 200 ; 往復下限位置 Q_MBPSH:.WORD 500 ; 往復上限位置 Q_MBVL:.BYTE 15 ; 低速カウント値 Q_MBVH:.BYTE 5 ; 高速カウント値 Q_MBSTP:.WORD 1000 ; 停止パルス ROM 領域の初期値 ;***** STM 制御メイン ***** M_MAIN: MOV.B ZMSSTG,R0L ; 状態遷移番号 (STG) JNZ M_MAIN10 ; ***** 時の処理 ***** JSR M_STG0 JMP.B M_MAIN90 M_MAIN10: CMP.B #01,R0L JNZ M_MAIN20 ; ***** 停止パルス中の処理 ***** JSR M_STG1 JMP.B M_MAIN90 M_MAIN20: ; ***** 動作中の処理 ***** JSR M_STG2 M_MAIN90: メインルーチンで 1ms 毎に呼び出す ;***** 中の処理 ***** M_STG0: MOV.B ZMBCMD,R0L ; リクエスト? JZ M_STG090 ; Yes, スキップ CMP.B #01,R0L JNZ M_STG010 ; 往復動作なら停止パルス開始へ ; ***** 固定位置リクエスト ***** JSR M_CMP ; 現在位置と目標位置の比較 JZ M_STG090 ; 一致ならスキップ M_STG010: MOV.W ZMBSTP,ZMCSTP ; 停止パルスカウンタセット JSR M_OUT ; 相出力 MOV.B #01,ZMSSTG ; 停止パルス中 STG M_STG090:
;***** 停止パルス中の処理 ***** M_STG1: SUB.W #1,ZMCSTP ; 停止パルスカウンタ 1 JNZ M_STG190 ; 0000でなければスキップ MOV.B ZMBCMD,R0L ; 停止コマンド? JZ M_STG180 ; Yes, 出力 へジャンプ CMP.B #01,R0L ; 固定位置コマンド? JNZ M_STG110 ; ***** 固定位置コマンド ***** JSR M_CMP ; 現在位置と目標位置の比較 JZ M_STG180 ; 一致なら出力 へジャンプ JNC M_STG130 ; 現在 < 固定位置 : 高速移動 + 方向 JMP.B M_STG150 ; 現在 > 固定位置 : 高速移動 方向 M_STG110: ; ***** 往復コマンド ***** JSR M_CMP ; 現在位置と上限 / 下限位置の比較 CMP.B #00,R0L ; 範囲内? JNZ M_STG120 ; 範囲外ならジャンプ ; *** 範囲内 *** CMP.B #00,ZMBDIR ; 記憶している方向判断 JZ M_STG140 ; + 方向なら 低速移動 + 方向 JMP.B M_STG160 ; 方向なら 低速移動 方向 M_STG120: CMP.B #01,R0L ; 下限と一致? JZ M_STG140 ; 現在 = 下限なら 低速移動 + 方向 CMP.B #02,R0L ; 上限と一致? JZ M_STG160 ; 現在 = 上限なら 低速移動 方向 CMP.B #03,R0L ; 現在 < 下限? JNZ M_STG150 ; 現在 > 上限なら 高速移動 方向 ; 現在 < 下限なら 高速移動 + 方向 M_STG130: MOV.B #00,ZMBDIR ; + 方向 ADD.W #1,ZMBPOS ; 現在 現在 +1 JMP.B M_STG170 M_STG140: MOV.B #00,ZMBDIR ; + 方向 MOV.B ZMBVL,ZMBV ; 低速移動 ADD.W #1,ZMBPOS ; 現在 現在 +1 JMP.B M_STG170 M_STG150: MOV.B #01,ZMBDIR ; 方向 SUB.W #1,ZMBPOS ; 現在 現在 1 JMP.B M_STG170 M_STG160: MOV.B #01,ZMBDIR ; 方向 MOV.B ZMBVL,ZMBV ; 低速移動 SUB.W #1,ZMBPOS ; 現在 現在 1 M_STG170: MOV.B #02,ZMSSTG ; 動作中 STG JSR M_OUT ; 出力 JMP.B M_STG190 M_STG180: AND.B #0F0h,p1 ; MOV.B #00,ZMSSTG ; 中 STG M_STG190: この例では, p1_0 ~ p1_3 が STM 用ポートとして割り当てられています
M_STG2: DEC.B ZMCV ; 移動パルスカウンタ 1 JNZ M_STG290 ; 00 以外ならスキップ ; パルスカウンタ再セット CMP.B #02,ZMBCMD ; 停止 or 固定位置リクエスト? JNC M_STG230 ; Yes, 停止パルスへジャンプ JSR M_CMP ; 現在と上限 / 下限を比較 CMP.B #00,R0L ; 範囲内? JNZ M_STG200 ; No, ジャンプ ; *** 範囲内 *** MOV.B ZMBVL,ZMBV ; 低速移動 CMP.B #00,ZMBDIR ; 記憶してある方向判断 JNZ M_STG260 ; + 方向? No, 低速移動 方向 JMP.B M_STG250 M_STG200: ; *** 範囲外 *** CMP.B #03,R0L JNC M_STG220 ; 上限 or 下限なら停止パルスへ JNZ M_STG210 ; 現在 > 上限ならジャンプ ; 現在 < 下限 JZ M_STG250 ; 同一方向なので動作継続 JMP.B M_STG220 ; 逆方向なら停止パルスへ M_STG210: ; 現在 > 上限 JNZ M_STG260 ; 同一方向なので動作継続 ; 逆方向なら停止パルス M_STG220: ; 停止パルス MOV.W ZMBSTP,ZMCSTP ; 停止パルスカウンタセット JSR M_OUT ; 相出力 MOV.B #01,ZMSSTG ; 停止パルス中 STG JMP.B M_STG290 M_STG230: CMP.B #00,ZMBCMD ; 停止リクエスト? JZ M_STG280 ; Yes, 停止パルスへジャンプ JSR M_CMP ; 現在と固定位置を比較 JZ M_STG280 ; *** 一致したら停止パルスへ *** JC M_STG240 ; *** 現在 < 固定位置 *** JZ M_STG250 ; 同一方向なので動作継続 JMP.B M_STG280 ; 逆方向なので停止パルスへ M_STG240: ; *** 現在 > 固定位置 *** JNZ M_STG260 ; 同一方向なので動作継続 JMP.B M_STG280 ; 逆方向なので停止パルスへ M_STG250: ADD.W #1,ZMBPOS ; 現在 現在 +1 JMP.B M_STG270 M_STG260: SUB.W #1,ZMBPOS ; 現在 現在 1 M_STG270: JSR M_OUT ; 出力 JMP.B M_STG290 M_STG280: MOV.W ZMBSTP,ZMCSTP ; 停止パルスカウンタセット JSR M_OUT ; 相出力 MOV.B #01,ZMSSTG ; 停止パルス中 STG M_STG290:
;***** 現在位置判定 ***** ; 入力 : ZMBPOS= 現在位置 ; ZMBPSK= 固定位置 ; ZMBPSL= 往復下限位置 ; ZMBPSH= 往復上限位置 ; 出力 : 固定位置 Z=1 : 一致 ; Z=0,C=1: 現在 > 固定位置 ; Z=0,C=0: 現在 < 固定位置 ; 往復 R0L=00 : 範囲内 ; 01 : 下限と一致 ; 02 : 上限と一致 ; 03 : 現在 < 下限 ; 04 : 現在 > 上限 M_CMP: CMP.B #02,ZMBCMD ; 往復動作? JNZ M_CMP50 ; ***** 往復動作 ***** CMP.W ZMBPSL,ZMBPOS ; 現在と下限を比較 JNZ M_CMP10 MOV.B #01,R0L ; *** 下限と一致 *** M_CMP10: JC M_CMP20 MOV.B #03,R0L ; *** 現在 < 下限 *** M_CMP20: CMP.W ZMBPSH,ZMBPOS ; 現在と上限を比較 JNZ M_CMP30 MOV.B #02,R0L ; *** 上限と一致 *** M_CMP30: JC M_CMP40 MOV.B #00,R0L ; *** 範囲内 ( 下限 < 現在 < 上限 ) *** M_CMP40: MOV.B #04,R0L ; *** 現在 > 上限 *** M_CMP50: CMP.W ZMBPSK,ZMBPOS ; 現在と固定位置を比較 M_CMP90: ;***** 相出力 ***** M_OUT: MOV.W ZMBPOS,A0 AND.W #0007,A0 ; 相は下位 3ビット有効 FCLR I ; 相出力変更作業中は割り込み禁止 MOV.B p1,r0l AND.B #11110000b,R0L OR.B Q_SOU:16[A0],R0L MOV.B R0L,p1 FSET I ポートの割り当てを変更した場合は修正が必要です Q_SOU: ; 下位 4ビット使用.BYTE 00000011b ; 相 0.BYTE 00000010b ; 相 1.BYTE 00000110b ; 相 2.BYTE 00000100b ; 相 3.BYTE 00001100b ; 相 4.BYTE 00001000b ; 相 5.BYTE 00001001b ; 相 6.BYTE 00000001b ; 相 7