2012年9月22日土曜日

Raspberry Pi でSPI ストリナステッピングモータドライバ

 ArduinoのSPIでストリナのSPI接続ステッピングモータドライバを動かせた ので、同じ事を Raspberry Piでもできないか調べてみました。Raspberry PiでのSPIはドライバをインストールすればI2Cのようにファイルディスクリプタでアクセスできるようですが、いつも使わせてもらっている GordonさんとことのwiringPiにラッパー関数があったので、それを使わせてもらうことにしました。SPIのドライバをインストールする方法も同サイトに記述があります。


#include <stdio.h>
#include <stdlib.h>

#include <wiringPi.h>
#include <wiringPiSPI.h>

#define L6470_SPI_CHANNEL 0

// 関数プロトタイプ。
void L6470_write(unsigned char data);
void L6470_init(void);
void L6470_run(long speed);

int main(int argc, char **argv)
{
 int i;
 long speed = 0;
 
 printf("***** start spi test program *****\n");
 
 // SPI channel 0 を 1MHz で開始。
 if (wiringPiSPISetup(L6470_SPI_CHANNEL, 1000000) < 0)
 {
  printf("SPI Setup failed:\n");
 }
 
 // L6470の初期化。
 L6470_init();
 
 while(1)
 {
  for (i = 0; i < 5; i++)
  {
   speed += 10000;
   L6470_run(speed);
   delay (5000);
  }
  for (i= 0; i < 5; i++)
  {
   speed -= 10000;
   L6470_run(speed);
   delay (5000);
  }
 }
 
 return 0;
}


void L6470_write(unsigned char data)
{
 wiringPiSPIDataRW(L6470_SPI_CHANNEL, &data, 1);
}

void L6470_init()
{
 // MAX_SPEED設定。
 /// レジスタアドレス。
 L6470_write(0x07);
 // 最大回転スピード値(10bit)
 L6470_write(0x00);
 L6470_write(0x20);
 
 // KVAL_HOLD設定。
 /// レジスタアドレス。
 L6470_write(0x09);
 // モータ停止中の電圧設定(8bit)
 L6470_write(0xFF);
 
 // KVAL_RUN設定。
 /// レジスタアドレス。
 L6470_write(0x0A);
 // モータ定速回転中の電圧設定(8bit)
 L6470_write(0xFF);
 
 // KVAL_ACC設定。
 /// レジスタアドレス。
 L6470_write(0x0B);
 // モータ加速中の電圧設定(8bit)
 L6470_write(0xFF);
 
 // KVAL_DEC設定。
 /// レジスタアドレス。
 L6470_write(0x0C);
 // モータ減速中の電圧設定(8bit)
 L6470_write(0xFF);
 
 // OCD_TH設定。
 /// レジスタアドレス。
 L6470_write(0x13);
 // オーバーカレントスレッショルド設定(4bit)
 L6470_write(0x0F);
 
 // STALL_TH設定。
 /// レジスタアドレス。
 L6470_write(0x14);
 // ストール電流スレッショルド設定(4bit)
 L6470_write(0x7F);
}

void L6470_run(long speed)
{
 unsigned short dir;
 unsigned long spd;
 unsigned char spd_h;
 unsigned char spd_m;
 unsigned char spd_l;
 
 // 方向検出。
 if (speed < 0)
 {
  dir = 0x50;
  spd = -1 * speed;
 }
 else
 {
  dir = 0x51;
  spd = speed;
 }
 
 // 送信バイトデータ生成。
 spd_h = (unsigned char)((0x0F0000 & spd) >> 16);
 spd_m = (unsigned char)((0x00FF00 & spd) >> 8);
 spd_l = (unsigned char)(0x00FF & spd);
 
 // コマンド(レジスタアドレス)送信。
 L6470_write(dir);
 // データ送信。
 L6470_write(spd_h);
 L6470_write(spd_m);
 L6470_write(spd_l);
}