Raspberry Pi Pico Wを使用してステッピングモータを駆動する実験をしました。プログラミングツールとしてはArduino IDEを使用しました。Arduino言語にはステッピングモータを駆動する関数としてStepperライブラリがありますが、最初は使用しないでプログラムを作成しました。また、Stepperライブラリーを使用した場合のプログラムも作成しました。
使用ステッピングモータ
ステッピングモータは28BYJ-48とそのドライバーボードのセットを使用しました。このステッピングモータとドライバーボードは複数のネット通販から購入することが出来ます。とにかく価格が安いので使用してみました。
今回使用したステッピングモータの主な仕様は表1の通りです。このモータは1/64のギアで減速されていて、1-2相励磁の場合にステップ角は5.625°/64なので4096ステップでモータ軸が1回転します。最大自起動周波数が500ppsなので、500パルス/sec以下で起動する必要があります。起動後は徐々に加速を行った場合に、最大で1000パルス/secまでは仕様上は可能と思われます。
項目 | 仕様 |
相数 | 4相 |
励磁方式 | 1-2相励磁方式 |
ステップ角 | 5.625°/64 (減速比1/64) |
電圧 | 5VDC |
相抵抗 | 22Ω ± 7% 25°C |
最大応答周波数 | 1000pps |
最大自起動周波数 | 500pps |
引き込みトルク | 800gf.cm / 5VDC 400pps |
ステッピングモータとドライバーボードの回路
ステッピングモータ28BYJ-48に関しては仕様書が有りましたが、ドライバーボードに関しては資料が無かったので、回路をテスターを使用して調べました。図1に調べたステッピングモータ28BYJ-48とドライバーボードの接続回路を示します。
ドライバーボード内のULN2003ANはダーリントントランジスタアレーで定格で500mAの電流を出力することが出来ます。ステッピングモータの赤線がコモン線で5Vに接続されています。外部接続コネクタとステッピングモータコイル線の関係は以下の通りです。
IN1をHIGH(3.3V)とした時にステッピングモータの赤線と青線に接続されたコイルに電流が流れます。
IN2をHIGH(3.3V)とした時にステッピングモータの赤線と桃線に接続されたコイルに電流が流れます。
IN3をHIGH(3.3V)とした時にステッピングモータの赤線と黄線に接続されたコイルに電流が流れます。
IN4をHIGH(3.3V)とした時にステッピングモータの赤線と橙線に接続されたコイルに電流が流れます。
ステッピングモータの駆動に関して
今回使用したステッピングモータ28BYJ-48は1-2相励磁の場合、8ステップでモータのコイルの励磁を切り替えて駆動します。4096ステップでモータが1回転します。ドライバーボードの外部接続コネクタの信号ピン(IN1~IN4)から見た励磁の順番を28BYJ-48の仕様書から以下に作成しました。本表から分かるように1相励磁と2相励磁を繰り返すので1-2相励磁と呼びます。この順にIN1~IN4の信号線を制御すればステッピングモータを回転させることが出来ます。
ボードピン | モータ線 | ステップ1 | ステップ2 | ステップ3 | ステップ4 | ステップ5 | ステップ6 | ステップ7 | ステップ8 |
IN1 | 青 | LOW | LOW | LOW | LOW | LOW | HIGH | HIGH | HIGH |
IN2 | 桃 | LOW | LOW | LOW | HIGH | HIGH | HIGH | LOW | LOW |
IN3 | 黄 | LOW | HIGH | HIGH | HIGH | LOW | LOW | LOW | LOW |
IN4 | 橙 | HIGH | HIGH | LOW | LOW | KIW | LOW | LOW | HIGH |
テスト装置回路図
マイコンとして価格の安いRaspberry Pi Pico Wを使用しました。ステッピングモータのドライバーボードの外部接続コネクタのIN1~IN4をRaspberry Pi Pico WのGP0~GP3に接続しました。またGP15にモータ回転スタート用のスイッチを接続しました。
図2にテスト装置回路図を示します。
プログラムNo.1 (Stepperライブラリ使用無)
Raspberry Pi Pico Wのプログラム開発ツールとして、Arduino IDEを使用しました。
Arduino言語にはステッピングモータを制御するStepperライブラリーがありますが1-2相励磁方式に対応してないので、Stepperライブラリを使用しないで1-2相励磁駆動のプログラムを作成しました。
このプログラムはGP15に接続されたスイッチをONすると、ステッピングモータが1024ステップ(90°)回転します。
全プログラムを4個に分割して説明します。
1.初期処理 setup()関数
setup()関数で各種初期設定をしています。
int motor_stepはステッピングモータのステップ値(表2のステップ1~ステップ8)を1~8の数値で記憶する変数です。
pinMode(15, INPUT_PULLUP)関数で起動用のスイッチをPG15に割り当てています。
pinMode()関数でステッピングモータのドライバーボードの入力信号IN1~IN4をGP0~GP3に割り当てています。
stepMoterOn()関数でステッピングモータの初期励磁をしています。最初はどのステップに居るのか分からないのですが、とりあえずステップ1で励磁しています。stepMoterOn()関数に関しては後項で説明します。
//------Raspberry Pi Pico W ステッピングモータ駆動テストNo.1-------------
int motor_step = 1; //ステップモータのステップ値(1~8)
void setup() {
pinMode(15, INPUT_PULLUP); //GP15を入力端子に設定(スイッチ接続)
pinMode(0, OUTPUT); //ステッピングモータ(IN1 青線)
pinMode(1, OUTPUT); //ステッピングモータ(IN2 桃線)
pinMode(2, OUTPUT); //ステッピングモータ(IN3 黄線)
pinMode(3, OUTPUT); //ステッピングモータ(IN4 橙線)
//ステッピングモータの初期励磁(ステップ1の位置で励磁)
motor_step = stepMoterOn(0, 1, 2, 3);
}
2.メイン処理 loop()関数
loop()関数で実際のステッピングモータの動作を行います。
GP15に接続されたスイッチが押されるまで待ちます。
ステッピングモータを1024ステップ回します。モータは4096ステップで1回転なので90°回転します。
step_1_rot()関数はステッピングモータを1ステップ駆動する関数で、現時点のステップ位置(1~8)を基に次のステップの励磁を導き出してI/Oに出力します。step_1_rot()関数に関しては後項で説明します。
delay(1)関数で1msec待ちをして、次のステップ送りまでの時間を取ります。このdelay()関数でモータの回転速度を決めます。さらに速く回すためにはμsec単位のdelayMicroseconds()関数を使用します。
void loop() {
while (true){
//スイッチ読込(PG15 LOW判断)
if (digitalRead(15) == LOW){
break;
}
}
//1024ステップ回転(1/4回転)
for (int i = 0; i < 1024; i++){
motor_step = step_1_rot(motor_step, true, 0, 1, 2, 3); //CW方向1ステップ回転
delay(1); //1msec待ち
}
}
3.初期位置励磁 stepMoterOn()関数
ステッピングモータを初期励磁としてステップ1の位置に励磁する関数です。GP0:LOW, GP1:LOW, GP2:LOW, GP3:HIGHとして表2のステップ1の励磁形でモータコイルを励磁します。
//------ステッピングモータの初期位置励磁
//引数
//gp_1: 青線用i/o番号
//gp_2: 桃線用i/o番号
//gp_3: 黄線用i/o番号
//gp_4: 橙線用i/o番号
//リターン値: 現状のモータステップ位置番号(1~8)
int stepMoterOn(int gp_1, int gp_2, int gp_3, int gp_4)
{
//ステップ1の位置で励磁
digitalWrite(gp_1, LOW); //GP0 LOW
digitalWrite(gp_2, LOW); //GP1 LOW
digitalWrite(gp_3, LOW); //GP2 LOW
digitalWrite(gp_4, HIGH); //GP3 HIGH
return 1; //ステップ1をリターン
}
4.モータ1ステップ駆動 step_1_rot()関数
ステッピングモータを1ステップ駆動する関数です。
引数として現状のステップを入力して、それに基づいて次のステップの励磁状態を導き出してI/O出力します。
//------ステッピングモータ1ステップ回転処理-------
//引数
//step: モータの現状ステップ位置番号(1~8)
//cw_flag: true:CW方向回転、 false:CCW方向回転
//gp_1: 青線用i/o番号
//gp_2: 桃線用i/o番号
//gp_3: 黄線用i/o番号
//gp_4: 橙線用i/o番号
//リターン値: 移動後のモータステップ位置番号(1~8)
int step_1_rot(int step, bool cw_flag, int gp_1, int gp_2, int gp_3, int gp_4)
{
int ret_step; //リターンステップ番号
//モータのステップ位置判断
switch(step)
{
case 1: //ステップ1
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, LOW); //GP0 OFF
digitalWrite(gp_2, LOW); //GP1 OFF
digitalWrite(gp_3, HIGH); //GP2 ON
digitalWrite(gp_4, HIGH); //GP3 ON
ret_step = 2; //ステップ2へ
}
else
{
digitalWrite(gp_1, HIGH); //GP0 ON
digitalWrite(gp_2, LOW); //GP1 OFF
digitalWrite(gp_3, LOW); //GP2 OFF
digitalWrite(gp_4, HIGH); //GP3 ON
ret_step = 8; //ステップ8へ
}
break;
case 2:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, HIGH); //GP2 or GP6 ON
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 3; //ステップ3へ
}
else
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, HIGH); //GP3 or GP7 ON
ret_step = 1; //ステップ1へ
}
break;
case 3:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, HIGH); //GP2 or GP6 ON
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 4; //ステップ4へ
}
else
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, HIGH); //GP2 or GP6 ON
digitalWrite(gp_4, HIGH); //GP3 or GP7 ON
ret_step = 2; //ステップ2へ
}
break;
case 4:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 5; //ステップ5へ
}
else
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, HIGH); //GP2 or GP6 ON
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 3; //ステップ3へ
}
break;
case 5:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, HIGH); //GP0 or GP4 ON
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 6; //ステップ6へ
}
else
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, HIGH); //GP2 or GP6 ON
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 4; //ステップ4へ
}
break;
case 6:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, HIGH); //GP0 or GP4 ON
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 7; //ステップ7へ
}
else
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 5; //ステップ5へ
}
break;
case 7:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, HIGH); //GP0 or GP4 ON
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, HIGH); //GP3 or GP7 ON
ret_step = 8; //ステップ7へ
}
else
{
digitalWrite(gp_1, HIGH); //GP0 or GP4 ON
digitalWrite(gp_2, HIGH); //GP1 or GP5 ON
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 6; //ステップ6へ
}
break;
case 8:
if (cw_flag == false) //CCW移動
{
digitalWrite(gp_1, LOW); //GP0 or GP4 OFF
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, HIGH); //GP3 or GP7 ON
ret_step = 1; //ステップ1へ
}
else
{
digitalWrite(gp_1, HIGH); //GP0 or GP4 ON
digitalWrite(gp_2, LOW); //GP1 or GP5 OFF
digitalWrite(gp_3, LOW); //GP2 or GP6 OFF
digitalWrite(gp_4, LOW); //GP3 or GP7 OFF
ret_step = 7; //ステップ7へ
}
break;
}
return ret_step; //移動後のステップ値をリターン
}
プログラムNo.2 (Stepperライブラリ使用)
Arduino言語のStepperライブラリを使用してステッピングモータを駆動するプログラムを作成します。
表3にStepperライブラリの概略を示します。
関数 | 説明 |
Stepper(steps, pin1, pin2, pin3, pin4) | steps: 1回転あたりのステップ数(int) pin1,pin2: モータに接続されているピンの番号 pin3,pin4: 4ピンのモータの場合のピン番号 戻り値: 作成されたインスタンス |
Stepper:setSpeed(rpms) | rpms:モータの回転速度。1分間あたり何回転するかを正の数で設定。(long) step()をコールしたときのスピードをセットする。 |
Stepper:step(steps) | steps:モータが回転する量(ステップ数)。逆回転させる場合は負の値を設定。(int) 回転が終了するまで関数を抜け出ない。 |
Stepperライブラリ使用時の励磁
今回使用したステッピングモータ28BYJ-48は1-2相励磁の場合、1回転4096ステップとなります。ただStepperライブラリのstep()関数は、ソースコードを見る限りでは2相励磁方式です。2相励磁の場合1回転2048ステップとなります。
Stepper(step2, pin1, pin2, pin3, pin4)
関数でI/Oピンを割り振った場合の励磁順序はソースコードを見る限りでは表4の様になっています。
引数 | ステップ1 | ステップ2 | ステップ3 | ステップ4 |
pin1 | HIGH | LOW | LOW | HIGH |
pin2 | LOW | HIGH | HIGH | LOW |
pin3 | HIGH | HIGH | LOW | LOW |
pin4 | LOW | LOW | HIGH | HIGH |
また、ステッピングモータ28BYJ-48の仕様書では1-2相励磁方式の励磁順序の表が載っていますが、それから推測した2相励磁の場合の励磁順序は表5の通りです。(時計方向回り時)
ドライバボード入力 | モータリード線 | ステップ1 | ステップ2 | ステップ3 | ステップ4 |
+ (5V) | リード線色 赤 | 5Vに接続 | 5Vに接続 | 5Vに接続 | 5Vに接続 |
IN1 | リード線色 青 | HIGH | LOW | LOW | HIGH |
IN2 | リード線色 桃 | HIGH | HIGH | LOW | LOW |
IN3 | リード線色 黄 | LOW | HIGH | HIGH | LOW |
IN4 | リード線色 橙 | LOW | LOW | HIGH | HIGH |
以上から次の様にステッピングモータを配線する必要があります。
pin1: リード線色 青 (ドライバボード入力 IN1)
pin2: リード線色 桃 (ドライバボード入力 IN3)
pin3: リード線色 黄 (ドライバボード入力 IN2)
pin4: リード線色 橙 (ドライバボード入力 IN4)
ドライバーボード入力のIN2とIN3がひっくり返っていることに注意が必要です。
最初は、このことに気が付かずにpin2で指定したI/OにIN2をpin3で指定したI/OにIN3を接続した所、step()関数を実行してもステッピングモータは振動するのみで全く回転しませんでした。
プログラム説明
以下にStepperライブラリを使用してステッピングモータを1024ステップ駆動するプログラムを示します。Stepperライブラリを使用しないプログラムと比べると非常に簡単になっています。
stepper()関数でモータの1回転のステップ数とI/Oの接続を設定して、setSpeed()関数で回転スピード(rpm)を設定すれば、step()関数でモータを設定したステップ数駆動することが出来ます。
注意点はstep()関数は2相励磁で動作するので、同じステップ数駆動しても1-2相励磁の場合と比べると2倍の回転角度の移動となります。
また、step()関数は設定したステップ数終了するまで抜け出てこないので、並行して別の処理を行いたい場合には1回のstep()関数でのステップ数を少なくして、繰り返しstep()関数を実施してstep()関数とstep()関数の間に別処理を挿入する等の工夫が必要となります。
//-----Raspberry Pi Pico W ステッピングモータ駆動テストNo.2-----
#include <Stepper.h>
Stepper stepper(2048, 0, 2, 1, 3); //モータNo.1設定(1回転2048ステップ)
void setup() {
pinMode(15, INPUT_PULLUP); //GP15を入力端子に設定(スイッチ接続)
stepper.setSpeed(14); //モータNo1回転スピードを14RPMへ
}
void loop() {
while (true){
//スイッチ読込(GP15 LOW判断)
if (digitalRead(15) == LOW){
break;
}
}
//1024ステップ回転
stepper.step(1024); //モータ回転 (1/2回転)
}
動作動画
以下動画は実際の動作状況です。
最後に
Raspberry Pi Pico Wに1個のステッピングモータを接続して動作させることが出来ました。次は1個のRaspberry Pi Pico Wで2個のステッピングモータを同時に動作させる実験を行いたいと思います。