ステッピングモーターを使う案件が来た。
ステッピングモーターは6本線が普通だと思っていたら、今回使うサンプルを見たら4本線だった。あれ?こんなのあるんだと初めて知った。
どうやって動かすの?と調べたらステッピングモーターにはユニポーラ駆動とバイポーラ駆動とか他にも2相じゃなくて3相、5相とかあるんですね。ふむむ。
とりあえず回路を作ろうと思ったが簡単な回路だとトランジスタ8個使うことになる…。複雑になりそうだ。ということでドライバICを使うことにした。
秋月電子通商さんで TA7774FG を発見。これだと入力端子に交互にパルスを入れてやれば回せるのでお手軽だなと選択し購入。
あとはモーターの制御。最終的にパソコンで制御したいらしいので、間に PIC を入れて制御しやすくしておいた。使ったのはPIC12F675。8本足のやつです。
ざっくりとPIC は GP0 ~ GP2 を出力、GP3 ~ GP5 を入力に設定。
ADC は未使用。内部発振。GP5 の IOポート割り込み有り。で設定。
動作は GP3 の状態を反転して GP2 へ。
GPIO の変化を検知して割り込み実行。
GP5 に入る負理論パルスを正理論に変換してドライバICへ伝達。
このとき GP4 の状態によりA,B チャネルのパルスの流れを反転。
という感じの仕様で作りました。
今回、割り込みを自分で組んだものでは初めて使ってみたけど意外と便利。使えるときは使っていこう。
プログラムは楽勝だ~とさくっと作成したら、いきなり2カ所ほどポカミスをやらかしました。
GP3 は入力のみだということを忘れて出力設定にしたら動かなかったという単純ミス。
プルアップの設定は wpu レジスタだけじゃなくて option レジスタの NOT_GPPU ビットを 0 にしないと有効にならないということ。
なんとまぁ。
そんなこんなで、間違いはあったけどPICは意図した動作をきちんとしてる。のだが、モーターを回すと回っているけどカクカク…?。
原因調査。
まずはモーターメーカーの制御ボードで実験。めっちゃスムーズに回る。原因はモーターではない。
次はドライバIC の特性なのか。ということで、発信器があったら良かったけどないので、PIC でパルス発生のプログラム書いて送信してみた。これも評価ボードほどではないけどスムーズに回る。
結論。パソコンが悪い。VEEでパソコンから制御パルス送っているのだけれどもどうやらこれがくせ者らしい。おそらく、VEE のデバッグモードだと割り込みやらなんやらでウェイトがきちんと動作しないようでこれが原因っぽい。
はじめは自作PIC-CDCのデジタルIOでカクカク動作だったのでメーカーもののDIOだと大丈夫かなと思ったがやはりダメっぽい。ランタイムにして動作させればもしかしたらうまく動くかもしれないが、パソコン制御は別担当なので、また後日その辺試してもらおう。
パルスも PIC 制御しなきゃダメなのかな。それの方が面白いけど。ちょっと期待。
一応、ソースコード。続きを読む以降に貼っておきました。
SourceBoost の BoostC 使ってます。どれもまあ似たようなものかと。
#include <system.h>
#include <stdio.h>
#include <pic12f675.h>
#include "..\\libs\\user_utils.h"
//
// _CONFIG PowerUP Timer-OFF, WDT-OFF, INT-OSC
// GP3 Digital I/O(MCLRE Off)
#pragma DATA _CONFIG, _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
void interrupt( void );
void configure_system( void );
void m_pulse_gen( uns8 fr_flag );
uns8 p_count = 1;
void interrupt( void )
{
if( intcon.GPIF == 1 )
{
intcon.GIE = 0; // Interrupt Off
if( gpio.GP5 == 0 )
{
m_pulse_gen( gpio.GP4 );
}
intcon.GPIF = 0;// Flag Clear
intcon.GIE = 1; // Interrupt On
}
}
void configure_system()
{// setting pic configure_system
cmcon = 0b00000111; // Comparator Mode Off
ansel = 0b00000000; // ADCS:Fosc/2, Digital I/O;
adcon0 = 0b10000000; // adcon off
option_reg.NOT_GPPU = 0;// GPIO pull-ups are enabled by individual port latch values
intcon.GPIE = 1; // Port Change interrupt Enable
intcon.GPIF = 0; // Port Change interrupt Flag Clear
trisio = 0b11111000; // PORT| --- --- In- In- In- Out Out Out (bit set)
gpio = 0b11111111; // gpio| --- --- --- --- --- --- --- ---
wpu = 0b11111111; // WPU | --- --- ena ena --- ena ena ena (Weak Pull-UP Register)
ioc = 0b11100000; // IOC | --- --- ena dis dis dis dis dis (Interrupt On Change)
}
void m_pulse_gen( uns8 fr_flag )
{
if( fr_flag == 1 )
{
switch( p_count )
{
case 1: gpio.GP0 = 1; p_count = 2; break;
case 2: gpio.GP1 = 1; p_count = 3; break;
case 3: gpio.GP0 = 0; p_count = 4; break;
case 4: gpio.GP1 = 0; p_count = 1; break;
default: break;
}
}
else
{
switch( p_count )
{
case 1: gpio.GP1 = 1; p_count = 2; break;
case 2: gpio.GP0 = 1; p_count = 3; break;
case 3: gpio.GP1 = 0; p_count = 4; break;
case 4: gpio.GP0 = 0; p_count = 1; break;
default: break;
}
}
}
void main()
{
delay_ms(250);
configure_system();
gpio.GP0 = 0;
gpio.GP1 = 0;
gpio.GP2 = 0;
delay_ms(250);
intcon.GIE = 1; // Interrupt On
while(1)
{
gpio.GP2 = 1 - gpio.GP3; // motor power on/off
}
}