別シリーズで2回ほど28BYJ-48ステッピングモータを扱いましたが、Arduinoで制御していたので、肝心の波形はArduinoのライブラリ次第。こちらではNuvoton NUC120ボードを使って「下回り」から操作して波形を操作して様子を見てみようというわけです。PWM駆動もやるつもりですが、まずはタイマの周期割り込みでArduino同様の2相励磁でモータが回るところから。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
今回使用するマイコンボードは、ちょっと引っかかっていた 台湾 Nuvoton社のArm Cortex-M0搭載のちょっと古いマイコンNUC120のボードです。何で気になっていたかというとNUC120の開発用にIAR社のEWARM環境をインストールした時に、古いインストーラ上では無償のお試し「ライセンスは30日限定」みたいな表示がでていたためです。しかしIAR社からダウンロードできた今年のライセンスファイル上はライセンス期間の縛りなど無いも同然に見えました。すでにインストール以来約1か月半経過。画面表示が正しければ、今回28BYJ-48ステッパモータのために書いたプログラムはビルドできないでしょう。
ビルドできました。
よかった。無償のお試しライセンスは容量制限ありなのでprintfなどまず使えませんが、モータの波形テストくらいは十分にできると。
さて、別シリーズでの混乱もあり、今回はちゃんと回路図を書いておくことにいたしました。例によって軽くて楽な「水魚堂さん」エディタであります。とはいえ、Nuvoton NUC120の部品は登録されていないので自分で作りました。高々48ピンとは言え、部品登録は結構辛い。とりあえず
モータ制御に関係しておる経路のみの回路
Arduinoと違うのは、Pin番号通りに素直に結線していること。自分で波形を定義しているので何とでもなるので。ソフトウエア上見えるところは、
-
- ソフト動作中確認表示のLED接続、PIN19(PB2), PIN20(PB3)
- モータ制御端子、 PIN21(PC3)、PIN22(PC2)、PIN23(PC1)、PIN24(PC0)
いずれもGPIOとして制御します(今回はPWMは使いませぬ。)
使用するライブラリと、割り込みハンドラの中で操作する大域変数はこちら。一応、UARTドライバを組み込んでも容量的にはOKだったですが、結局使いませんでした。IARの環境からはオンボードのデバッガが使えるので不自由しませぬ。
#include <stdio.h> #include "NUC1xx.h" #include "Driver\DrvSYS.h" #include "Driver\DrvGPIO.h" #include "Driver\DrvUART.h" volatile uint32_t sTicks = 0; volatile uint32_t stepCounter = 0; volatile uint32_t stepStatus = 0;
SysTick割り込みの「ハンドラ」がこちら。後で設定が出てきますが、SDK使うとこの関数が本当の割り込みハンドラから呼び出されるようです。
void SysTick_Handler(void) { sTicks++; stepperP2(); }
上のハンドラが呼び出される度(10ms毎)にモータの制御波形を作る関数がこちら。べたな2相励磁の波形。別投稿のArduinoではステップ5ms設定だったので速度は半分。波形は相似。Arduinoであれば出来合いの関数を呼び出すだけが、自力で書くと面倒です。しかし、ここを変更すれば1相励磁、1-2-1相励磁など各種対応もできる筈。
void stepperP2(void) { if (stepCounter-- > 0) { switch (stepStatus++) { case 0: DrvGPIO_ClrBit(E_GPC,0); DrvGPIO_SetBit(E_GPC,1); DrvGPIO_SetBit(E_GPC,2); DrvGPIO_ClrBit(E_GPC,3); break; case 1: DrvGPIO_ClrBit(E_GPC,0); DrvGPIO_ClrBit(E_GPC,1); DrvGPIO_SetBit(E_GPC,2); DrvGPIO_SetBit(E_GPC,3); break; case 2: DrvGPIO_SetBit(E_GPC,0); DrvGPIO_ClrBit(E_GPC,1); DrvGPIO_ClrBit(E_GPC,2); DrvGPIO_SetBit(E_GPC,3); break; case 3: DrvGPIO_SetBit(E_GPC,0); DrvGPIO_SetBit(E_GPC,1); DrvGPIO_ClrBit(E_GPC,2); DrvGPIO_ClrBit(E_GPC,3); break; } if (stepStatus > 3) { stepStatus = 0; } } }
さて、メイン関数がこちら、クロックの指定とGPIOの初期化をした後は、ソフトウエアのループで、外部のLED2つ(赤と緑)を交互に点灯させるだけのもの。初期設定のSysTick_Configで SystemCoreClock / 100 と100で割った周波数(カウント値)をセットしているのでSysTick割り込みは100Hzとなります。200Hzにしたければ200で割ればよい筈。モータ駆動はハンドラに任せているので、メインプログラムはポートの初期化のみ。
int main (void) { UNLOCKREG(); DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); /* Enable 12MHz EXT. OSC. */ DrvSYS_Delay(5000); /* wait 12MHz. Delay by SysTick timer */ SystemCoreClockUpdate(); /*set GPIOs output*/ DrvGPIO_Open(E_GPB,2, E_IO_OUTPUT); DrvGPIO_Open(E_GPB,3, E_IO_OUTPUT); DrvGPIO_Open(E_GPC,0, E_IO_OUTPUT); DrvGPIO_Open(E_GPC,1, E_IO_OUTPUT); DrvGPIO_Open(E_GPC,2, E_IO_OUTPUT); DrvGPIO_Open(E_GPC,3, E_IO_OUTPUT); SysTick_Config(SystemCoreClock / 100); while(1) { DrvGPIO_ClrBit(E_GPB,2); DrvGPIO_SetBit(E_GPB,3); delay_loop(); DrvGPIO_SetBit(E_GPB,2); DrvGPIO_ClrBit(E_GPB,3); delay_loop(); } }
Arduinoと相似な2相励磁(速度は半分)でモータ回りました。その様子がアイキャッチ画像に。