PR

ステッピングモーターの脱調を防ぐ加減速制御をPythonで実装【XYテーブル自作 第5回】

RaspberryPi

はじめに

XYテーブル製作シリーズ 第5回

スポンサーリンク

はじめに:「ガガガ」と鳴って止まる脱調を防ぐ

このシリーズで製作する自作XYテーブルの外観図
このシリーズのゴール:自作XYテーブル

モーターを速く動かそうとすると「ガガガ」と異音がして止まる——これが脱調で、静止状態からいきなり高速で回そうとするのが原因です。実用的なスピードで正確に動かすには、速度を徐々に変える加減速制御(台形駆動)が欠かせません。今回はそれをPythonで実装します。

この記事で分かること

  • 脱調が起きる理由と、台形駆動(加速→定速→減速)の考え方
  • ステップごとの「待ち時間(interval)」で速度をコントロールする仕組み(小さいほど速い)
  • 待ち時間のリストを作る関数 get_intervals() の実装(線形ランプ)
  • 加減速付きでモーターを動かすPythonコード(X_Move_acc_dec.py、ZIP配布)

スポンサーリンク

加減速の仕組みと「待ち時間」のコントロール

停止しているモーターをいきなり高速で回そうとすると、負荷に耐えきれず脱調(空回り)して止まります。これを防ぐため、速度を3つのフェーズに分けて制御します。これが台形駆動(速度プロファイル)です。

  • 加速区間(スローアップ):徐々に速度を上げる
  • 定速区間:目標の最高速度を維持する
  • 減速区間(スローダウン):停止に向けて徐々に速度を落とす
時間を横軸、速度を縦軸にとった台形の速度プロファイル。立ち上がり・定速・立ち下がりの3区間
台形駆動の速度プロファイル

待ち時間(interval)で速度を決める

各STEPパルスの間に time.sleep(interval) を挟み、この interval を変えて速度を制御します。値が小さいほどモーターは速く回ります。

フェーズ待ち時間(例)モーターの状態
加速0.005 → 0.003 → 0.001どんどん速くなる
定速0.001(一定)一定の速さで回る
減速0.001 → 0.003 → 0.005どんどん遅くなる

スポンサーリンク

使用するハードウェアと配線

第4回「X軸とY軸を2台動かす」と同じハードウェア構成・配線で行います(今回はX軸のみ動作させます)。

🔀 第4回 PythonでX軸・Y軸のステッピングモーターを2軸制御する方法|A4988ドライバー2台の配線とコード 配線と2軸制御の土台はこちら。

スポンサーリンク

Pythonプログラム(加減速付き・X_Move_acc_dec.py)

X軸のみの実装です。Y軸は今回動作させません。

import RPi.GPIO as GPIO
import time

# =====================================================
# GPIO モード設定
# =====================================================
GPIO.setmode(GPIO.BCM)

# ===== PIN設定 =====
X_STEP = 21
X_DIR  = 20
X_EN   = 16
X_MS1  = 17
X_MS2  = 27
X_MS3  = 22
X_RESET = 5
X_SLEEP = 6

# =====================================================
# モーション設定(将来互換)
# =====================================================
BELT_PITCH = 2.0
PULLEY_TEETH = 32
FULL_STEPS_PER_REV = 200
MICROSTEP = 16

MM_PER_REV = BELT_PITCH * PULLEY_TEETH
STEPS_PER_REV = FULL_STEPS_PER_REV * MICROSTEP
MM_PER_STEP = MM_PER_REV / STEPS_PER_REV

# =====================================================
# GPIO 初期化関数(rev4互換)
# =====================================================
def gpio_init_axis(STEP, DIR, EN, MS1, MS2, MS3, RESET, SLEEP):

    pins = [STEP, DIR, EN, MS1, MS2, MS3, RESET, SLEEP]

    for pin in pins:
        GPIO.setup(pin, GPIO.OUT)

    GPIO.output(RESET, GPIO.HIGH)
    GPIO.output(SLEEP, GPIO.HIGH)
    GPIO.output(EN, GPIO.LOW)

    # 1/16 マイクロステップ
    GPIO.output(MS1, GPIO.HIGH)
    GPIO.output(MS2, GPIO.HIGH)
    GPIO.output(MS3, GPIO.HIGH)


# ===== 加減速プロファイル作成 =====
def get_intervals(total_steps):

    min_delay = 0.003   # 最高速
    max_delay = 0.009    # 最低速

    accel_steps = total_steps // 3
    decel_steps = accel_steps
    const_steps = total_steps - accel_steps - decel_steps

    intervals = []

    # 加速
    for i in range(accel_steps):
        ratio = i / accel_steps
        delay = max_delay - (max_delay - min_delay) * ratio
        intervals.append(delay)

    # 定速
    for i in range(const_steps):
        intervals.append(min_delay)

    # 減速
    for i in range(decel_steps):
        ratio = i / decel_steps
        delay = min_delay + (max_delay - min_delay) * ratio
        intervals.append(delay)

    return intervals


# ===== 移動関数(加減速付き) =====
def move_mm(distance_mm, direction):

    steps = int(distance_mm / MM_PER_STEP)

    GPIO.output(X_DIR, direction)

    intervals = get_intervals(steps)

    for delay in intervals:

        GPIO.output(X_STEP, GPIO.LOW)
        time.sleep(delay)

        GPIO.output(X_STEP, GPIO.HIGH)
        time.sleep(delay)


try:

    print("50mm 正転(加速 → 定速 → 減速)")
    move_mm(50, GPIO.LOW)

    time.sleep(1)

    print("50mm 逆転(加速 → 定速 → 減速)")
    move_mm(50, GPIO.HIGH)

finally:

    GPIO.cleanup()
⬇ X_Move_acc_dec.py をダウンロード(ZIP)

スポンサーリンク

プログラムのポイント:get_intervals()

この関数が加減速の核心です。加速区間・定速区間・減速区間の3つに分け、ratio(進捗0〜1)を使って待ち時間を線形に変化させています。

delay = max_delay - (max_delay - min_delay) * ratio   # 加速:徐々に短く(速く)
delay = min_delay + (max_delay - min_delay) * ratio   # 減速:徐々に長く(遅く)

実行するとどう変わる?

以前は一定速度で「ガガガガガガ」と鳴っていた動きが、今回は「ゆっくり → 速く → ゆっくり」と滑らかになります。


スポンサーリンク

まとめと次回予告

内容
第1回LEDを光らせる
第2回モーターを回す
第3回A4988でmm単位制御
第4回XYの2軸制御
第5回加減速制御(今回)

次回・第6回では、X軸とY軸を2軸同時に動かします(threading)。斜め移動や図形描画に必要な、XYテーブル制御の核心部分です。

次に読む記事

🧵 次回はこちら(第6回) Raspberry PiでXYテーブル制御|Pythonでステッピングモーターを2軸同時に動かす threadingでX軸・Y軸を同時駆動する。 🗺️ 全体像 自作XYテーブルの全手順ロードマップ|Raspberry Pi+ステッピングモーターで2軸制御 第0回〜第11回の全工程をまとめたロードマップ。

スポンサーリンク

よくある質問(FAQ)

Q脱調(だっちょう)とは何ですか?

Aステッピングモーターが指令パルスに追従できず、回転がずれる(または空回りして止まる)現象です。急加速・急停止、負荷過大、トルク不足、速すぎる回転が原因になります。加減速制御で立ち上がりを緩やかにすると大幅に減ります。

Q待ち時間(delay)はどのくらいにすればいいですか?

Aモーター・電圧・負荷で変わります。まず min_delay=0.003(最高速)、max_delay=0.009(最低速)程度から始め、脱調するなら max_delay を大きく(ゆっくり始動)、遅すぎるなら min_delay を小さくして詰めます。実機で少しずつ調整するのが確実です。

Q加速区間・減速区間はどのくらいの長さが適切ですか?

A本記事は全体の1/3ずつを加速・減速に割り当てています。移動距離が短いと定速区間がなくなり三角プロファイルになりますが、それでも脱調防止には有効です。距離が長いほど定速区間の割合を増やして所要時間を短縮できます。

Q台形駆動とS字(シグモイド)加減速の違いは?

A台形駆動は速度を直線的に増減させます(実装が簡単)。S字加減速は加速度自体も滑らかに変化させ、機械的な衝撃(ジャーク)をさらに抑えます。ホビー用途のXYテーブルなら台形駆動で十分実用になります。

Q2軸で加減速すると同期がずれませんか?

A軸ごとに独立して get_intervals() を回すと、移動距離が違う軸で終了時刻がずれます。直線補間では「移動時間を合わせる」または「1ループで両軸のパルスをBresenham法で配分する」方式にします。第6回以降で扱います。


スポンサーリンク

XYテーブル製作シリーズ(全12回)

補足記事

第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 をフォロー

この記事が役に立ったら、シェアしてもらえると嬉しいです🥕

Xでポスト はてブ LINE Pocket

PROJECT LOG — SERIES INDEX
スポンサーリンク

シリーズ記事一覧

電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。


超音波距離センサーHC-SR04をRaspberry Pi Picoで使う|仕組み・配線・精度検証
.uds1-block { position: relative; overflow: hidden; border-radius: 12px; border: 1px solid #f0cba8; background: linear-g…
今週の注目ガジェット〜09/07週〜|電子工作・自作向け新製品まとめ(TickrCast/Radxa Linkr ほか)
ニンジンのガジェット通信 09/07週。ESP32-P4の自作気象モニター、極小IP-KVM「Radxa Linkr」、ESP32のDINレール型PLC、LTE開発キットなど、電子工作で使えそうな新製品5つを解説。
サーボモータの角度をタクトスイッチで可変|OLED(SSD1306)に現在角度をリアルタイム表示
Raspberry Pi Pico 2W×MG996RにタクトスイッチとOLED(SSD1306)を追加。ボタンで角度を可変しながら現在角度をリアルタイム表示するMicroPython実装を、framebufの文字拡大やサーボの遊び対策まで実機ベースで解説します。
MG996RサーボモーターをRaspberry Pi Pico 2Wで動かす:PWM制御とキャリブレーション実践
MG996RサーボモーターをRaspberry Pi Pico 2Wで動かす方法を解説。公称180度のはずが実測198度だった個体差の原因究明から、ホーンのズレ補正、タクトスイッチでの角度制御まで実機検証の様子を紹介します。
Tapo P110Mの消費電力をExcelレポート化する【年次集計・電気代試算・セキュリティ判断編】
FastAPI+openpyxlでTapo P110Mの消費電力をExcelレポート化。15秒間隔の生ログを日次集計する設計や、31円/kWhでの電気代試算、外部公開を見送った理由まで解説します。

コメント