XYテーブル製作シリーズ 第6回
はじめに:X軸とY軸を「同時に」動かして斜め移動する
前回まではX軸単体・Y軸単体を動かしてきました。XYテーブルとして図形を描いたり位置決めするには、XとYを同時に動かして斜め移動する必要があります。今回はPythonの threading(スレッド)で2つのモーターを同時に動作させる方法を解説します。
この記事で分かること
threading.ThreadでX軸スレッド・Y軸スレッドを同時に起動する仕組み- 軸ごとにピンをまとめて渡し、加減速付きで動かす
run_motor() - X軸50mm・Y軸30mm を同時に動かして斜め移動を実現するフルコード
- A4988ドライバー2台のGPIOピン配置と結線図
ハードウェア構成とGPIOピン設定
| 部品 | 型番 |
|---|---|
| マイコン | Raspberry Pi 3 Model A+ |
| モータードライバ ×2 | A4988 |
| モーター ×2 | NEMA17 |
| 電源 | 12V 5A |
GPIOピン配置
# X軸
X_STEP = 21 X_DIR = 20 X_EN = 16
X_MS1 = 17 X_MS2 = 27 X_MS3 = 22
X_RESET = 5 X_SLEEP = 6
# Y軸
Y_STEP = 2 Y_DIR = 26 Y_EN = 18
Y_MS1 = 23 Y_MS2 = 24 Y_MS3 = 25
Y_RESET = 12 Y_SLEEP = 13
結線であると便利なもの:
Pythonのthreadingで2軸を同時制御する
Pythonの threading を使うと複数の処理を同時に動かせます。今回のプログラムではX軸スレッドとY軸スレッドを同時に起動し、tx.join() / ty.join() で両方の完了を待ちます。run_motor() には第5回の加減速(台形駆動)も組み込んでいます。
import RPi.GPIO as GPIO
import time
import threading
GPIO.setmode(GPIO.BCM)
# -------------------------
# X軸
# -------------------------
X_STEP = 21
X_DIR = 20
X_EN = 16
X_MS1 = 17
X_MS2 = 27
X_MS3 = 22
X_RESET = 5
X_SLEEP = 6
# -------------------------
# Y軸
# -------------------------
Y_STEP = 2
Y_DIR = 26
Y_EN = 18
Y_MS1 = 23
Y_MS2 = 24
Y_MS3 = 25
Y_RESET = 12
Y_SLEEP = 13
# -------------------------
# モーション設定
# -------------------------
BELT_PITCH = 2.0
PULLEY_TEETH = 32
MM_PER_REV = BELT_PITCH * PULLEY_TEETH
FULL_STEPS = 200
MICROSTEP = 16
STEPS_PER_REV = FULL_STEPS * MICROSTEP
STEPS_PER_MM = STEPS_PER_REV / MM_PER_REV
ACC_DEC_STEPS = 100
# -------------------------
# GPIO初期化
# -------------------------
def gpio_init_axis(STEP, DIR, EN, MS1, MS2, MS3, RESET, SLEEP):
pins = [STEP, DIR, EN, MS1, MS2, MS3, RESET, SLEEP]
for p in pins:
GPIO.setup(p, GPIO.OUT)
GPIO.output(RESET, GPIO.HIGH)
GPIO.output(SLEEP, GPIO.HIGH)
GPIO.output(MS1, GPIO.HIGH)
GPIO.output(MS2, GPIO.HIGH)
GPIO.output(MS3, GPIO.HIGH)
GPIO.output(EN, GPIO.LOW)
# -------------------------
# 加減速計算
# -------------------------
def get_intervals(total_steps, acc_steps, total_time):
const_steps = max(total_steps - acc_steps*2, 1)
total_ratio = acc_steps*0.5 + const_steps + acc_steps*0.5
base_interval = total_time / total_ratio / 2
intervals = []
for i in range(acc_steps):
intervals.append(base_interval*(acc_steps-i)/acc_steps)
for i in range(const_steps):
intervals.append(base_interval)
for i in range(acc_steps):
intervals.append(base_interval*(i+1)/acc_steps)
return intervals
# -------------------------
# モーター制御
# -------------------------
def run_motor(axis_name,
STEP, DIR, EN,
MS1, MS2, MS3,
RESET, SLEEP,
distance_mm, cycles):
print(axis_name,"開始")
gpio_init_axis(STEP,DIR,EN,MS1,MS2,MS3,RESET,SLEEP)
steps = int(distance_mm * STEPS_PER_MM)
intervals = get_intervals(steps, ACC_DEC_STEPS, 1.5) # 1.5秒で加減速込みの移動を完了させる
for c in range(cycles):
# 正転
if axis_name == "X軸":
GPIO.output(DIR,GPIO.LOW)
else:
GPIO.output(DIR,GPIO.HIGH)
for t in intervals:
GPIO.output(STEP,GPIO.HIGH)
time.sleep(t)
GPIO.output(STEP,GPIO.LOW)
time.sleep(t)
# 逆転
if axis_name == "X軸":
GPIO.output(DIR,GPIO.HIGH)
else:
GPIO.output(DIR,GPIO.LOW)
for t in intervals:
GPIO.output(STEP,GPIO.HIGH)
time.sleep(t)
GPIO.output(STEP,GPIO.LOW)
time.sleep(t)
GPIO.output(EN,GPIO.HIGH)
print(axis_name,"終了")
# -------------------------
# XY同時スタート
# -------------------------
def start_both():
x_dist = 60 # 移動距離(mm)
x_cycle = 1 # 移動回数
y_dist = 30 # 移動距離(mm)#
y_cycle = 2 # 移動回数
tx = threading.Thread(
target=run_motor,
args=("X軸",
X_STEP, X_DIR, X_EN,
X_MS1, X_MS2, X_MS3,
X_RESET, X_SLEEP,
x_dist, x_cycle)
)
ty = threading.Thread(
target=run_motor,
args=("Y軸",
Y_STEP, Y_DIR, Y_EN,
Y_MS1, Y_MS2, Y_MS3,
Y_RESET, Y_SLEEP,
y_dist, y_cycle)
)
tx.start()
ty.start()
tx.join()
ty.join()
# -------------------------
# 実行
# -------------------------
try:
start_both()
finally:
GPIO.cleanup()python3 XY_both_move.pyX軸とY軸が同時に動作し、斜め移動が実現できます。
まとめと次回予告
threadingでX軸・Y軸を同時に動かせるようになりました。ただしこのままでは「現在位置が分からず、安全制御がない」状態です。次回・第7回では、リミットスイッチと原点復帰(Homing)を実装します。
次に読む記事
🏠 次回はこちら(第7回) Raspberry Pi+PythonでXYテーブルの原点復帰(Homing)を実装|リミットスイッチ・バックオフ処理 電源ON→原点復帰→動作開始という実用的な制御へ。 → 📈 前回(第5回) ステッピングモーターの脱調を防ぐ加減速制御(台形駆動)をPythonで実装する方法 run_motor に組み込んだ加減速のしくみ。 → 🗺️ 全体像 自作XYテーブルの全手順ロードマップ|Raspberry Pi+ステッピングモーターで2軸制御 第0回〜第11回の全工程をまとめたロードマップ。 →よくある質問(FAQ)
Qthreading を使うと本当に「同時」に動きますか?
AOSレベルではX軸・Y軸のスレッドが並行して実行され、体感上は同時に動きます。ただしPythonのGIL(グローバルインタプリタロック)の影響で厳密な同時刻ではありません。ステップパルスの間隔が μ秒単位でずれることはありますが、XYテーブルの位置決め用途では実用上問題ありません。
Q斜め移動で直線がガタつきます(きれいな斜線にならない)。
AX軸とY軸を独立に動かすと、移動距離の短い軸が先に止まり「L字」に近い軌跡になります。きれいな斜線には、両軸の移動時間を合わせる(速い軸を遅くする)か、1ループ内で両軸のパルスをBresenhamアルゴリズムで配分する直線補間が必要です。
Q片方のモーターだけ動きません/逆に回ります。
AGPIOピンの割り当てミス、EN ピンが HIGH のまま(LOWで有効)、コイル配線の相違いが主な原因です。逆回転は run_motor 内で軸名により DIR を切り替えるか、配線でコイルのペアを入れ替えます。
Qスレッド実行後にプログラムが終了しません。
Atx.join() / ty.join() で両スレッドの完了を待ってから finally の GPIO.cleanup() に進みます。daemon=True にしたスレッドはメインが終わると強制終了されるので、確実に動かし切りたい処理では join() を使います。
XYテーブル製作シリーズ(全12回)
- Raspberry Pi ImagerでのOSインストール手順|microSD書き込みから初期設定まで
- ラズパイでLチカ|PythonとRPi.GPIOでLEDを点灯・点滅させる方法
- ラズパイでステッピングモーターを回す方法|A4988の配線とPython制御・Vref調整
- ステッピングモーターをmm単位で動かす計算式とPython実装|step/mmの求め方
- PythonでX軸・Y軸のステッピングモーターを2軸制御する方法|A4988ドライバー2台
- ステッピングモーターの脱調を防ぐ加減速制御(台形駆動)をPythonで実装する方法
- Raspberry PiでXYテーブルを2軸同時制御|Pythonのthreadingでステッピングモーターを同時に動かす(この記事)
- Raspberry Pi+PythonでXYテーブルの原点復帰(Homing)を実装|リミットスイッチ・バックオフ処理
- PythonのTkinterでXYテーブルをGUI操作する|移動量入力・XY同時実行・緊急停止ボタン
- PythonのGUIが固まる理由とThreadの使い方|Tkinterでモーター制御中もボタンを効かせる
- XYテーブルGUIに原点復帰・現在位置表示・ソフトリミットを実装|Queueでスレッド安全にGUI更新
- XYテーブル制御GUIに単軸動作・片道移動・安全なプログラム終了を実装
- 自作XYテーブルの完成構成と設計資料(図面・BOM・結線図)|完成版Pythonコード配布
補足記事
⚡ 第1.5回・補足 A4988の電流制限(Vref)調整方法|焼損を防ぐ計算式とテスターでの設定手順 モーターを回す前に必ずやる A4988 の電流調整。 → 🔀 番外編 L6470が動かない原因|A4988との違いとSPI通信・デイジーチェーンの罠 高機能ドライバ L6470 を A4988 と同じ感覚で使ってハマった話。 → 🗺️ 全体像 自作XYテーブルの全手順ロードマップ|Raspberry Pi+ステッピングモーターで2軸制御 第0回〜第11回の全工程をまとめたロードマップ。 →Follow me on X
本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕
@ninjin_py_vba をフォローシリーズ記事一覧
電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。
-
FILE.01 — IoT
Raspberry Pi Pico W × GASラズパイPico W×GASで自作!「LINEで動く温湿度&スマートリモコン」完全ロードマップ
「外出中のペットの室温が心配…」そんな思いからスタートしたIoT自作プロジェクトの総集編。温湿度監視からエアコン遠隔操作まで、仕組みをゼロから作りたい方のための全5回の開発記録です。
シリーズを読む -
FILE.02 — CNC
Arduino × レーザー刻印CNCCNC自作シリーズ
高精度な加工を目指し、本格的な自作CNC製作に挑戦中。現在は基幹パーツであるオリエンタルモーターの納品を待つ「設計・準備編」を公開。ハードとソフトの両面から、理想のマシンを形にする過程をリアルタイムにお届けします。
シリーズを読む -
FILE.03 — XY軸制御
Raspberry Pi × ステッピングモーターXYテーブルシリーズ
Raspberry Piとステッパモーターを使い、ゼロから2軸制御に挑む記録。OS設定から回路設計、多軸制御のPythonコードまで、躓きやすいポイントを徹底図解。電子工作初心者が「動く感動」を味わうための実戦ガイドです。
シリーズを読む -
FILE.04 — 業務自動化
Python × Excel × CustomTkinter【Python開発記】NINJIN Mail制作記
PythonとExcelを連携させ、実務で即戦力となるメール送信ツールを開発。CustomTkinterによるUI構築や、ミスを防ぐテンプレート活用術など、現場の「痒い所に手が届く」自動化ノウハウを細部まで丁寧に解説します。
シリーズを読む -
FILE.05 — 業務自動化
Python × Excel × GUIアプリ化Invoice Maker(請求書・見積書自動作成)
手作業の請求書作成から卒業!PythonでExcelデータを読み込み一括PDF化する「Invoice_Maker」の作り方を全3回で解説。基本ロジックからGUIアプリ化まで、実務で役立つ自動化ノウハウが満載です。
シリーズを読む

コメント