BVE 鉄道シミュレーターで自宅運転台を動かそう～電車でGoコントローラーを使う～

BVE 鉄道シミュレーターで自宅運転台を動かそう～準備編～の続きになります。
https://qiita.com/usashirou/items/f99effc0651ff35ead9c
今回は、電車でＧｏコントローラーを改造してＢＶＥを動かしてみます。
#BVEの外部プラグインでコントール
BVEはプラグインを追加することで入力機器や外部出力で動作する機器を追加できます。
今回は、BVEの入力インタフェースとATSプラグインを使用して電車を動かしてみましょう。
入力インタフェースはキーボードや外部コントローラーから車両を運転できるようにするプラグインになります。
保安装置プラグインは、車両からの情報を出力するために使います。
初めに外部コントローラーを使えるようにしましょう。
#外部コントローラーを使えるようにする
今回は初代電車でGoコントローラーのワンハンドル版を使用できるようにします。
なお、現在販売されているUSB版やコンバーターを使用すれば無加工で使用できるようです。
#改造
まずは、隠しネジを外して分解していきます。
初代電車でGoコントローラーはマスコンの位置に応じて可変抵抗で電圧を変化させています。
なお、ブレーキとマスコンで２つの可変抵抗がついており、どちらの出力も読み取る必要があります。
今回は、この可変抵抗とボタンの出力をArduinoUnoで検出します。
ArduinoUnoから3.3VとGND、検出用のGPIOとしてアナログ入力がありA0~A5のうちの2個及びキーのABC,Start,Selectの5個のデジタル入力を使用するため基板から外にジャンパーケーブルを出します。
なお、元のケーブルは使う可能性がある為、私は残しましたが、切っても問題ないと思います。
__注：入力する電源は3.3Vを使用してください__
![DSC_0773 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e646b8c0-bc50-9ae5-94e8-73696c370966.jpeg)
そして、元に戻します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c6368bc4-3cc7-01f9-0977-bfc385491047.png)
#コントローラーとArduinoUnoをつなげた様子
![DSC_0071 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/ec942a2f-49ea-7090-be4a-80dfde479b48.jpeg)
#入力プラグイン
標準でいくつかのコントローラーに対応していますが、Arduinoの入力を受け取れるプラグインを追加しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/10638f8d-82f4-62fc-0adb-d72b51d41f1b.png)
三八電車店さんのUniversalContactInterface(UCI)を使用します。
http://saha209kame.web.fc2.com/BVE_ATSPI.html
標準だと__C:\Program Files (x86)\mackoy\BveTs5\Input Devices__にプラグインを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/bf4cdfc7-6461-9f81-e7d5-7bfcbc5d1bfd.png)
ダウンロードした__UniversalContactInterface.dll__を__Inputs__フォルダに置きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/cc8b13f0-c795-3d42-e969-35b89f4973c8.png)
セキュリティ警告が出ますが続行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/7c2fad44-6bbe-b23d-2158-9359688e1ec0.png)
__UniversalContactInterface__が表示されています。
これでUniversalContactInterfaceが使用できるようになります。
BVEを起動して入力プラグインの項目に__UniversalContactInterface__があることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/95ce7dd2-00d6-22b8-1bb7-c99707091c56.png)
プロパティを開けることで中の設定を変えることが可能です。
例えば、ABCのスイッチにホーンを割り当てたりといったことが可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c8c05c47-e0f8-eaab-c1bc-604bf1d63914.png)
ArduinoをつなげたCOMポートを選択してOKをクリックします。
#電圧を調べる
三八電車店さんですでにArduinoのプログラムが用意されていますが、このままでは使えない為、修正しましょう。
最初に可変抵抗の値を把握しましょう。
可変抵抗の値をanalogReadを使用して1ノッチ毎に把握しておきましょう。
analogReadはすべてのＧＰＩＯピンで使用することは出来ません。
ArduinoUnoやNanoの場合Axピンが該当します。
以下はArduinoUnoで試した例です。

```
Brake
EB: 630
B8:375
B7:333
B6:292
B5:250
B4:208
B3:166
B2:125
B1:83
B0:41

Mascon
P0:83
P1:166
P2:250
P3:334
P4:418
P5:502
```
#流用するプログラム
今回は__ねぎ味噌BVE公開所__さんのプログラムを流用します。
valとして40分の１の値で判断するようにします。
http://kongoexp165hakureirw.blog.fc2.com/blog-entry-5.html
これを先の三八電車店さんのプログラムに挿入します。
#プログラム
使用したプログラムは以下です。
まだ修正可能な場所がいくつかあると思いますがとりあえず動くようになりました。
UniversalContactInterfaceで加速にするにはB0が必要なのでB0＋Pxが出力されるようにしています。

```
const int maspin = A3;//マスコンの可変抵抗を接続するピンを選択
const int brpin = A2;//ブレーキの可変抵抗を接続するピンを選択

int NOWBR = 0;
int BEFORBR = 0;

int NOWMC = 0;
int BEFORMC = 0;

const int DEAD = 4;
int DEADsw = 0;
int NOWDEAD = 0;
int BEFORDEAD = 0;

const int REBF = 11;
int REBFsw = 0;
const int REBR = 12;
int REBRsw = 0;

const int SW0 = 5;
int SW0sw = 0;
int NOWSW0 = 0;
int BEFORSW0 = 0;
const int SW1 = 6;
int SW1sw = 0;
int NOWSW1 = 0;
int BEFORSW1 = 0;
const int SW2 = 7;
int SW2sw = 0;
int NOWSW2 = 0;
int BEFORSW2 = 0;
const int SW3 = 8;
int SW3sw = 0;
int NOWSW3 = 0;
int BEFORSW3 = 0;
const int SW4 = 9;
int SW4sw = 0;
int NOWSW4 = 0;
int BEFORSW4 = 0;
const int SW5 = 10;
int SW5sw = 0;
int NOWSW5 = 0;
int BEFORSW5 = 0;

int NOWREB = 0;
int BEFORREB = 0;

int ON = LOW;
int OFF = HIGH;

void setup() {
  pinMode(DEAD, INPUT_PULLUP);
  pinMode(REBF, INPUT_PULLUP);
  pinMode(REBR, INPUT_PULLUP);
  pinMode(SW0, INPUT_PULLUP);
  pinMode(SW1, INPUT_PULLUP);
  pinMode(SW2, INPUT_PULLUP);
  pinMode(SW3, INPUT_PULLUP);
  pinMode(SW4, INPUT_PULLUP);
  pinMode(SW5, INPUT_PULLUP);

  Serial.begin(19200);
  while (!Serial);
}

void loop() {
  int current = analogRead(maspin);
  int brake = analogRead(brpin);
  int bval = brake / 40; //1～1023割る1ノッチ当たりの範囲 intは小数点以下切り捨てを利用
  int mval = current / 40; //1～1023割る1ノッチ当たりの範囲 intは小数点以下切り捨てを利用

  DEADsw = digitalRead(DEAD);
  REBFsw = digitalRead(REBF);
  REBRsw = digitalRead(REBR);

  SW0sw = digitalRead(SW0);
  SW1sw = digitalRead(SW1);
  SW2sw = digitalRead(SW2);
  SW3sw = digitalRead(SW3);
  SW4sw = digitalRead(SW4);
  SW5sw = digitalRead(SW5);
  
  //スイッチ
  if (SW0sw == ON) {
    NOWSW0 = 1;
  }
  if (SW0sw == OFF) {
    NOWSW0 = 0;
  }
  if (NOWSW0 != BEFORSW0) {
    if (NOWSW0 == 1) {
      Serial.print("S0\r");
    }
    if (NOWSW0 == 0) {
      Serial.print("S100\r");
    }
  }
  BEFORSW0 = NOWSW0;

  if (SW1sw == ON) {
    NOWSW1 = 1;
  }
  if (SW1sw == OFF) {
    NOWSW1 = 0;
  }
  if (NOWSW1 != BEFORSW1) {
    if (NOWSW1 == 1) {
      Serial.print("S1\r");
    }
    if (NOWSW1 == 0) {
      Serial.print("S101\r");
    }
  }
  BEFORSW1 = NOWSW1;

  if (SW2sw == ON) {
    NOWSW2 = 1;
  }
  if (SW2sw == OFF) {
    NOWSW2 = 0;
  }
  if (NOWSW2 != BEFORSW2) {
    if (NOWSW2 == 1) {
      Serial.print("S2\r");
    }
    if (NOWSW2 == 0) {
      Serial.print("S102\r");
    }
  }
  BEFORSW2 = NOWSW2;

  if (SW3sw == ON) {
    NOWSW3 = 1;
  }
  if (SW3sw == OFF) {
    NOWSW3 = 0;
  }
  if (NOWSW3 != BEFORSW3) {
    if (NOWSW3 == 1) {
      Serial.print("S3\r");
    }
    if (NOWSW3 == 0) {
      Serial.print("S103\r");
    }
  }
  BEFORSW3 = NOWSW3;

  if (SW4sw == ON) {
    NOWSW4 = 1;
  }
  if (SW4sw == OFF) {
    NOWSW4 = 0;
  }
  if (NOWSW4 != BEFORSW4) {
    if (NOWSW4 == 1) {
      Serial.print("S4\r");
    }
    if (NOWSW4 == 0) {
      Serial.print("S104\r");
    }
  }
  BEFORSW4 = NOWSW4;

  if (SW5sw == ON) {
    NOWSW5 = 1;
  }
  if (SW5sw == OFF) {
    NOWSW5 = 0;
  }
  if (NOWSW5 != BEFORSW5) {
    if (NOWSW5 == 1) {
      Serial.print("S5\r");
    }
    if (NOWSW5 == 0) {
      Serial.print("S105\r");
    }
  }
  BEFORSW5 = NOWSW5;

  //レバーサ
  if (REBFsw == ON && REBRsw == OFF) {
    NOWREB = 1;
  }
  if (REBFsw == OFF && REBRsw == OFF) {
    NOWREB = 0;
  }
  if (REBFsw == OFF && REBRsw == ON) {
    NOWREB = 2;
  }
  if (NOWREB != BEFORREB) {
    if (NOWREB == 0) {
      Serial.print("RN\r");
    }
    if (NOWREB == 1) {
      Serial.print("RF\r");
    }
    if (NOWREB == 2) {
      Serial.print("RB\r");
    }
  }
  BEFORREB = NOWREB;

  //デッドマン
  if (DEADsw == ON) {
    NOWDEAD = 1;
  }
  if (DEADsw == OFF) {
    NOWDEAD = 0;
  }
  if (NOWDEAD == 0 && NOWDEAD != BEFORDEAD && (NOWBR == 0 || NOWMC != 0)) {
    Serial.print("B998\r");
  }

  BEFORMC = NOWMC;
  BEFORDEAD = NOWDEAD;

  //ブレーキ

  if (bval == 1) {
    NOWBR = 0; //制動N段
  }
  if (bval == 2) {
    NOWBR = 1; //制動1段
  }
  if (bval == 3) {
    NOWBR = 2; //制動2段
  }
  if (bval == 4) {
    NOWBR = 3; //制動3段
  }
  if (bval == 5) {
    NOWBR = 4; //制動4段
  }
  if (bval == 6) {
    NOWBR = 5; //制動5段
  }
  if (bval == 7) {
    NOWBR = 6; //制動6段
  }
  if (bval == 8) {
    NOWBR = 7; //制動7段
  }
  if (bval == 9) {
    NOWBR = 8; //制動8段
  }
  if (bval == 15) {
    NOWBR = 9; //制動EB段
  }
  if (NOWBR == 0) {
  //  Serial.print("B0\r");
  }
  if (NOWBR == 1) {
    Serial.print("B1\r");
  }
  if (NOWBR == 2) {
    Serial.print("B2\r");
  }
  if (NOWBR == 3) {
    Serial.print("B3\r");
  }
  if (NOWBR == 4) {
    Serial.print("B4\r");
  }
  if (NOWBR == 5) {
    Serial.print("B5\r");
  }
  if (NOWBR == 6) {
    Serial.print("B6\r");
  }
  if (NOWBR == 7) {
    Serial.print("B7\r");
  }
  if (NOWBR == 8) {
    Serial.print("B8\r");
  }
  if (NOWBR == 9) {
    Serial.print("B998\r");
  }
  if (NOWBR == 0) {
    if (mval == 2) {
      NOWMC = 0; //力行N段
    }
    if (mval == 4) {
      NOWMC = 1; //力行1段
    }
    if (mval == 6) {
      NOWMC = 2; //力行2段
    }
    if (mval == 8) {
      NOWMC = 3; //力行3段
    }
    if (mval == 10) {
      NOWMC = 4; //力行4段
    }
    if (mval == 12) {
      NOWMC = 5; //力行5段
    }
  }


  if (NOWMC != BEFORMC) {
    if (NOWMC == 0) {
      Serial.print("B0\r");
      Serial.print("P0\r");
    }
    if (NOWMC == 1) {
      Serial.print("B0\r");
      Serial.print("P1\r");
    }
    if (NOWMC == 2) {
      Serial.print("B0\r");
      Serial.print("P2\r");
    }
    if (NOWMC == 3) {
      Serial.print("B0\r");
      Serial.print("P3\r");
    }
    if (NOWMC == 4) {
      Serial.print("B0\r");
      Serial.print("P4\r");
    }
    if (NOWMC == 5) {
      Serial.print("B0\r");
      Serial.print("P998\r");
    }
  }
  delay(10);
}
```
これで外部コントローラーが使えるようになったと思います。
#引用・著作権表示
© 2020 mackoy
© 三八電車店
© ねぎ味噌BVE公開所