HOME >> 鉄道模型自動運転システム > 登山鉄道の自動運転システム スケッチの記述
ハード回路の動作チェックもなんとか無事に完了したので、いよいよソフトの出番となった。
.
■ ソフト開発の環境
Arduinoの統合開発環境 Arduino IDE がインストールされているパソコンを準備した。 OSはWindows10 を搭載しており、Wi-fi が備わっているので室内に設置した Wi-fi 基地局との通信も容易である。
まず、ネットより最新のArduino 用ソフトをダウンロードしてインストールする。 バージョンは、1.8.9 であった。 このソフト Arduino IDE を起動させ作動を確認する。 そして、制御機器に取り付けた Arduino のUSB 端子とUSBケーブルを使用して接続する。
この時、Arduino IDE の「ツール」の中の「シリアーポート」を見ると、COMポートとして Arduino を認識しているかどうかをチェックします。 表示されていれば準備完了です。 それでは、いよいよソフト( スケッチと呼ぶ )の記述を開始しましょう。
■ スケッチの概要
記述の順番は、まず最初に初期設定として、ピン番号の定義や関数の定義を記述しておき、次にvoid setup() にて、入出力ポートの使い方をセットアップします。 そして、運行モードを定義する関数を記述しておきます。 昔の人はサブルーチンと呼んでいましたが、古い頭ですね。
そして最後にメインの処理ルーティンを void loop() に記述します。
◆運行モードを記述する関数について
「システム構想」 で示した運行ダイヤの各運行モードを関数として定義しておく。 すなわち、運行ダイヤ図に示した d1() 〜d6() までのモードを関数のDirection 1(densha) 〜 6() として記述しておく。 カッコ内は走行する電車の番号を指定する引数である。 そして、メインループで電車を指定した運行モードを順次記述していく手順である。
// Tozan-Auto-12 2018/3/8 #define Vr1_pin 0 #define Vr2_pin 1 ************* #define P2_PIN 12 #define P1_PIN 13 int t1; int t2; ************ int e5; int duty; void setup() { pinMode(Vr1_pin, INPUT); pinMode(Vr2_pin, INPUT); ************ pinMode(P2_PIN, OUTPUT); pinMode(P1_PIN, OUTPUT); } void direction1(int densha) { if (analogRead(densha) < 400 ) { //電車の設定の有無チェック return; //無の場合はこの運行をパスする } digitalWrite(P1_PIN, LOW); //経路を設定する delay(500); digitalWrite(P2_PIN, LOW); delay(500); digitalWrite(P3_PIN, LOW); delay(500); t1 = digitalRead(T1_PIN); //出発点通過チェック while (t1 == LOW ) { //出発点通過待ち duty = analogRead(densha); //VRの値を読込む duty = (duty - 500) /4; //低速走行 analogWrite(Fl_PIN, 0); //フィーダー出力0 analogWrite(Fr_PIN, duty); //フィーダー出力 t1 = digitalRead(T1_PIN); //出発点通過チェック delay(50); } t2 = digitalRead(T2_PIN); //到着点通過チェック while (t2 == LOW ) { //到着点通過待ち duty = analogRead(densha); //VRの値を読込む duty = (duty - 500) / 3; //通常速度 analogWrite(Fr_PIN, duty); //フィーダー出力 t2 = digitalRead(T2_PIN); //到着点通過チェック delay(50); } e2 = digitalRead(E2_PIN); //到着チェック while (e2 == LOW ) { //到着待ち duty = analogRead(densha); //VRの値を読込む duty = (duty - 500) / 4; //低速走行 analogWrite(Fr_PIN, duty); //フィーダー出力 e2 = digitalRead(E2_PIN); //到着点通過チェック delay(50); } delay(500); analogWrite(Fr_PIN, 0); delay(1000); return; } ***************************************** void loop() { while (digitalRead(UNTEN_PIN) == LOW){ //運行ボタンを待つ delay(200); } direction5(1); //運行ダイヤ第1クール delay(1000); direction1(0); delay(1000); direction3(0); delay(1000); direction4(2); delay(1000); direction2(2); delay(1000); direction6(1); delay(1000); direction5(0); //運行ダイヤ第2クール ********************************* direction5(2); //運行ダイヤ第3クール ********************************* }
運行ダイヤを示す関数は、同じ記述内容のものを6個用意して、その中の異なる項目だけ修正しておけば良いのである。 そこで、それぞれの関数毎に設定する内容を下に示す様に表にしてまとめた。
ポイントへの信号は、直進が LOW で、分岐が HIGH の指令である。 また、フィーダーはNゲージの基本である 右プラスが前進指令 であるので、それに従ってPWM信号を発信する。 監視ポイントとして出発駅側と到着駅側の通過信号と、レールエンドに達した到着信号を監視して、走行状態を把握する。
◆ スケッチの記述内容
右に示すスケッチに従って説明しよう。 なお、****** の部分は途中の部分を省略していることを示す。
● 初期設定:
I/O ポートの番号とスケッチの記述記号とを関係付けておくために、最初に #define 命令で指定する。 さらに使用する変数のデータ型を定義して置く。
そして、void setup() にて入出力ピンのモードを指定する。
● 運行関数の記述:
void direction1(int densha) にて運行関数を記述する。 カッコ内に指定された引数をdensha という変数に引き継ぐ。 そして、最初に電車が設定されているどうかをチェックする。 運行を開始する前に停車していた位置にて、電車1,2,3を決めているが、それに対応して速度設定ボリュームも対応させている。 この時の番号は、0、1、2である。 即ち、densha = 0 が電車1なのだ。
このようにした理由は、もし電車1、即ち densha = 0 の場合、analogRead(densha) で読み取らせるポートは Analog の0番ポートに設定しているからである。
速度設定ボリュームから読み取ったアナログ値が、もし 400 以下であればスイッチがOFFの状態であると判断する。 ON であれば2.5ボルト以上あるので、1023/2 以上の値を示すが、安全を見て400 と設定した。
もし、電車が設定されていなければ電車が無いとみなして、この運行モードを実施せずにパスさせるので、return 命令によって何もせずにこの関数を抜け出すのである。
電車が設定されておれば、まずこの運行経路の設定をポイント操作によって実施しする。 そして、速度設定ボリュームの値に従って、いよいよ電車を発車させるのである。
出発出口まではゆっくりと走行し、中間部は指定の速度で走行させるが、上り坂や下し坂などによって、その値を変えておく必要がある。 なにしろここは急勾配のある登山鉄道なのである。 このために duty という変数を計算させている。
到着地点の入り口を通過すると、レールエンドでの激突を避けるために、減速走行を指定する。 激しくぶつかると電車は脱線してしまうのである。
無事に到着すると、電力供給をゼロに落として、この運行モードを完了し、運行関数を終了させる。
● 運行ダイヤの記述
このスケッチのメインループにおいて、「システム構想」 で示した運行ダイヤに従って、運行モードを記述していく。 この時、関数の引数として指定する電車の番号も入れておく。 指定する電車番号か異なるものの、同じパターンが3回続いて、最初の位置の戻ってくる。 これをワン・サイクルとして、繰り返し実施するようにしている。
ただし、いきなり走り出しては困るので、最初に運行開始の指示する運行ボタンをチェックするようにしている。 運行ボタンがおされれば、運行を開始するのである。
そして、このチェックはワン・サイクル毎に実施する。 すると、途中でこの運行ボタンをOFF にすると、そのサイクルを終了後に、このボタンの状態をチェックするので、各電車は開始状態で停車したままで止まってくれることになる。 ここですべての電源をOFF すると電車を定位置停車した状態で終了させることになる。 このことのメリットは、次回の運行開始がスムースに出来る事なのだ。
■ トラブルの対応
さて、スケッチが記述出来たので、実行させることにしたのだが・・・・・・・・・・・。
ここで失敗した内容を記録しておこう。
◆ コンパイル・エラー
コンパイル実施時にエラーが出てしまいました。 その内容は、
error: stray '\343' in program
error: stray '\200' in program
教則本などを持ち出して記述方法などをチェックしたのですが、間違いを見つける事が出来なかった。 そこで、文法などをネットで検索してみたがなかなか見つからなかった。 そこでダイレクトにエラー文を検索文字として検索すると、ありましたねー! ありがとう!!!
error: stray '\343' in program
error: stray '\200' in program
error: stray '\200' in program
というエラーは全角の空白が原因。
検索をかけて見つけるべし。
さっそく検索をかけてみると、コメントのためのダブル・スラッシュの前に、全角の空白がいっぱい挿入されていました。 コメントを全角文字で記入して、体裁を整えるために全角の空白文字を使用したのが原因でした。 本当に有難うございました。
◆ Arduino に書き込めない
コンパイルエラーをクリアー出来たので、Arduino にUSB を使って書込みを実施しようとしたが、これも拒否された。 シリアルポートの設定もチェックしたのだが間違いない。 ふと気が付いて、I/Oポート類を外して実施したところ、今度は成功した。 原因は、シリアルポートとして共用している D0/RX とD1/TX がブッキングしていたからである。
使用中はシリアル通信を使用しないので問題無いと思っていたが、修正書込み、あるいはモニタリング時にはシリアル通信を使用するため、このポートは開けておくべきであった。 書込みのたびに接続を外すのは大変だからである。
そこで、一時停止ボタンと警報機能を諦めて、二つのポートを開ける様にし、メインボードとの配線位置を変更した。 即ち、D0/RX とD1/TX のポートを使用していた二つの信号入力をここに持ってきた。
2019/8/20 作成