L6470でステッピングモータを動かす
この記事について
L6470(を使用した既存のモータードライブキット)でステッピングモータを動かす記事です。
この記事は、サンプルコードを拾ってきて、とりあえず動かす(動かした)だけでは少しモヤモヤするという人に向けて書いています。
私もモヤモヤしたので、可能な範囲で調べてこの記事を書いています。そのため、記事内容に収まらない応用方法についてはお答えできないかもしれません。
L6470はバイポーラステッピングモータのドライブICですが、基本的には実装されたキット全体を指してL6470と書いています。ICのみを指すときには、L6470使用やIC L6470などと書いています。
随時更新中(2019.11.8)
使ったもの
L6470使用 ステッピングモータードライブキット
秋月電子で購入
L6470使用 ステッピングモータードライブキット: 組立キット 秋月電子通商-電子部品・ネット通販
バイポーラ ステッピングモーター ST-42BYH1004
秋月電子で購入
バイポーラ ステッピングモーター ST−42BYH1004: パーツ一般 秋月電子通商-電子部品・ネット通販
モータの主な仕様
項目 | 詳細 |
---|---|
ステータ | バイポーラタイプ |
相数 | 2 |
基本ステップ角 | 0.9度±5% |
1回転ステップ数 | 400 |
絶縁抵抗 | 100MΩ(500VDC) |
コイル抵抗 | 5.0±10%Ω/相 |
入力定格電圧 | 5V |
定格電流 | 1.0A/相 |
静止トルク | 4.4kgf・cm |
重量 | 0.34kg |
注意 | 軸を回さない。感電する |
配線
配線 | 色 |
---|---|
A(A相) | Black |
C(_A相) | Green |
B(B相) | Red |
D(_B相) | Blue |
L6470でステッピングモータを回す
ピンの役割と接続
モータの制御はマイコンとL6470をピンで接続し、SPI通信によってコマンドを送受信することで行われる。 Master(制御する側)とSlave(制御される側)を以下としたときの各デバイスのピンの役割を理解し、正しい対応関係でピン同士を接続する。
- Master: Arduin UNO R3
- Slave: L6470 Driver
Adruino側
SPI通信のためのピン
※SSピン以外は変更することができない
ピン番号 | 名称 | 役割 |
---|---|---|
D11 | MOSI(Master Out Slave In) | マスタからスレーブへデータを送るライン |
D12 | MISO(Master In Slave Out) | スレーブからマスタへデータを送るライン |
D13 | SCK(Serial Clock, Output) | データ転送を同期させるためマスタより生成されるクロック信号 |
D10 | SS(Slave Serect pin, Output) | デジタル信号を渡すことでスレーブを選択する。LOWが渡されたスレーブはマスタとの通信をおこなう。HIGHが渡されたときマスタからのデータを無視する。 |
L6470側
SPI通信のためのピン
ピン番号 | 名称 | 分類 |
---|---|---|
5 | SDO (SPI Data Out) | Logic output |
6 | CK (SPI Clock) | Logic input |
7 | SDI (SPI Data In) | Logic input |
8 | #CS (SPI Chip Serect, = Slave Srect) | Logic input, 負論理 |
ArduinoとL6470の各ピンを比較すると、以下の対応関係でピンを接続することがわかる。
- D11 (MOSI) <-> 7 (SDI)
- D12 (MISO) <-> 5 (SDO)
- D13 (SCK) <-> 6 (CK)
- D10 (SS) <-> 8 (#CS)
その他のピン
必要に応じてその他のピンも接続することで、L6470に機能を追加して利用することができる。
ピン番号 | 名称 | 分類 | 役割 |
---|---|---|---|
1 | #BUSY/SYNC | Open Drain Output | Busy Frag Mode(SYNC_EN bitがLOW(0)のときdefault)・デフォルトの状態では、コマンド実行中はLOWになる。・一定速度コマンド、絶対位置指定コマンド、移動コマンドが実行中のとき、ピン出力がLOW・コマンドが実行されたとき(目標速度、目標座標に到達)、このBUSYピンは解放される。Synchronization Signal Mode(SYNC_EN bitがHIGH(1)のとき)・このモードでのステップクロック信号は、SYNC_SELとSTEP_SELパラメータの組み合わせに応じて出力される。 |
2 | FRAG(Status Frag) | Open Drain Output | アラーム発生時にFRAGピンをGNDに接続する。(内部のオープンドレイントランジスタによる) |
3 | GND (Ground) | ||
4 | EXT-VDD(External-VDD) | Power | ロジック出力ピンの電圧範囲を設定。VDDpinは内部でVregまたは3.3V電源に接続されていない。 |
9 | STCK(Step-clock Input) | Logic Input | Step-clock mode時に入力された信号によってモータの動きが定義される。 |
10 | #STBY/#RST(Stepby and Reset) | Logic Input | LOW logic levelでlogicをリセット、デバイスをスタンバイモードに。使わない場合はVDDにつなげておく。 |
ロジック電源の設定をする
ピンの接続によって信号を送受信する路はつながるが、IC L6470やモータを動かすためには当然電源が必要。モータードライブキットではモータを動かす電源の他に、MCU(Micro Control Unit = ここではIC L6470)を動かすロジック電源が必要である。キットではジャンパピンの挿入によって、MCUへの電源電圧の供給方法を設定することができる。
MCUは3.3~5Vの間で動作し、MCUからマイコンへ入力されるデジタル信号の電圧もロジック電源の電圧によって決定される。IC L6470は内部のレギュレータによってモータ電源から3Vの電圧をMCUに回すことができるが、その場合はArduinoに入力するデジタル信号も3Vとなってしまう。Arduinoは5V駆動であるため、3Vのデジタル信号をArduinoに入力することは好ましくない。
よって、MCUの内部レギュレータは使用せずに、Arduinoの5VピンからEXT-VDDピンに電圧を供給してMCUを駆動させるのが良い。 (下図真ん中の方式)
SPI通信の設定をする
L6470を使う際には、初めにコマンドを送るためのSPI通信の設定を以下のように記述する。
これらの設定はL6470のSPI通信の仕様に従って決めたものであり、仕様はデータシートで確認できる(データシートの確認については後述)。
void setup(){ // ... 他の初期化設定 ... SPI.begin() SPI.setBitOrder( **MSBFIRST** ) SPI.setDataMode( **SPI_MODE3** ) }
以下では、上の各設定についてそれぞれ説明する。
SPI.begin()
SPIバスを初期化する。 SCK、MOSI、SSの各ピンは出力に設定され、SCKとMOSIはlowに、SSはhighになる。
SPI.setBitOrder()
SPI.transfer()という関数で送信する1バイト(8ビット)分の情報を、左端(最上位)と右端(最下位)のどちらから送信するかを決める。
設定には MSBFIRSST と LSBFRIST の2通りがあり、いずれかを選択する。
MSB と LSB
以下の表で示している通り。2進数で表された情報において
を指す。(ここでは8bit=1byte)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
MSB | LSB |
SPI.setBitOrder() の記述方法
- SPI.setBitOrder( MSBFIRST )
- 最上位ビット(MSB)から順にデータを送信する
- 7→6→5→4→3→2→1→0
- SPI.setBitOrder( LSBFIRST )
- 最下位ビット(LSB)から順にデータを送信する
- 0→1→2→3→4→5→6→7
SPI.setDataMode()
信号におけるクロック位相(clock phase)とクロック極性(clock polarity)という2つの要素を決定する。
- クロック位相:シフトされたデータを読み取るタイミング
- クロック信号の 立ち下がりエッジ or 立ち上がりエッジ
- クロック極性:アイドリング(待機)状態を示すクロック信号の状態
- HIGH状態 or LOW状態
SPI.setDataMode()の記述方法
- 例)SPI.getDataMode( SPI_MODE3 )
- クロック信号の立ち上がりで送信(シフト)されたデータの読み取りを行う
- また、クロック信号がHIGHの間をアイドリング状態とする
SPI_MODE一覧
立ち下がりエッジで読み取り | 立ち上がりエッジで読み取り | |
---|---|---|
LOW状態でアイドリング | SPI_MODE0 | SPI_MODE1 |
HIGH状態でアイドリング | SPI_MODE2 | SPI_MODE3 |
SPIの設定まとめ
SPI.setBitOrder()とSPI.setDataMode()の設定の組み合わせは以下の通り。
(図はLinkより引用)
L6470のSPI通信仕様
L6470のSPI通信の仕様は、データシートから確認することができる(8. Serial Interface)。
(追記予定)
コマンドの送信方法
L6470は、SPI通信で内部のレジスタにコマンドをシフト(送信)することで制御することができる。そのとき、
- MSBファーストでコマンドを8ビットずつに区切り、SPI.transfer() で送信する
- 8ビットごとに、CS(SS)のHIGH->LOWを行う
ことが必要であり、以下のようなコマンド送信用の関数を用意すると良い。
モータ制御のために送信するコマンドについてはこの次に記述する。
void L6470_send( unsigned char add_or_val ){ while( !digitalRead(PIN_BUSY) ){ // BUSY(LOW状態)が解除されるまで待機する // L6470のBUSY/SYNCピンをArduinoに接続しておく必要がある } digitalWrite( PIN_SPI_SS, LOW); SPI.transfer( add_or_val ); //1バイト(8ビット)のデータを送信 digitalWrite( PIN_SPI_SS, HIGH); } void L6470_transfer( int add, int bytes, long val ){ // 内部レジスタ長が最大22ビットなので、3バイト(24ビット)のデータまで扱える配列を用意する int data[3]; // 送信する値を8ビットごとに分けて配列に格納する for( int i = 0; i < bytes; i++) { // 0xffと論理積を取ることで、後ろから8ビット分のみを格納 data[i] = val & 0xff; // 右に8ビットシフトすることで、次には配列に格納した部分をのぞいた値を扱う val = val >> 8; } // 送信バイト数に応じて、MSBファーストになるよう配列の後ろの要素から送信する if ( bytes == 3 ) { // はじめにレジスタを指定するためにアドレスを送信するので、一度に最大32ビット送信する L6470_send( add ); L6470_send( data[2] ) ; L6470_send( data[1] ) ; L6470_send( data[0] ) ; } else if ( bytes == 2 ) { L6470_send( add ); L6470_send( data[1] ) ; L6470_send( data[0] ) ; } else if ( bytes == 1 ) { L6470_send( add ); L6470_send( data[0] ) ; } // 3バイト以上送ろうとしたら回避する処理をちゃんと書いた方が良いと思う… }
制御のパラメータを設定する
L6470には、モータの制御に関するパラメータを設定するための内部レジスタ(記憶回路)が多く存在する。レジスタのアドレスを指定したのちに値を送信することで、パラメータを設定することができる。
- 各レジスタは可変長、22ビットや4ビット等がある。各レジスタの内部アドレスは0x01~0x19が割り当てられている
- 各レジスタのパラメータには初期設定(デフォルト値)が決まっており、電源投入直後にはデフォルト値が設定される
- 大体はデフォルトの値で動作する。変更が必要な場合もあり
- レジスタの値を設定した後に、回転・ストップ等の指示を送ってモータを制御する
SetParam() によるレジスタの値の設定
モータの動作を指示する
Run() による定速回転
コマンド:Run( DIR, Spd )
回転方向DIR(Direction)と、目標速度Spd(Speed)を指定してステッピングモータを定速回転させる
32ビットの情報を4回に分けて送信する
初めの8ビット
- 定速回転のコマンド+回転方向の指定
Command binary code
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
0 | 1 | 0 | 1 | 0 | 0 | 0 | DIR |
16進数
定速正回転の場合(DIR = 1) | 定速負回転の場合(DIR = 0) | |
---|---|---|
2進数 | 01010001 | 01010000 |
16進数 | 0x51 | 0x50 |
残りの24ビット
回転速度の指定
モータ速度の表現方法
Speed,MAX_SPEED,MIN_SPEEDレジスタでほぼ同じ表現が用いられる
- レジスタの容量など、異なる点もある
各レジスタにはステップ/動作クロックで表された値が格納されている
1秒あたりのステップ数(ステップ/秒)には、それぞれ以下の式で変換される
Speedレジスタ(20ビット)
初期値は0(0ステップ/動作クロック,0ステップ/秒)
動作クロックは250ns
MAX_SPEEDレジスタ(10ビット)
初期値は041
動作クロックは250ns
# ステップ/動作クロックからステップ/秒への変換
MAX_SPEEDレジスタの最大値
初期値041は7ビット
10ビットの最大値1111111111は0x3FF, 1023
MIN_SPEEDレジスタ(13ビット)
初期値は000(0ステップ/動作クロック、0ステップ/秒)
動作クロックは250ns
デバイスの初期化
- Arduinoのvoid setup()内で、モータ駆動する前に以下の内容を実行する。
void L6470_resetDevice(){ // nop命令 L6470_send(0x00); L6470_send(0x00); L6470_send(0x00); L6470_send(0x00); // ResetDevice L6470_send(0xc0); }
nop命令を4回(4byte分)送った後に、デバイスをリセットする(ResetDeviceコマンドを送る)。
- これは、L6470に一度に送る情報が最大で4byteであるため
nop命令を4回送ることで、前のコマンドを確実に終了させてからデバイスをリセットする
ResetDevice (Application commands)
L6470デバイスを電源投入後の状態にリセットする
- パラメータの初期化等
Command binary code
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
16進数
0xc0
- SPI.transfer(0xc0)で初期化
NOP (Application commands)
Nothing is performed
- 何もしない
Command binary code
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
16進数
0x00
- SPI.transfer(0x00)で何もしない命令
参考資料
SPI通信
SPI (Bit order, Data modeについて)
L6470
取扱説明書等
データシート和訳
その他参考サイト(ソースコード等)
(L6480の動かし方 [メモ][開発] ステッピングモータードライバL6470とL6480: ヤメ記者SEの徒然なるままに…)