BVE 鉄道シミュレーターで自宅運転台を動かそう~Arduino Unoで動かす

BVE 鉄道シミュレーターで自宅運転台を動かそう~パイロットランプをつけるの続編として

https://qiita.com/usashirou/items/ff696eb86201bd0670e7

ArduinoUnoで速度計とパイロットランプを動かす方法を記します。
ArduinoUnoだけでなく、ArduinoNanoなどのATmega328系のマイコンボードでも対応可能です。
主な変更箇所は、転送速度と速度計のDACをanalogwriteに変更することです。

## 転送速度
転送速度を __19200bps__ に変更します。
これはATmega328で __115200bps__ の転送は荷が重い為です。

    Serial.begin(19200);

## 速度計：PWM出力
__ArduinoUno__ は数字の横に __～__ がついているものが __PWM出力__ できるポートになります。
３，５，６，９，１０，１１の5ピンが使用可能です。
##  注意：5・6番ピンはデューティー比の問題がある為使わない方が良いようです。
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2153
今回は5番ピンを使用していますが、実際の場合は、別のピンを指定してください。
 
    analogWrite(ピン番号, 速度 * 補正);

## パイロットランプ・走行表示灯：LED出力
ドア状態を2番に出力します。
後で使用する走行表示灯は3番にしました。
BVEはドアが開くと1に閉まると0になるので

    1⇒HIGH
    0⇒LOW
にします。

      if (dai0 == 1) {
        digitalWrite(2, HIGH );
      }
      if (dai0 == 0) {
        digitalWrite(2, LOW );
      }
## 配線の様子
今回は、リレーをLEDの代わりにつないで説明します。
5番ピンに可変抵抗をつなげます。
LEDのマイナス側に2，3番ピンをつなげ、電源とLEDの間に抵抗をつなげます。
これで2，3番ピンはLOWになる事で点灯する回路となります。
![DSC_0163 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a1393d06-4718-d5bc-8833-6fcc3ac38a81.jpeg)
# BveSerialOutputの設定
BveSerialOutputはドア状態,速度を出力するようにしました。
なお、固定文字列には　 __,__　を入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/180eb25b-8a96-9222-0539-491b5bbd8fec.png)
## プログラム
```
//https://qiita.com/Ninagawa_Izumi/items/6a18249a31a87dad84e2
char dai0;  //2つのデータを扱うのでdai0とdai1を用意します。
char dai1;

#define elements 2 //カンマで区切るデータの最大項目数　今回は2個
String data_string; //シリアルで受け取る全文字列
char *p; //文字列をカンマで分割するstrtok処理で使うポインタ
String p_string; //上記ポインタで区切った文字列の仮格納用
String data_array[elements]; //カンマ分割されたstrデータを格納する

void setup() {
  pinMode(2, OUTPUT); //出力ピンを設定します。
  pinMode(5, OUTPUT);

  Serial.begin(19200);
  Serial.setTimeout(10); // タイムアウトの時間を10msに変更
}

void loop() {
  if (Serial.available() > 2 ) {
    data_string = Serial.readStringUntil(0x0a); //シリアルデータを改行記号が現れるまで読み込む
    data_string.trim(); //文字列を念のためトリミングする
    int data_len = data_string.length() + 1; //str→char変換用にデータの長さを調べる
    char data_char[data_len]; //str→char変換用のchar配列を準備
    data_string.toCharArray(data_char, data_len); //ようやくstr→charに変換
    p = strtok(data_char, ","); //カンマ分割の1要素目を行う
    p_string = p; //一旦strにいれる
    data_array[0] = p_string; //最終目的の配列に1要素目を格納

    for (int i = 1; i < elements; i++) { //2要素名以降について、要素数分だけデータ配列に格納
      p = strtok(NULL, ","); //カンマ分割の2要素目以降のstrtokはこの書式になる
      if (p != NULL) { //要素が空でない場合はその要素をデータ配列に格納
        p_string = p;
        data_array[i] = p_string;
      } else {
        data_array[i] = "0"; //要素が空の場合はデータ配列に0を格納
      }
    }
    //データを表示する
    for (int i = 0; i < elements ; i++) {
      dai0 = data_array[0].toInt();
      if (dai0 == 1) {
        digitalWrite(2, HIGH );
      }
      if (dai0 == 0) {
        digitalWrite(2, LOW );
      }

      dai1 = data_array[1].toInt();
      if (dai1 >= 0 && dai1 <= 125) {
        analogWrite(5, dai1 * 1.45);　//補正値を修正する
      }

    }
    Serial.println();
  }
}
```
# 走行表示灯を点ける
少し改造します。
走行表示灯は時速5kや10Kで点灯します。
今回は10Km/hになると点灯するようにします。

      if (dai1 >= 10) {
        digitalWrite(3, LOW );
      }
      if (dai1 < 10) {
        digitalWrite(3, HIGH );
      }
# プログラム
プログラムです。
```
//https://qiita.com/Ninagawa_Izumi/items/6a18249a31a87dad84e2
char dai0;
char dai1;

#define elements 2 //カンマで区切るデータの最大項目数
String data_string; //シリアルで受け取る全文字列
char *p; //文字列をカンマで分割するstrtok処理で使うポインタ
String p_string; //上記ポインタで区切った文字列の仮格納用
String data_array[elements]; //カンマ分割されたstrデータを格納する

void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);

  Serial.begin(19200);
  Serial.setTimeout(10);        // タイムアウトの時間を10msに変更
}

void loop() {
  if (Serial.available() > 2 ) {
    data_string = Serial.readStringUntil(0x0a); //シリアルデータを改行記号が現れるまで読み込む
    data_string.trim(); //文字列を念のためトリミングする
    int data_len = data_string.length() + 1; //str→char変換用にデータの長さを調べる
    char data_char[data_len]; //str→char変換用のchar配列を準備
    data_string.toCharArray(data_char, data_len); //ようやくstr→charに変換
    p = strtok(data_char, ","); //カンマ分割の1要素目を行う
    p_string = p; //一旦strにいれる
    data_array[0] = p_string; //最終目的の配列に1要素目を格納

    for (int i = 1; i < elements; i++) { //2要素名以降について、要素数分だけデータ配列に格納
      p = strtok(NULL, ","); //カンマ分割の2要素目以降のstrtokはこの書式になる
      if (p != NULL) { //要素が空でない場合はその要素をデータ配列に格納
        p_string = p;
        data_array[i] = p_string;
      } else {
        data_array[i] = "0"; //要素が空の場合はデータ配列に0を格納
      }
    }
    //データを表示する
    for (int i = 0; i < elements ; i++) {
      dai0 = data_array[0].toInt();
      if (dai0 == 1) {
        digitalWrite(2, HIGH );
      }
      if (dai0 == 0) {
        digitalWrite(2, LOW );
      }

      dai1 = data_array[1].toInt();
      if (dai1 >= 0 && dai1 <= 125) {
        analogWrite(5, dai1 * 1.45);
      }
      if (dai1 >= 10) {
        digitalWrite(3, LOW );
      }
      if (dai1 < 10) {
        digitalWrite(3, HIGH );
      }
    }
    Serial.println();
  }
}
```
以上でArduinoUnoで速度計とパイロットランプ、走行表示灯が制御できたと思います。
なお、リレーの使い方はこちらを参照ください。

https://qiita.com/usashirou/items/6860911a88e6c5b0c7a5