昨年末の第109回で、Nuvoton社のちと古いNUC120マイコン(Arm Cortex-M0搭載)で28BYJ-48ステッパモータを回してみました。2相励磁で反時計方向だけ。それではいけない、1相励磁とか、1-2相励磁とか、方向逆転とか、一通りやって波形見て置くべし、ということで今回やってみました。本人は(いつも)「一撃」で出来ると思っているのですが、またいろいろあるんだこれが。
目論みといたしましては、第109回の回路に励磁の方式とか回転方向とかを制御するための入力スイッチを加え、ソフトには物理的なスイッチに応じた動作をさせるようにいたしたかったのでございます。スイッチとしては、
- モータのON/OFFを制御するスイッチ
- モータの回転方向(CW/CCW)を制御するスイッチ
- モータの励磁方式を制御するスイッチ
の3種必要。励磁方式は、1相、2相、1-2相励磁と3種あるので、3番目のスイッチ相当のものはは物理スイッチ2個(2ビット)にせざるを得ません。そしてスイッチのON/OFFを「ゆるゆる回っている」メインルーチンで「適宜」読んでやります。読んだ結果は大域変数に反映しているので、それを100分の1秒割り込みハンドラから起動されるモータ制御関数で解釈してやる、という塩梅。
さて励磁のパターンについてですが、私メのような門外漢が説明するのは遠慮しておきます。今回投稿に合致して短くて分かり易い解説は、TDU(東京電機大学)の以下の文書であります。
他にもモータ各社やモータドライバ各社が立派な説明文書を出されていて参考になるのですが、一部はプロ向けですかね。一応リンク貼っておきます。モータ業界の大立者日本電産(NIDEC)技術解説、オリエンタルモータ技術資料、ドライバ視点からは、新日本無線(JRC)ステッピングモータの基本、日本パルスモータ(NPM)ドライブICの制御方式「励磁方式」 などであります。真面目に読んだらきっと詳しくなるのだけれど、ちゃんと読んでいない。。。
さてソフトの実装については、何も難しいことは無い筈、どちらかというと使用させていただいているIARシステムズ社のEWARMの無償環境の上限リミットの方がちょっと気になってました。
結論からいうと、上限リミットなど何の問題もなく、問題あったのは自分のせいでした(何時ものこと。)先に列挙してしまうと、以下の4点ありました。バグは1個ならば直ぐに分かることが多いですが、複数個重なると何やら妖怪変化へと変化しまする。
- スイッチ治具の回路が思っていたのと違っていた
- スイッチの順番を思っていたのと逆につないでしまった
- スイッチ対応にする過程で古いコードの削除忘れた
- 1,2相励磁のパターンのswitch文の中でbreak一つ忘れていた
かなり前に、何のためにか作ったのか忘れた4連装スイッチ治具があったので使うことにいたしました。頭の中に「思い描いていた」回路は左のような感じです。SW1とSW2を励磁方式の選択に、SW3は回転方向選択、そしてSW4でモータのON/OFF制御のつもりです。
しかしね、全然ダメ。上のバグリストのうち2つを踏みました。実際の回路は下のような感じです。なお、この右側にモータ制御の本体回路があるのですが第109回と同じなので省略。
こちらが実物回路。論理は反転。電気的には問題ないですが、スイッチの左右の順番も考えていたのと逆でした。大馬鹿もの。
入力キーを確認するための関数はこちら。ゆるゆると「回っている」メイン関数の中で十分な時間インターバルを開けて呼ばれるのでチャッタ対策など何もしていません。
void inputKey(void) { int32_t keyValue; keyValue = DrvGPIO_GetBit(E_GPA, 8); if (keyValue == 1) { // MOTOR ON motorON = 1; return; } else { // MOTOR OFF motorON = 0; keyValue = DrvGPIO_GetBit(E_GPA, 9); if (keyValue == 1) { // CCW motorCCW = 1; } else { motorCCW = 0; } keyValue = DrvGPIO_GetBit(E_GPA, 11); if (keyValue == 1) { motorMode = MOTOR_P12; } else { keyValue = DrvGPIO_GetBit(E_GPA, 10); if (keyValue == 1) { motorMode = MOTOR_P2; } else { motorMode = MOTOR_P1; } } } }
上記の関数がセットした大域変数を読み取って実際にモータへ出力するパターンを生成している関数の上位層(割り込みハンドラから100分の1秒毎に呼ばれる)がこちら。実際のパターンはこの下の子関数の中に押し込めてあります。
void stepperControl(void) { if (!motorON) { return; } if (motorCCW) { if (stepStatus > MOTOR_PHASE_START) { stepStatus--; } else { stepStatus = MOTOR_PHASE_END; } } else { if (stepStatus < MOTOR_PHASE_END) { stepStatus++; } else { stepStatus = MOTOR_PHASE_START; } } switch(motorMode) { case MOTOR_P1: stepperP1(); break; case MOTOR_P2: stepperP2(); break; case MOTOR_P12: stepperP12(); break; } }
さて、電源入れて起動すれば、スイッチに応じて「回る」ようになりました。あちこちLED入っているのでチカチカしながら回ります。その様子は上の方のアイキャッチ画像を御覧ください。肝心のステッパモータは左下の方で「クリップ」を回しています。新規追加の4連スイッチは左上、Nuvoton NUC120ボードは上の方の紫色ぽいボードで、下のブレッドボードでモータドライバ基板と結線しています。ブレッドボードに刺した電源基板で5Vをモータドライバに与えています。モータドライバは右下に顔を出しております。
ドライブ波形(マイコン出力端子)の観察には、いつものように Digilent社Analog Discovery2の「ロジアナ」モードを使用。
1相励磁CW(時計方向)
上記のように、各信号のアクティブ期間(マイコン端子での値なのでHigh)にオーバラップがない駆動であります。
1相励磁CCW(反時計方向)
回転方向を逆転させると、下のように駆動の順番が逆転します。
2相励磁CW(時計方向)
2相励磁は、第109回でやりました。隣り合う信号のアクティブ期間同士が常にオーバラップするような駆動です。
2相励磁CCW(反時計方向)
2相の反転。これまた簡単。
バグ!12相励磁CCW(反時計方向)
およよ、なんだ、これは、1番上の信号だけ幅が狭いんでないかい。
まあこれが、バグリストの4番目のやつ。1-2相励磁のパターンのswitch文の中のbreakが1個抜けていたというお粗末。
12相励磁CCW(反時計方向)
気御取り直してBUG FIXした波形。上と比べるとその差は明らか、こちらが1-2相励磁。隣同士、互いに被りつつも、単独でアクティブになっている期間もあり、と。
12相励磁CW(時計方向)
BUGさえ直せば、方向反転は簡単。
まあ、今回は、全ての励磁方法でパターンの周期は80msで同じにしているので同じ速さで回っていますが、その中で8ステップ必要な1-2相励磁にくらべ、1相と2相は4ステップで行けるので、ステップ時間一定にすれば1、2相は倍速になる筈。
しかしな、「泣く子とBUGには勝てぬ。」