今回はステッピングモータの概要と制御方法について学んでゆきます。
ステッピングモータの制御~ULN2003APG
前回はこちらです

ステッピングモータ
ステッピングモータは、パルスモータ、ステップモータ、ステッパーモータとも呼ばれ、プリンタのヘッド移動やスロットマシンのリール制御、3Dプリンタのヘッド移動などに使用されています。
本実験では、ROHS社の「28BYJ-48」を使用します。
https://akizukidenshi.com/catalog/g/g113256/

基本原理
ステッピングモータは、4本または6本の配線が接続されており、入力されたパルス電力によって回転します。
DCモータとは異なり、ステッピングモータは単純に電圧をかけるだけでは回転しません。
そのため、ステッピングモータの駆動・制御には、必ずドライバ回路が必要です。
ステッピングモータは、入力されたパルス数に比例した角度だけ回転するため、細かな回転角の制御が可能です。
特徴
- ステップ角:モータの構造によって、1パルスで回転する角度が決まっています。例えば、40度回転させたい場合は、40度をステップ角で割った数だけパルスを送ります。
- 保持トルク:停止時にも一定のトルクがあり、小さな力では軸が回転しません。
- 位置制御:入力されたパルス数に比例して回転するため、位置決めの誤差が累積しません。
- 角速度制御:入力されたパルスの周波数に比例して回転速度が変化します。
- オープンループ制御:センサーを使わずに制御が可能です。
配線と駆動回路
ステッピングモータにはバイポーラ結線とユニポーラ結線があり、制御方法が異なります。
バイポーラ結線
- 特徴:電流の流れる方向を変更する必要があるため、Hブリッジが2セット使用されます。
- 駆動回路:複雑ですが、高いトルクと効率が得られます。

ユニポーラ結線
- 特徴:駆動回路が単純で、バイポーラよりも簡単に制御できます。
- 駆動回路:トランジスタやMOSFETを用いた簡単な回路で駆動できます。
- 本実習:ユニポーラ式のステッピングモータの駆動回路を実装します。

ステッピングモータの制御例
- 40度回転:ステップ角が5度の場合、40度÷5度=8パルスを送信します。
- 角速度制御:パルスの周波数を変えることで、回転速度を制御します。
ユニポーラ結線ステッピングモータの駆動回路
ステッピングモータの駆動方法には、オンにする電磁石の組み合わせによって以下の3種類の制御方法があります:
1相励磁(1相駆動)
- 特徴:1つの電磁石のみを駆動させる制御方法。
- メリット:消費電力が小さい。
- デメリット:トルクも小さい。

2相励磁(2相駆動)
- 特徴:2つの電磁石を同時に駆動させる制御方法。
- メリット:トルクが大きい(1相励磁と比較して√2倍のトルク)。
- デメリット:消費電力が大きく、発熱も大きくなる。

1-2相励磁
- 特徴:1相励磁と2相励磁を交互に行う制御方法。
- メリット:分解能が倍になる。
- デメリット:トルクが脈動してしまう。

マイクロステップ
- 特徴:モータの励磁電流を0と1ではなく、無段階のサイン波で駆動する手法。
- メリット:高分解能、静寂性、高回転が可能。
駆動回路の動作
駆動回路が1秒間に発するパルスの回数を「パルスレート」または「パルス周波数」といいます。パルスレートが高すぎたり、負荷トルクが大きすぎたりするとモータを始動させることができません。このときの始動できるトルクの大きさを「引込トルク」といい、パルスレートに依存します。
- 最大自起動周波数:始動できるパルスレートの上限。
- 最大連続応答周波数:運転できるパルスレートの上限。
駆動回路の作成
市販のステッピングモータドライバを使用すると手軽に駆動できます。
ステッピングモータへのスイッチングは電流が多く流れる為、直接行うことが出来ません。
今回はArduinoキットに含まれている、ULN2003APGという回路を使用します。

ULN2003APGのデータシート
https://www.tyro-teq.com/show_datasheet?path=/ds/pdf/u/0094/ULN2003APGSCHZ.pdf

この回路はIN1~IN4のデジタル入力の状況によって、モータの出力をそれぞれON,OFFを切り替えてくれます。
この回路の電源はマイコンからではなく、別途電池や安定化電源で供給しましょう。
配線例はは以下の通り行います。

制御プログラム
無限に正転を行うプログラムを下記に示します。
Pico ULN2003基板
─────────────────────────
GP10 ───→ IN1
GP11 ───→ IN2
GP12 ───→ IN3
GP13 ───→ IN4
GND ───→ GND
+5V ←── 外部電源
モータコネクタ ──→ 28BYJ-48# ============================================
# ステッピングモータ 28BYJ-48 を回すプログラム
# ============================================
from machine import Pin
from time import sleep_ms
# IN1〜IN4のピン設定
IN1 = Pin(10, Pin.OUT)
IN2 = Pin(11, Pin.OUT)
IN3 = Pin(12, Pin.OUT)
IN4 = Pin(13, Pin.OUT)
# 励磁パターン(2相励磁・4ステップ)
# 1ステップごとに IN1〜IN4 をこの順番でON/OFFする
seq = [
[1, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 1],
[1, 0, 0, 1],
]
# 回転速度(数字を小さくすると速くなる、単位:ミリ秒)
v = 2
# メインループ:ずっと正転し続ける
while True:
# 4つのパターンを順番に出力する
for pattern in seq:
IN1.value(pattern[0])
IN2.value(pattern[1])
IN3.value(pattern[2])
IN4.value(pattern[3])
sleep_ms(v)仕様書によると今回使用したモータは減速機も内蔵されており、1-2相励磁で制御した場合は1パルスで5.625/64=0.087890625°回転します。
つまり4096ステップで1回転することになり、
上記のプログラムは1相励磁で1ループで4ステップの出力が行われる為、512ループで1回転します。
送るパルスは早すぎるとモーター側の回転が追い付かなくなり、1周回りきらなくなる場合があるので注意が必要です。
課題12
ステッピングモータとドライバ回路を使用し、プッシュスイッチ1を押すと右に1回転、2を押すと左に1回転するプログラムを作成せよ。
解答例はこちら
配線(追加分)
| 部品 | Picoのピン |
|---|---|
| プッシュスイッチ1:片側 | GP14 |
| プッシュスイッチ1:もう片側 | GND |
| プッシュスイッチ2:片側 | GP15 |
| プッシュスイッチ2:もう片側 | GND |
# ============================================
# プッシュスイッチでステッピングモータを回す
# SW1を押す → 右に1回転
# SW2を押す → 左に1回転
# ============================================
from machine import Pin
from time import sleep_ms
# モータ用のピン設定(IN1〜IN4)
IN1 = Pin(10, Pin.OUT)
IN2 = Pin(11, Pin.OUT)
IN3 = Pin(12, Pin.OUT)
IN4 = Pin(13, Pin.OUT)
# プッシュスイッチのピン設定(内部プルアップ使用)
sw1 = Pin(14, Pin.IN, Pin.PULL_UP)
sw2 = Pin(15, Pin.IN, Pin.PULL_UP)
# 正転用の励磁パターン(2相励磁)
seq_forward = [
[1, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 1],
[1, 0, 0, 1],
]
# 逆転用の励磁パターン(順番を逆にしたもの)
seq_reverse = [
[1, 0, 0, 1],
[0, 0, 1, 1],
[0, 1, 1, 0],
[1, 1, 0, 0],
]
# 回転速度(数字を小さくすると速くなる)
v = 2
# 1回転に必要なステップ数(2相励磁:512回×4ステップ)
STEPS_PER_REV = 512
# --------------------------------------------
# モータを1回転させる関数
# --------------------------------------------
def rotate_one_turn(seq):
# 512回、パターンを繰り返す
for _ in range(STEPS_PER_REV):
# 4ステップのパターンを順番に出力
for pattern in seq:
IN1.value(pattern[0])
IN2.value(pattern[1])
IN3.value(pattern[2])
IN4.value(pattern[3])
sleep_ms(v)
# --------------------------------------------
# メインループ
# --------------------------------------------
while True:
# スイッチ1が押されたら正転で1回転
if sw1.value() == 0:
print("右に1回転")
rotate_one_turn(seq_forward)
# スイッチ2が押されたら逆転で1回転
if sw2.value() == 0:
print("左に1回転")
rotate_one_turn(seq_reverse)
# CPU負荷軽減のため少し待機
sleep_ms(10)次回はこちら

