ステッピングモータを、モータドライバ(L6470)を用いて、ラズパイから制御する方法を紹介します。
初心者の方にも理解しやすいように丁寧に解説したつもりです。
本記事が皆さまの参考になれば幸いです。
本記事では、下記の内容を紹介しています。
この記事で分かること
本記事を読み終わると、下記の内容が分かるようになります。
- ステッピングモータの制御に必要なもの
- 各パーツの結線、回路図
- モータドライバ(L6470)の制御コマンド
- pythonサンプルコード
スポンサーリンク
必要なもの
はじめに、ステッピングモータ制御に必要なパーツや、あると便利なパーツを紹介します。
ステッピングモーター
ステッピングモータは秋月電子通商で購入しました。
値段が手頃だったのでこちらを選んでいます。
モータードライバ
モータドライバIC(L6470)が組み込まれたドライブキットを、秋月電子通商で購入しました。
8V~45Vまでのモータ動作電源電圧に対応しているので、ステッピングモータが変わっても使用できます。
部品のハンダ付けが必要です。
DC 12V 電源アダプター
ステッピングモータの動作電源電圧が12Vだったので、電源電圧供給用に用意しました。
スクリュー端子台のコネクタがついていると、簡単にモータードライバと接続できます。
ジャンパーワイヤー
電子工作には必須のジャンパーワイヤ。
絶対に使うことになるので、オス-オス、オス-メス、メス-メスは一通りそろえておくと良いです。
スポンサーリンク
ラズパイ、モータドライバ、ステッピングモータの結線、回路図
次に、それぞれのパーツの結線について紹介します。
ラズパイのピン配置
結線を紹介する前に、ラズパイのピン配置を載せておきます。
ラズパイ ピン配置
ラズパイのピン配置は、ターミナルからも確認できます。
ターミナルに下記のコマンドを入力します。
$ pinout
各パーツの結線、回路図
ラズパイ-ドライバ間は、SPI通信で制御を行います。
そのため、SPI通信に関わる端子同士を結線します。
なお、モータドライバ(L6470)のJP1の3、4pinは短絡させています。
スポンサーリンク
ラズパイからステッピングモータを制御する、pythonサンプルコード
各パーツが結線できたので、ソフトについて紹介します。
ライブラリのインストール
SPI通信に必要なライブラリをインストールします。
「WiringPi」というライブラリをラズパイにインストールします。
WiringPiを利用することで、GPIOに簡単にアクセスできるようになります。
ターミナルに下記コマンドを入力して、ライブラリをインストールします。
$ sudo pip3 install wiringpi
なお、「RPi.GPIO」というライブラリも使用していますが、
こちらはOSがRaspbianの場合は、デフォルトでラズパイにインストールされています。
モータドライバ(L6470)の制御用コマンド
モータドライバの制御用コマンドは、L6470のデータシートを参照してください。
データシートはこちらからダウンロードできます。
モータドライバ(L6470)のデータシートを少し見てみましょう。
制御用コマンドが載っているページを抜粋します。
L6470データシート抜粋
このデータシートに記載のある、
速度指定回転の「Run(DIR,SPD)」コマンドを例に説明します。
制御コマンドを送信するために、2進数を16進数に変換する必要があります。
ここでは変換方法について詳細には説明しませんが、Excelで2進数から16進数への変換を行った結果を載せます。
(Excelでの2進数→16進数変換については、ネットにたくさん情報が載っているので気になる方は調べてみてください。)
Run(DIR,SPD)の0bit目は、Directionつまり回転方向を入力します。
"0" or "1"を入力することになりますが、この例では "1" を入力しています。
このExcelの変換結果によると、Runを実行するには、16進数で"51"を送信すればよいことがわかります。
このあと紹介するPythonコマンドに、速度指定回転のコマンド送信の実例も載っているので、併せて参考にしてみてください。
このような形で、データシートから制御用コマンドを読み取っていくことになります。
Pythonのサンプルコード
Pythonのサンプルコードを紹介します。
こちらのサイトがすごく綺麗なコードを書いていたので、参考にさせていただいました。
(というか、ほとんどそのまま使用させて頂いております)
### --- ステッピングモータ制御 --- ###
import wiringpi as wp
import RPi.GPIO as GPIO
import struct
import time
import sys
### --- 接続用パラメータ --- ###
SPI_CH = 0 # SPI チャンネル
SPI_HZ = 1000000 # SPI 通信速度
GPIO_Nbr = 25 # GPIO-NO
GPIO.setmode(GPIO.BCM) # GPIO-NO 指定
GPIO.setup(GPIO_Nbr,GPIO.IN) # GPIO INPUT 指定
### --------------------------- ###
# L6470初期設定
def INIT_L6470():
spi_send([0x00,0x00,0x00,0xc0]) # Reset Device
spi_send([0x05,0x00,0x0e]) # Acceleration (12)
spi_send([0x06,0x00,0x0e]) # Deceleration (12)
spi_send([0x07,0x00,0x0e]) # Maximum speed (10)
spi_send([0x08,0x00,0x01]) # Minimum speed (13)
spi_send([0x15,0x03,0xFF]) # Full-step speed (10)
spi_send([0x16,0x03]) # Micro Step (8)
spi_send([0x09,0x50]) # Holding Kval (8)
spi_send([0x0A,0x50]) # Constant Speed Kval (8)
spi_send([0x0B,0x50]) # Acceleration starting Kval (8)
spi_send([0x0C,0x50]) # Deceleration starting Kbal (8)
# SPI データ送信
def spi_send(spi_dat_ary):
for itm in spi_dat_ary:
tmp=struct.pack("B",itm)
wp.wiringPiSPIDataRW(SPI_CH, tmp)
# データ加工・送信(共通)
def L6470_SEND_MOVE_CMD( cmd , DAT ):
tmp=[]
tmp.append(cmd)
tmp.append((0x0F0000 & DAT) >> 16)
tmp.append((0x00FF00 & DAT) >> 8)
tmp.append((0x00FF & DAT))
print(tmp)
spi_send(tmp)
# JOG (SPEED指定 : 0---30000)
def L6470_run(run_spd):
# 方向検出
if (run_spd > 0):
dir = 0x50 #Run(と回転方向)
spd = run_spd
else:
dir = 0x51 #Run(と回転方向)
spd = -1 * run_spd
L6470_SEND_MOVE_CMD( dir , spd )
# 移動量指定移動
def L6470_POSITIONING(MV_DIST):
# 方向検出
if (MV_DIST > 0):
dir = 0x40 #Move(と回転方向)
else:
dir = 0x41 #Move(と回転方向)
MV_DIST = -1 * MV_DIST
L6470_SEND_MOVE_CMD( dir , MV_DIST )
# 絶対位置指定移動
def L6470_MOVE_ABS(MV_DIST):
dir = 0x60 #GoTo
if (MV_DIST < 0):
MV_DIST = -1 * MV_DIST
L6470_SEND_MOVE_CMD( dir , MV_DIST )
# 停止
def L6470_STOP():
spi_send([0xB0]) # SoftStop
time.sleep(0.2)
spi_send([0xA8]) # HardHiZ
time.sleep(0.2)
# 原点設定
def L6470_SET_ORIGIN():
spi_send([0xD8]) # Reset Position
time.sleep(0.5)
# 原点移動
def L6470_MOVE_ORIGIN():
spi_send([0x70]) # GoHome
time.sleep(0.5)
# ドライバーBUSY解除待ち
def wait_until_not_busy():
while True:
time.sleep(0.2)
mtr_sts = GPIO.input(GPIO_Nbr)
#print(mtr_sts)
if GPIO.input(GPIO_Nbr) == GPIO.HIGH :
print("L6470 NOT BUSY")
break
time.sleep(0.2)
##################################
# メインプログラム
##################################
if __name__ == "__main__":
wp.wiringPiSPISetup(SPI_CH,SPI_HZ) # SPI 接続
INIT_L6470() # L6470初期設定
# 速度指定回転
print("CONSTANT SPEED ROTATION START")
spd_run = 8000
L6470_run(spd_run)
print("Speed : %d" % spd_run)
time.sleep(5)
L6470_STOP()
print("STOP")
time.sleep(1)
spd_run = -8000
L6470_run(spd_run)
print("Speed : %d" % spd_run)
time.sleep(5)
L6470_STOP()
print("STOP")
time.sleep(1)
print("CONSTANT SPEED ROTATION FINISHED")
print("")
# 移動量指定回転
print("STEP ROTATION START")
rng=10
step = int(1600 / rng)
for i in range(rng):
L6470_POSITIONING(step) # 移動量指定移動
wait_until_not_busy() # ドライバーBUSY解除待ち
print("STEP ROTATION FINISHED")
print("")
# 絶対位置指定回転
print("ABS ROTATION START")
L6470_SET_ORIGIN() # 原点位置設定(0)
rng=10
step = int(3*(1600 / rng))
for i in range(rng):
L6470_MOVE_ABS((i+1)*step) # 絶対位置指定移動
wait_until_not_busy() # ドライバーBUSY解除待ち
L6470_MOVE_ORIGIN() # 原点位置移動
print("ABS ROTATION FINISHED")
GPIO.cleanup()
※このコードでラズパイ上は動作していますが、サイト移植時にインデントを手打ちしています。
もしエラーが出た場合は、インデント部分を確認いただければと思います。
その他不具合がある場合は、コメント欄に記載いただければこちらで確認します。(可能な範囲で)
ステッピングモータが動作する様子
速度指定回転、移動量指定回転、絶対位置指定回転の3つのモードで動作することを確認できました。
スポンサーリンク
まとめ
ラズパイから、モータドライバ(L6470)を介して、ステッピングモータを制御する方法を紹介していきました。
ステッピングモータが自分の思い通り動くと嬉しいですよね。
ステッピングモータは様々な工作に使えますので、是非活用してみてください。
Pythonコードは、KatsEyeさんのサイトを参考にさせていただきました。改めて、感謝申し上げます。
スポンサーリンク