手持ちの便利デバイス Arduino Uno R3 を、ドライバー不要のヒューマンインターフェースデバイス(USBゲームパッド)にするよ。
(Arduino Leonardoを使うともっと簡単だよ!!)
Arduino UNO Big Joystick HID firmware
スーパー便利なファームウェアが公開されているので、これを使ってかんたん実現!
やりかた
1.ポルコンシフターをArduinoに接続する
こんなmini-Din6pinメス→バラ端子のコネクターを作ったよ。
ピンアサインはスケッチ参照。
2.いったん下記スケッチを書き込む
Arduinoエディタのシリアル通信窓(115200bps)で、各ギア位置にレバーを持っていったときの x=*** y=*** の数値をメモ
3.測定した数値をもとにスケッチの下記部分の数字を編集し、正しい動作になるか再チェック
#define value_X_R 570
#define value_X_12 540
#define value_X_34 240
#define value_X_56 050
#define value_Y_R135 450
#define value_Y_246 040
↑これがうちのポルコンシフターから拾った数値をざっくり入力したもの。
1速/2速や5速/6速でx軸の数値が変わったりするけど、隣の列との間のうまく動く数値に調整しよう!ちゃんと動けばアバウトな数値でOK!
この数値をもとに、閾値を計算している。
書き込み後、シリアル通信窓で gear= の部分がうまくうごけばOK。
ポルコンシフターの仕組みは、レバーにXYの2軸の抵抗値を読み取るアナログポテンショメーターがついてて、その抵抗値を読んでレバー位置を判定する仕組み。アナログなので個体差が出るから、ポルコン本体ではキャリブレーションが必須なんだね。
4.本番スケッチを書き込む
#define DEBUG
行を、
#undef DEBUG
にしてから転送
5.Unoをdfuモードにし、HIDファームウェアを書き込む
dfu-programmerが必要。
やりかたは、冒頭のファームウェア公開ページをよく読んでね!
(1)Arduino基板上のピンをショートさせる
(2)コマンドライン上で指定のコマンドを打ち込む
6.完成!
良さそうなHシフターが発売されるまではこれでいける!
以下、よく理解してないけどどうやら動くスケッチを公開!
/* Fanatec Shifter USB Adapter with Arduino Uno R3 Author: ukfunk 2014 derived from http://hunt.net.nz/users/darran/weblog/15f92/Arduino_UNO_Big_Joystick_HID_firmware.html Shifter Pin Assign mini-Din 6 pin (female socket) _1 2_ 1:Y-axis 2:X-axis 3 4 3:GND 4:3.3V 5[]6 5:mode 6:N/C please connect 1,2,3,4 pins to Arduino (When the 6+1 gated shifter is connected pins 5 and 3 are jumped together to tell the wheel that the gated shifter is conected.) */ #define DEBUG // #define DEBUG mode #undef HID mode #define pinY A0 // Y-axis analog input (mini-Din pin 1) #define pinX A1 // X-axis analog input (mini-Din pin 2) // set individuality of your shifter using DEBUG mode #define value_X_R 570 #define value_X_12 540 #define value_X_34 240 #define value_X_56 50 #define value_Y_R135 450 #define value_Y_246 40 // axis thresholds calculation const int threshold_X_R1 = (value_X_R + value_X_12)/2; const int threshold_X_13 = (value_X_12 + value_X_34)/2; const int threshold_X_35 = (value_X_34 + value_X_56)/2; const int threshold_Y_R135 = value_Y_R135 - (value_Y_R135 - value_Y_246)/5; const int threshold_Y_246 = value_Y_246 + (value_Y_R135 - value_Y_246)/5; int gear = 0; int pastgear = 0; int yvalue = (value_Y_R135 - value_Y_246)/2; int xvalue = value_X_34; int xp = 0; #define NUM_BUTTONS 40 #define NUM_AXES 8 // 8 axes, X, Y, Z, etc typedef struct joyReport_t { int16_t axis[NUM_AXES]; uint8_t button[(NUM_BUTTONS+7)/8]; // 8 buttons per byte } joyReport_t; joyReport_t joyReport; void setup(void); void loop(void); void setButton(joyReport_t *joy, uint8_t button); void clearButton(joyReport_t *joy, uint8_t button); void sendJoyReport(joyReport_t *report); void setup(){ Serial.begin(115200); delay(200); for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) { joyReport.button[ind] = 0; } } // Send an HID report to the USB interface void sendJoyReport(struct joyReport_t *report){ #ifndef DEBUG Serial.write((uint8_t *)report, sizeof(joyReport_t)); #else // check individuality of your shifter Serial.print(\"x= \"); Serial.print(xvalue); Serial.print(\"\\ty= \"); Serial.print(yvalue); Serial.print(\"\\tgear=\"); Serial.print(gear); Serial.println(); // dump human readable output for debugging for (uint8_t ind=0; ind<NUM_BUTTONS/8; ind++) { Serial.print(\"button[\"); Serial.print(ind); Serial.print(\"]= \"); Serial.print(report->button[ind], HEX); Serial.print(\" \"); } Serial.println(); delay(1000); #endif } // turn a button on void setButton(joyReport_t *joy, uint8_t button) { uint8_t index = button/8; uint8_t bit = button - 8*index; joy->button[index] |= 1 << bit; } // turn a button off void clearButton(joyReport_t *joy, uint8_t button) { uint8_t index = button/8; uint8_t bit = button - 8*index; joy->button[index] &= ~(1 << bit); } void loop(){ // get gear position yvalue = analogRead(pinY); if (yvalue > threshold_Y_R135){ gear = xposition(); } else if (yvalue < threshold_Y_246){ gear = xposition() + 1; } else { gear = 0; } // set output status if (pastgear == gear){ ;// do nothing } else if (pastgear == 0 && gear > 0){ setButton(&joyReport, gear-1); } else if (pastgear > 0 && gear == 0){ clearButton(&joyReport, pastgear-1); } else { setButton(&joyReport, gear-1); clearButton(&joyReport, pastgear-1); } sendJoyReport(&joyReport); pastgear = gear; delay(10); } int xposition(){ xvalue = analogRead(pinX); if (xvalue > threshold_X_R1 && yvalue > threshold_Y_R135) {xp = 7;} // Reverse Gear else if (xvalue > threshold_X_13) {xp = 1;} // 1-2 else if (xvalue < threshold_X_35) {xp = 5;} // 5-6 else {xp = 3;} // 3-4 return xp; }
0 コメント:
コメントを投稿