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

BVE 鉄道シミュレーターで自宅運転台を動かそう～速度計を動かすの続きです。
https://qiita.com/usashirou/items/8d22cedf303128739911
今回は、運転台についているパイロットランプを点灯させてみます。
パイロットランプはドアが閉まったことを確認するためにあるという解釈で動かします。
BVEではパイロットランプの出力がありますのでこれを認識して動かしてみましょう。

マイコンボードのGPIOにおいて０と１を受信した際に動作する内容を記述します。
プログラムです

```
      if (dai == 1) {
        digitalWrite(2, LOW);
      }
      if (dai == 0) {
        digitalWrite(2, HIGH);
      }
```
ESP32のNodeMCUにはGPIO2にLEDがついており、これでLEDが点滅できるようになります。
それでは、前回の続きとして速度計と、パイロットランプを同時にコントロールしてみましょう。
#BveSerialOutputの設定
__BveSerialOutput__の設定に__ドア状態__と__速度計__を出力するようにしましょう。
__カンマ区切りのデータをarduinoのシリアルで受け取り配列に入れたい__をそのまま引用させていただきます。
https://qiita.com/Ninagawa_Izumi/items/6a18249a31a87dad84e2
このプログラムを使用すると__,__区切りの文字列をdata_arrayという配列に分割してくれるプログラムになります。

配列としても便利ですし、人が見る際にも　__,__　を入れてあげることで速度と、ドア状態が別物であると把握しやすくなります。
__BveSerialOutput__の固定文字として , を入れるようにします。
__速度　, ドア状態__という出力がなされることになります。
私は__速度　, 速度　, 電流　, ドア状態__としました。
![スクリーンショット 2022-01-28 123624.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/24be5d5e-f0a4-8457-4dd2-a2fa2414637f.png)
次は、マイコンのプログラムです。
最初に、すべての文字列を受信するプログラムに変更しましょう。
__カンマ区切りのデータをarduinoのシリアルで受け取り配列に入れたい__を流用させていただき以下のようにしてみました。

今回は、シリアル通信の受信内容を , で区切って個別に処理するプログラムにします。
まずは、data_arrayから　，　で区切ったものをdaiに代入するプログラムにします。

    dai = data_array[].toInt();

動作確認を行うためなので、今回は、すべて同じ速度計のプログラムにしています。
係数を変更することで各自のメータに合わせましょう。
最大電圧255とした値を表示速度で割り、補正しましょう

    ledcWrite(X, dai * XXXX);


#プログラム

```
//引用プログラム　https://qiita.com/Ninagawa_Izumi/items/6a18249a31a87dad84e2
const int dac1 = 25;
const int dac2 = 26;
const int dac3 = 32;
const int dac4 = 33;
char dai1;
char dai2;
char dai3;
char dai4;

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

void setup() {
  pinMode(dac1, OUTPUT);
  pinMode(dac2, OUTPUT);
  pinMode(dac3, OUTPUT);
  pinMode(dac4, OUTPUT);
  pinMode(2, OUTPUT);

  ledcSetup(1, 12800, 8);
  ledcSetup(2, 12800, 8);
  ledcSetup(3, 12800, 8);
  ledcSetup(4, 12800, 8);
  ledcAttachPin(dac1, 1);
  ledcAttachPin(dac2, 2);
  ledcAttachPin(dac3, 3);
  ledcAttachPin(dac4, 4);
  Serial.begin(115200);
　Serial.setTimeout(10);        // タイムアウトの時間を100msに変更
}

void loop() {
  if (Serial.available() > 10 ) {
    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++) {
      Serial.print("A");
      Serial.print(data_array[0]);
      dai1 = data_array[0].toInt();
      if (dai1 >= 0 && dai1 <= 125) {
        ledcWrite(1, dai1 * 1.45);
      }
      dai2 = data_array[1].toInt();
      if (dai2 >= 0 && dai2 <= 125) {
        ledcWrite(2, dai2 * 1.45);
      }
      dai3 = data_array[2].toInt();
      if (dai3 >= 0 && dai3 <= 125) {
        ledcWrite(3, dai3 * 1.45);
      }
        dai4 = data_array[3].toInt();
      if (dai4 == 1) {
        digitalWrite(2, LOW);
      }
      if (dai4 == 0) {
        digitalWrite(2, HIGH);
      }
      Serial.print("B");
      Serial.print(data_array[1]);
      Serial.print("C");
      Serial.print(data_array[2]);
      Serial.print("Door");
      Serial.print(data_array[3]);
      Serial.print("E");
      Serial.print(data_array[4]);
      Serial.print("F");
      Serial.print(data_array[5]);
    }
    Serial.println();
  }
}
```
#BVE出力の状態
BVEを起動すると速度計、速度計、電流、ドア状態が出力され、速度計やLEDが点滅できると思います。
![スクリーンショット 2022-01-28 121554.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/eb5e70f0-a6da-f9f4-5aae-b0432b68e500.png)
#ＢＶＥで動かした映像
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ESP32とArduinoUnoでBVEを動かしてみた <a href="https://t.co/9tXcI20sAR">pic.twitter.com/9tXcI20sAR</a></p>&mdash; usashirou (@usashirou1) <a href="https://twitter.com/usashirou1/status/1490289573196288001?ref_src=twsrc%5Etfw">February 6, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
#外部出力する
今回はESP32のLEDでしたが、GPIO出力を使用することで車側表示灯をリレーで点灯させる事も可能です。
__ArduinoUnoとリレーモジュールで車側表示灯を制御しよう__
https://qiita.com/usashirou/items/6860911a88e6c5b0c7a5
#引用・著作権表示
© 2020 mackoy
© 三八電車店
© ねぎ味噌BVE公開所
© ED67900-5
© ツナギ図laboratory