手持ちの便利デバイス 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 コメント:
コメントを投稿