秋月電子のL6470キットをデイジーチェーン接続(2)

秋月電子通商の<AE-L6470DRV>をデイジーチェーン接続で駆動させるためにしたことをアレコレ書いてます。


mbedとL6470のふつうの接続

L6470はSPIでの接続なので、マイコンとの接続は4本線(GNDを含めると5本線)になりますが、
秋月電子の紙ぺらにはEXT-VDDに6本目の点線が描かれています。
これはキットのコネクタの左側にあるJP1ジャンパの設定で結線が変わることを指しています。
おそらく殆どの人はL6470の内部レギュレータを使用するので、この結線は不要になります。

L6470_common_con.png

マイコンとL6470が1個だけであれば、デイジーチェーンのことを考えなくてもよいので
秋月電子の紙ぺらと同じように接続すれば問題ありません。

mbedであればSPIのインターフェース(MISO, MOSI, SCK)が連番で並んでいると思うので、
それを画像のように繋げていけば大丈夫です。CSDigitalOutができるピンであればどこでもOKです。
ただし、あまりSPIのところから離れすぎるとGNDとゴッチャになってしまう可能性あるので、
できるだけコンパクトに配線することを推奨します。

続いて、デイジーチェーン接続の場合ですが・・・


mbedとL6470のデイジーチェーン接続

med2l6470drv.png

1:1の接続では、よそ様のサイトにも腐るほど挙がっている通りに接続すれば大丈夫ですが、
デイジーチェーン接続になるとちょっとだけややこしくなります。

SCK, CS, GNDはL6470の個数の数だけ分配させて1:1接続と同じように接続します。
(もちろんCSはDigitalOutできればどこでもいいですし、GNDもGNDの刻印があるPINならどこでもいいです)
ややこしいのがMISOMOSIで、「7番から入って、5番から出る」ことを念頭に接続しないといけません。

mbedからでたMOSIは1番目のL6470の7番と接続します。
最後のL6470の5番はmbedのMISOに接続します。
残ったすべての7番と5番を順番通りに結んでいくと、きれいなデイジーチェーン接続ができます。(願望)

SPI通信

SPI通信で命令を送るデバイスには、いろいろと命令を送る条件がありますが、
L6470の場合は以下のようなルールを守らなければなりません。

  1. SCKの信号は負パルス
  2. SCKは2つ目のエッジでラッチ
  3. SPIクロックの周波数は5MHz以下
  4. データはMSBファーストで転送する
  5. 通信は8bitで行う
  6. CSの立ち下げで受信送信

なにやらギャーギャー騒いでますが、mbedではSPI通信のための便利な機能があるので、
4番目以外は簡単に解決できます。

SCK信号は負パルスで、SCKは2つ目のエッジでラッチ(シフト先行)なのでSPIモードは3になり、
通信は8bitで行います。また、SPIのクロックは5MHz以下なので、安全シロをとって4,960,000Hzに設定しましょう。
この場合のコードは、

SPI_L6470.format(8, 3);
SPI_L6470.frequency(4960000);

となります。(SPI_L6470はインスタンス)
formatやfrequencyについてはmbed公式のhandbookをご参照ください

4番目のMSBファーストというのは、8bitを超えるデータについては桁の高いものから順に送ることを指します。
たとえば、送信データとして10進数で「22,524」を送る場合は、
2進数に置き換えると0101 0111 1111 1100になりますが、
MSBファーストではまず0101 0111を送ってから、次に1111 1100を送ります。
プログラム的に書くとこのようになります。
(もっとうまいやり方はいくらでもあります・・・)

//送信データ準備
int soushin_data = 22524;
//CS信号立ち下げ
csel = 0;
//SPI通信(8bit MSB First)
spi.write((soushin_data & 0b1111111100000000) >> 8);
spi.write(soushin_data & 0b0000000011111111);
//CS信号立ち上げ
csel = 1;

1つめの(soushin_data & 0b1111111100000000)の結果は「0101 0111 0000 0000」になります。
上の8bitだけを送りたいので、8bit右シフトして、下8桁を切り捨てています。
2つめの(soushin_data & 0b0000000011111111)の結果は「0000 0000 1111 1100」になります。
上はゼロのみなので、特にビットシフトせずにそのまま送出可能です。

SPIでのデータ送受信

L6470が8bit送信で、MSBファーストなのはわかったかと思いますが、
実際のコマンドやデータ送受信はどのようなものかイメージが湧かないと思います。

L6470に対してデータを送出する手順は、

  1. CS信号を立ち下げる
  2. コマンドを送る(8bit)
  3. CS信号を立ち上げる
  4. またCS信号を立ち下げる
  5. パラメータを送る(MSBファースト8bit)
  6. またCS信号を立ち上げる
  7. またまたCS信号を立ち下げる
  8. 残りパラメータを8bit送る
  9. またまたまたCS信号を立ち上げる
  10. 以後、パラメータを送り終えるまで7から9を繰り返す

となります。(最終的にCS信号は立ち上がっている(High)状態が正解)

なにもコマンドやパラメータを送付しない場合NOP(0x00)を送ります。
データを受信する場合も、コマンドを送った後にNOPを受信が終わるまで送り続けます。
(もちろん8bitごとにCS信号の上げ下げも伴う)

デイジーチェーンSPIでのデータ送受信

L6470が1つの場合は、CSを下げてデータを送ってCSを上げる簡単なお仕事です。
デイジーチェーンの場合は、CSを下げて、L6470の数×8bit分の命令を一機に送って、CSを上げます。

L6470を5つ接続しているのであれば、5×8で40bit分の命令を送ることになりますが、
じゃあ上のSPI_L6470.format(8, 3);が、SPI_L6470.format(40, 3);になるのか? と考えますが
5つ分のコマンドやパラメータを固めて送ると、デバッグし辛くなるのでやめておきましょう
素直に8bitを5回送ってわかりやすく、計算しやすくしたほうが利口です(経験談)

実際に2つのL6470をデイジーチェーン接続して、1番目のモーターに対して
GetParamコマンド(0x20)でSTATUSレジスター(0x19)を確認した際のSPI通信波形は以下のようになります。
(実際のコマンドは、0x20 | 0x19 = 0x39)

l6470SPI_getStatus.png


この通信ログはロジックアナライザ(台湾ZEROPLUS社のLAP-C[16064])で取得しています
画像が表示されていないスマートフォンの方は、PCビューでご覧ください

これは左から右に時系列にSPI通信の波形を見たログになりますが、
上側のMasterOutと書かれた緑がmbedから送出されたデータ
下側のSlaveOutと書かれた緑のものがL6470から返されたデータです。
SCK信号(茶)CS信号(赤)は参考のために入れておきました。
SCKがちゃんと負パルスでシフト先行(2回目のエッジ=縦線からデータ送信が始まっている)なのが分かるかと思います。

まず1回目の通信でCSを立ち下げ0x39とNOP(0x00)を送りCSを立ち上げています。
この時、1つ目のL6470が0x39を受け取ってGetParam(STATUS)を実行する準備に入り、
2つ目のL6470は0x00で何もしない待ちぼうけ状態です。

2回目の通信でCSを立ち下げGetParam(STATUS)の結果の最初の8bit(0x7C)が帰ってきます。
データを受信するので、mbedからはNOPを送りCSを立ち上げます。

3回目の通信でCSを立ち下げ、GetParam(STATUS)の結果の残りの8bit(0x50)が帰ってきます。
もちろんデータ受信なので、mbedからはNOPを送りCSを立ち上げます。

これで、1つめのL6470から0x7C50というデータを受信することができました。
簡単ですね!
注:ここにたどり着くまでに丸3日を要しています

2015/ 06/ 14追記

以下の受け取ったデータの解釈について、おかしいのではないか?と連絡をうけました。
たしかに言われてみればビット反転のマークがついていないのに、勝手に反転していると書いていますね・・・。
うーん・・・。当時の私は何を考えていたんだかわからない。
以下に記載されているものについては信頼性皆無ですので、「あぁ。パラメータが受け取れたんだな」程度にお考えください。

L6470Status.png

実際に受け取ったデータはデータシートの表と照らし合わせることで、モーターがどういった状態であるのかを確認することが可能です。

上記(0x7C50)の場合、
「STEP/CLKモードではなく(15bit)、
 B相もA相もロスはなく(14bit, 13bit)、
 オーバーカレント(12bit)と温度異常(11bit, 10bit)は起きていません、
 電圧も正常で(9bit)、
 不正コマンド(8bit)や処理されていないコマンド(7bit)はなく、
 現在減速中で(6bit, 5bit)、時計回りに回っています(4bit)。
 スイッチは接続されておらず(3bit)、スイッチオープン状態で(2bit)、
 モーターは現在回転中(1bit)、ハイインピーダンス状態ではありません(0bit)」

ということがわかります。

ちなみに、上記では1番目のモーターに対してコマンドを送っていましたが、
2番目に送る場合は下記のようになります。

l6470SPI_getStatus2.png


やっぱり簡単ですね!

次の記事では、こんなややこしいことを考えずに、mbedらしくパパッと動かすためのプログラムを紹介します。


コメントを残す