0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-04-02

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

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

転送速度

転送速度を 19200bps に変更します。
これはATmega328で 115200bps の転送は荷が重い為です。

Serial.begin(19200);

速度計:PWM出力

ArduinoUno は数字の横に がついているものが PWM出力 できるポートになります。
3,5,6,9,10,11の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

BveSerialOutputの設定

BveSerialOutputはドア状態,速度を出力するようにしました。
なお、固定文字列には  , を入れます。
image.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で速度計とパイロットランプ、走行表示灯が制御できたと思います。
なお、リレーの使い方はこちらを参照ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0