プレステコントローラの接続
回路図はコレ
本来はSPIのハードウエア機能で通信すると速く美しいのですが、まずは移植性も良いIOポート使用のプログラムになっています。
現在プレステコントローラは入手困難です。
ヴィストンで扱っていますロボットコントローラーVS-C1を使われてください。
以下ソースコードは動作確認済みなります。(基本プログラムがベースになっております。)
このソースは富山研究室の池田君から頂きました!感謝!
アナログモードで使用してください。
LCDに表示がでるようになっています。全てのボタンの情報が表示されるので確認できます。
追加******
下のソースを貼付けても上手く動かないという話を聞きますので、動くソースを丸ごとダンロードしてください。
※[Release]モードでビルドしてください。
サーボはD1/D2/D3/D4で動く設定にしてあります。もっとたくさんのサーボを動かしたい場合は
以下ソースでサーボが動かないのはDevInit_F2803x.cのピン設定がPWMになっていないからだと思われます。
↓
ソースコード
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File #include "NolibM.h" #include <stdio.h> #define PS_CON_DAT GpioDataRegs.GPADAT.bit.GPIO12 /* 入力に設定 */ #define PS_CON_CMD GpioDataRegs.GPADAT.bit.GPIO13 /* 出力に設定 */ #define PS_CON_SEL GpioDataRegs.GPADAT.bit.GPIO27 /* 出力に設定 */ #define PS_CON_CLK GpioDataRegs.GPADAT.bit.GPIO26 /* 出力に設定 */ #define ZERO_PM 10 /* ジョイスティックの不感帯の幅 */ volatile struct EPWM_REGS *ePWM[] = { &EPwm1Regs, //intentional: (ePWM[0] not used) &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs, &EPwm6Regs, &EPwm7Regs, }; /* コントローラの情報を収納する構造体の定義 */ struct PS_CMD{ unsigned char dat[34]; unsigned char length; }; // These are defined by the linker (see F2808.cmd) extern Uint16 RamfuncsLoadStart; extern Uint16 RamfuncsLoadEnd; extern Uint16 RamfuncsRunStart; // Watch Viewでの値表示用にglobal変数として宣言 int16 speed; Uint16 sen1,sen2,sen3,sen4; // ボタン用の変数 unsigned char ll ,dd, rr, uu; // 左、下、右、上 unsigned char st, R3, L3, se; // スタート、右ジョイスティックスイッチ、左ジョイスティックスイッチ、セレクト unsigned char ss, xx, cc, tt; // しかく、ばつ、まる、さんかく unsigned char R1, L1, R2, L2; // R1、L1、R2、L2 char right_ud, right_lr; // 右ハンドル上下、右ハンドル左右 char left_ud, left_lr; // 左ハンドル上下、左ハンドル左右 /******************************** * プレステ用コントローラの状態の読み取り *******************************/ #define SPI_DELAY 400 void pscon_read(struct PS_CMD *psmd) { int i,j; for(i=0;i<35;i++){ //配列ゼロ初期化 psmd->dat[i] = 0; } PS_CON_SEL = 1; DSP28x_usDelay(SPI_DELAY); PS_CON_SEL = 0; DSP28x_usDelay(SPI_DELAY); PS_CON_CLK = 1; PS_CON_CMD = 0; DSP28x_usDelay(SPI_DELAY); for(i=0; i<8; i++){ //1バイト目コマンドを送る 0x01 PS_CON_CLK = 1; DSP28x_usDelay(SPI_DELAY); PS_CON_CMD = (0x01 >> i) & 0x01; // DSP28x_usDelay(SPI_DELAY); PS_CON_CLK = 0; DSP28x_usDelay(SPI_DELAY); } DSP28x_usDelay(2*SPI_DELAY); //------ for(i=0; i<8; i++){ //2バイト目コマンドを送る 0x42 PS_CON_CLK = 1; // DSP28x_usDelay(SPI_DELAY); PS_CON_CMD = (0x42 >> i) & 0x01; DSP28x_usDelay(SPI_DELAY); PS_CON_CLK = 0; DSP28x_usDelay(SPI_DELAY); psmd->dat[0] |= (PS_CON_DAT & 0x01) << i; //データを読み込む } psmd->length = (0x0F & psmd->dat[0])*2; if(psmd->length > 32){ psmd->length = 32; } if(psmd->length == 0){ psmd->length = 32; } DSP28x_usDelay(2*SPI_DELAY); for(i=0; i<8; i++){ //3バイト目コマンド0x00 PS_CON_CLK = 1; DSP28x_usDelay(SPI_DELAY); PS_CON_CMD = 0; PS_CON_CLK = 0; DSP28x_usDelay(SPI_DELAY); psmd->dat[1] |= (PS_CON_DAT & 0x01) << i; //データ読み込み } PS_CON_CLK = 1; DSP28x_usDelay(SPI_DELAY); for(i=0; i<psmd->length; i++){ //種類によって読み込む情報量が違う psmd->dat[i+2] = 0; for(j=0; j<8; j++){ PS_CON_CLK = 1; DSP28x_usDelay(SPI_DELAY); PS_CON_CLK = 0; DSP28x_usDelay(SPI_DELAY); psmd->dat[i+2] |= (PS_CON_DAT & 0x01) << j; } } PS_CON_CLK = 1; DSP28x_usDelay(SPI_DELAY); PS_CON_SEL = 1; //DSP28x_usDelay(10000); //------ } void main(void) { int i; int cnt; int right_spd, left_spd; struct PS_CMD sts; char msg1[16],msg2[16]; initNolibM(); //初期化 GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // 0=GPIO, 1=TZ1, 2=SCITX-A, 3=SPISIMO-B GpioCtrlRegs.GPADIR.bit.GPIO12 = 0; // 1=OUTput, 0=INput GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; // 0=GPIO, 1=TZ2, 2=Resv, 3=SPISOMI-B GpioCtrlRegs.GPADIR.bit.GPIO13 = 1; // 1=OUTput, 0=INput GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 0; // 0=GPIO, 1=Resv, 2=Resv, 3=SPICLK-B GpioCtrlRegs.GPADIR.bit.GPIO26 = 1; // 1=OUTput, 0=INput GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 0; // 0=GPIO, 1=Resv, 2=Resv, 3=SPISTE-B GpioCtrlRegs.GPADIR.bit.GPIO27 = 1; // 1=OUTput, 0=INput motor(0, MotCN3); motor(0, MotCN4); motor(0, MotCN5); motor(0, MotCN6); wait(10); ledFlash(OFF,1); ledFlash(OFF,2); ledFlash(OFF,3); ledFlash(OFF,4); cnt = 1; for(i=0;i<34;i++){ sts.dat[i] = 0; } right_ud = 0; left_ud = 0; while(1) { pscon_read(&sts); // コントローラの状態を読み取る // コントローラの情報をLCDに表示 sprintf(msg1,"%02x %02x %02x %02x %2d",sts.dat[0], sts.dat[1], sts.dat[2], sts.dat[3], sts.length); sprintf(msg2,"%02x %02x %02x %02x %1d",sts.dat[4], sts.dat[5], sts.dat[6], sts.dat[7], cnt); lcd_HOME();//カーソルをホームへ lcd_PUTS((unsigned char *)msg1); lcd_LF(); lcd_PUTS((unsigned char *)msg2); // 読取データをそれぞれの変数に分割 if(sts.dat[1] == 0x5a){ if(sts.length >= 2){ ll = (0x80 & ~sts.dat[2]) >> 7; dd = (0x40 & ~sts.dat[2]) >> 6; rr = (0x20 & ~sts.dat[2]) >> 5; uu = (0x10 & ~sts.dat[2]) >> 4; st = (0x08 & ~sts.dat[2]) >> 3; R3 = (0x04 & ~sts.dat[2]) >> 2; L3 = (0x02 & ~sts.dat[2]) >> 1; se = (0x01 & ~sts.dat[2]); ss = (0x80 & ~sts.dat[3]) >> 7; xx = (0x40 & ~sts.dat[3]) >> 6; cc = (0x20 & ~sts.dat[3]) >> 5; tt = (0x10 & ~sts.dat[3]) >> 4; R1 = (0x08 & ~sts.dat[3]) >> 3; L1 = (0x04 & ~sts.dat[3]) >> 2; R2 = (0x02 & ~sts.dat[3]) >> 1; L2 = (0x01 & ~sts.dat[3]); } if(sts.length >= 6){ // 不感帯の設定 for(i=0; i<4; i++){ if((0x80 - ZERO_PM) < sts.dat[4+i] && sts.dat[4+i] < (0x80 + ZERO_PM)){ sts.dat[4+i] = 0x80; } } right_lr = sts.dat[4] - 0x80; // 左がマイナス -128 ~ +127 right_ud = sts.dat[5] - 0x80; // 上がマイナス -128 ~ +127 left_lr = sts.dat[6] - 0x80; // 左がマイナス -128 ~ +127 left_ud = sts.dat[7] - 0x80; // 上がマイナス -128 ~ +127 } } // 分割終わり if(L2 == 1){ right_spd = right_ud * 35 / 128; left_spd = left_ud * 35 / 128; }else if(R2 == 1){ right_spd = right_ud * 100 / 128; left_spd = left_ud * 100 / 128; }else{ right_spd = right_ud * 70 / 128; left_spd = left_ud * 70 / 128; } motor(right_spd, MotCN3); motor(left_spd, MotCN5); wait(100); // 動作確認用にLEDを順次点滅 if(cnt==1){ ledFlash(TOGGLE,1); }else if(cnt == 2){ ledFlash(TOGGLE,2); }else if(cnt == 3){ ledFlash(TOGGLE,3); }else{ ledFlash(TOGGLE,4); cnt = 0; } cnt++; } // 無限ループ終わり }