HOME >> 鉄道模型自動運転システム > 登山鐡道 新自動運転システム スケッチの記述
.
■ はじめに
電子回路の動作チェックもなんとか無事に完了したので、いよいよソフトの出番となった。
■ Arduino用ソフトの準備
プログラム、いやスケッチの記述用として新たにノートパソコンを用意していたのだ。 古いパソコンはOSが古くて、更新もままならないのでお蔵入りとしている。
そこで、物置部屋にも持ち込めるようにと新しく導入したのが右の写真に示すパソコンである。 とは言ってもリース落ちの中古品であるが、Windows10やWi-fi が備わっているので、気楽に使用できそうである。
さっそく、ネットより最新のArduino 用ソフトをダウンロードしてインストールし、スケッチを記述し始めたが、ラズパイでの命令との違いに戸惑ってしまった。
そこで、もう一度 Arduino の教科書を持ち出し、確認しながら進める必要があった。 しかし、基本的なロジックは踏襲すているので、サブルーチンとしての関数の記述方法や I/O の記述方法を確認しながら実施した。
// 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クール ********************************* }
■ スケッチの概要
「登山鐡道 新自動運転システム構想」 で示した運行ダイヤの各運行モードを関数として定義する。 すなわち、図に示した d1 〜D6 までのモードを関数のDirection 1(densha) 〜 6() として記述しておく。 カッコ内は走行する電車の番号を指定する引数である。 そして、メインループで電車を指定した運行モードを順次記述していく手順である。
運行ダイヤを示す関数は、同じ記述内容のものを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番ポートに設定しているからである。
こんなところでデジタルの不思議に出くわすのである。
デジタル、特に10進数は指折り数える人類の歴史を思い出す。 ひとつ、ふたつと数える場合は、ゼロではなくて、1から始めるのだ。 21世紀の始めでも 2001年がなぜ21世紀なのか、2000年代だから20世紀ではないのか? と不思議であったが、キリストが生まれた最初の100年間が1世紀目なのだ。101年からもう2世紀目となっているのである。 日本でも、昔は生まれたばかりの赤ちゃんは1歳と数えたそうな。 数え始めは1なのだ。
ゼロの発明は数学の歴史のエポックであったと聞く。 0と1のデジタルの世界では、ゼロから始まるのである。
余談はさておいて、速度設定ボリュームから読み取ったアナログ値が、もし 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 のポートを使用していた二つの信号入力をここに持ってきました。
A3/D17 ポート: 一時停止 ⇒ スイッチバックの通過信号 T2
A5/D19 ポート: アラーム ⇒ 街中駅の通過信号 T1
次回は試運転の様子を報告しよう。
2018/3/14 作成 M.T.