HOME >> 鉄道模型実験室 > スケッチの構成に関する一考察
■ いきさつ
Arduinoを使って鉄道模型の自動運転に挑戦されている「イノッチ」さんのブログを応援している時に、プログラムの書き方について振り返る機会がありました。 そこで、Arduino のプルグラムを記述するスケッチについて、自分なりの考えをまとめてみました。 これはコンパイラを使用するC言語などとも共通する考えと思いますが、Arduino を常用する小生としては、スケッチを基本にしてまとめています。
.
■ プログラムの全体構成
自分として気が付いていなかったのですが、プログラム全体を構成する方式には、右のイラストの様に、「駅伝方式」と「もぐらたたき方式」がある事に気が付きました。
C言語などのプログラム解説書を見ると、プログラムは、「順次」、「分岐(選択)」、「繰返し(反復)」処理を組み合わせて処理されると解説されています。
スケッチでの全体構成を見た場合にも、同様な形態が考えられます。 右のイラストに示すように、順次処理して行く方法(自分では「駅伝方式」として呼ぶことにする)と、条件をチェックして該当する場合のみ対応する処理を実施する構成(自分では「もぐらたたき方式」として呼ぶことにする)が考えられます。
この他に、罰として校庭を10周せよ! といった繰返し処理を使った全体構成としては稀であると考えるので、上記の二つの方式で構成されると考えて良いであろうと考えます。
駅伝(リレー)の場合、次の中継所まで走り、中継所に辿り着くと次のランナーにタスキを渡します。 走行中は常に中継所はまだか、まだかとわき目も振らずに走っているのです。 一方のもぐらたたきの場合は、どのモグラが頭を出したの、常にチェックして、出てきたモグラがあれば、瞬時に対応します。 コンピュータはある時点では一つの事しか出来ませんので、チェックは順番に実施しますが、その巡回速度は極めて速く、ミリ秒?いやマイクロ秒単位かも知れません。 自動販売機のように、お客さんがどのスイッチを押すのか分から無い場合などの対応方法であると考える事もできますし、多くの自動運転システムなど、状態の変化をいち早くキャッチしてそれに対応させるシステムなど、この様な構成にしておく必要があり、多くのシステムで採用されている方式だと勝手に想像しています。
どの様な構成にするかは、対象とする制御システムによって、適不適がある事は明らかですが、プログラマーの好みによっても左右されるものと思われます。
.
■ IF文とwhile文の違い
そして、このような構成を記述するための命令語も、それぞれに適不適があり、駅伝方式には while文が、もぐらたたき方式には if 文が適していると思われますので、ここで、その違いを見てみましょう。
条件をチェックしてYESであった場合、前に戻るのが while 文であり、次の命令に進むのが if 文なのです。
駅伝方式では、次のチェックポイントが決まっています。 このためそのポイントだけを常にチェックしており、その間は決められた処理を常に実行している(ひたすら走っている)のです。 従って while文が最適なのです。 Arduino 日本語リファレンスには次のように説明されています。
whileは繰り返しの処理に使います。 カッコ内の式がfalseになるまで、処理は無限に繰り返されます。 条件式で使われる変数は、whileループの中で、値を加えるとかセンサの値を読むといった処理により変化する必要があります。 そうしないと、ループから抜け出すことができません。
while(条件式){
// 実行される文
}
一方の IF 文は、
if文は与えられた条件が満たされているかどうかをテストします。 カッコ内の条件がtrueのとき、波カッコ{}内の文が実行されます。 条件が満たされていない(trueでない)とき、波カッコ内の文は実行されず次の処理に移ります。
if (someVariable > 50) {
// 条件を満たしたとき実行される文
}
このため、もぐらたたき方式にはこの命令が有効なのです。 しかし、それぞれの命令にも長所と短所があるため、使用する場合にはそれなりの配慮が必要なのは当然でしょう。
■ 自分の自動運転の場合の構成は?
振り返って自分の記述例をみると、殆どが駅伝方式の構成でした。 何故だったのかと考えると、それはアセンブラ言語を少しかじっていた為と思われる。 アセンブラでは、昨年流行った go to 命令を多用しており、そのジャンプ先は、幾つか前の命令に戻るとか、ラベル位置まで移動させることが容易でした。 即ち、
btfss GPIO,3 ; S2をチェック、前方のチェックポイントに来たか?
goto $-1
これだけの記述でwhile文と同じチェックを実施していたのです。 簡単でしたの躊躇なく活用していたのでが、この流れがスケッチで記述する場合にも生きていたと解釈しています。 何も深く考えていなかったのです。
************************************************************************************
どこかで、「構造化プログラミング」という言葉を耳にしたことがあり、自分には関係のない高級プログラミングの世界と思っていました。 しかし、ウィキペディアにて検索してみると、
制御構造(control structures)とは、goto文によるフロー分岐やループ表現を、if文による選択構文やwhile文による反復構文に置き換えるためのプログラム記法を意味している。 ラベル先にジャンプするというgoto文の機能を、if文やwhile文は「特定のコード群だけを実行する」という概念に置き換えている。
さらに、
実行順序を決定するものが制御構造であり、以下の三つがある。
1. 順次(sequence)部分プログラムを順々に実行する。
2. 選択(selection) 条件式が導出した状態に従い、次に実行する部分プログラムを選択して分岐する。
3. 反復(repetition)条件式が導出した特定の状態の間、部分プログラムを繰り返し実行する。
との解説もあった。
なんのことはない! 1969年、即ち50年も前から知られていたことであり、自分の勉強不足を露呈したに過ぎないのである。
***************************************************************************************************************************
.
■ もぐらたたき方式を使ってみよう
またまた、変なことを思いついたと思われるが、きっかけは右のレイアウトを考えていたからである。 「卓上レイアウトで楽しもう その29」(2021/1/6)のレイアウトを変形させていたのである。
レイアウトを組んでいるときに、ハタと手が止まってしまった。 このレイアウトはリバース線を含んでいるので、色々な運行モードが考えられる。 それに合わせて、給電ポイントやセンサの位置、ギャップの位置を考えなければならない。
さらに、上記の全体構成を考えていた時期と重なっていたので、全体構成を「もぐらたたき方式」で実施してみようと考えたのである。 即ち、
操作方法は、
の操作を実施することにする。 すると、選択された運行モードを実行し、終了後はホームに停車して待機状態となる。 連続運転の場合はこれを繰り返すことになる。
なんだか楽しめそうである!
*******************************************************************************
でも、色々な運行モードを考えたり、それに合わせたセンサ等の設置場所を詰めていく必要があるが、その前に、運行モードの選択手段をどうするのかを考えておかなければならない。 そこで、ロータリスイッチを昔使った事があるのを思い出した。 「逆流電流を測定する」(2014/4/3)参照。 この装置はもう使用しないので部品状態に分解し、再利用することにした。 このロータリースイッチは、1回路12接点の仕様で、秋月から購入した部品であった。 さらにストッパの位置を変更することが2〜12接点に変更可能である。
しかし、運行モードの設定をいくつにするかにもよるが、スイッチの選択状態を Arduino にどの様に入力させるかが問題なのである。 各接点ごとに Arduino のI/Oポートを使用したならば、いっぺんに I/Oポートが不足してしまうのである。 そこで、ロータリスイッチの選択状態をコード化する基板を作ることにし、デコードは Arduino上で実施すようにする。 こうすると、12接点の判別は、4個のチャネルで済むことになるだ。
そこで、まず、このコード化する基板の工作から始めた。 次回はその内容を報告する。
2021/1/15 作成