Webプログラマの夏休み PHPでNゲージ模型を自由自在に動かそう[動画つき]

第1回三次元に挑戦

はじめに

先日、東京のお台場にガンダムの実物大の模型ができました。見に行かれた方も多いのではないでしょうか。CGでどんな映像でも作れる時代ですが、やはり実物というのは迫力が違うものです。

画像

ガンダムに対抗するわけではないのですが、本稿では鉄道模型の制御に挑戦してみようと思います。模型であっても、実際に車両が動くというのは格別なものです。普通、制御というとC言語などを使用しますが、ここではPHPからLAN経由で制御するようにしてみました。まずどうやって制御しているのか、見ていきましょう。

こんなふうに動きます

まずは写真のような一直線のレイアウトを動かしてみましょう。普通のNゲージでは電源は1ヵ所だけ供給しますが、今回は5ヵ所に供給しています。これについては、後ほど解説します。

図1 直線レイアウト
図1 直線レイアウト
画像

そして、PHPのプログラムはリスト1のようになります。このプログラムをコマンドラインから実行すると、右端に置いた車両が左端まで走行して止まります。

リスト1 左端まで進む
#! /usr/local/bin/php
<?php
$url = "http://192.168.0.100/";

file_get_contents($url."?00=C");
file_get_contents($url."?01=D");
file_get_contents($url."?02=D");
file_get_contents($url."?03=C");

?>

往復運転させるには、リスト2のようにします。

リスト2 往復運転
#! /usr/local/bin/php
<?php
$url = "http://192.168.0.100/";

for (;;) {
	file_get_contents($url."?00=C");
	file_get_contents($url."?01=D");
	file_get_contents($url."?02=D");
	file_get_contents($url."?03=C");
	sleep(30);
	file_get_contents($url."?00=A");
	file_get_contents($url."?01=A");
	file_get_contents($url."?02=A");
	file_get_contents($url."?03=A");
	
	file_get_contents($url."?04=c");
	file_get_contents($url."?03=d");
	file_get_contents($url."?02=d");
	file_get_contents($url."?01=c");
	sleep(30);
	file_get_contents($url."?04=A");
	file_get_contents($url."?03=A");
	file_get_contents($url."?02=A");
	file_get_contents($url."?01=A");
}

?>

見ての通り、複雑なものではありません。これは、PHPから送ったコマンドをコントローラが受けとり、電気の制御を行ってくれているからです。

LANから制御する仕掛け

Nゲージの動く仕組みは、レールにかけた電圧を車輪が受けとり、モーターが回って走行するというものです。電圧を高くすればスピードが速くなり、電圧をマイナスにすれば逆方向に走ります。普通のNゲージのセットでは、電源(パワーパック)からレール全体に電気を供給し、速度と方向を制御するようになっています。例えば駅のところで車両を止めるには、人間が目で見ながら、スピードを落として止めることになります。

今回のシステムでは、少し違った方法を採用しました。絶縁レールを用いて、レールを電気的に分割し、部分ごとに異なる電圧を供給できるようにします。駅のところのレールの電気をオフにしておけば、駅のところまで来ると勝手に停止することになります。今回のレイアウトで5箇所に給電しているのは、この方法によるものです。

絶縁レール。矢印のところで分割されている。
絶縁レール。矢印のところで分割されている。

このようなシステムには、たくさんの出力があるコントローラが必要です。今回開発したコントローラ(写真)は出力が14組あり、LANからそれぞれの出力を別個に制御できるようになっています。Nゲージではポイントも電気で制御するようになっているので、ポイントとレールを合計で14個までつなげることになります。ちなみに、コントローラにはPICというマイコンを使用しています。

コントローラ
コントローラ

コントローラはHTTPサーバになっており、PHPからHTTPリクエストを送ることで制御します。たとえばhttp://192.168.0.100/?00=Dのリクエストを送ると、00番のレールに電圧が出力されます。Dの部分がコマンドで、表1のようなコマンドが使用できます。

表1 コマンド一覧
コマンド機能
A停止
B走行1/16
C走行1/8
D走行1/4
E走行1/2
F走行100%
b逆走行1/16
c逆走行1/8
d逆走行1/4
e逆走行1/2
f逆走行100%
Pポイント分岐
pポイント直進
S車両検出

では、これをPHPから呼び出してみましょう。

PHPのプログラム

先ほどのプログラム(リスト1、2)では、PHPのfile_get_contents()を利用しています。これはURLを指定すると、ページの内容を文字列で返してくれます。00~03までの4つのレールに電気を供給することで、左に向かって走行し、左端で停止します。

図2 給電のようす
図2 給電のようす

走り終わるのを時間待ちして、今度は01~04のレールに給電することで、右端まで走行します。

図3 給電のようす(その2)
図3 給電のようす(その2)

時間待ちでは信頼性が低いので、レールに車両が来たことをコマンドで検出してみましょう。これは、たとえば以下のようにします。

 while (file_get_contents("http://192.168.0.100/?00=S") + 0 == 0)
   ;

Sコマンドは、指定したレールに車両があると1を返します。車両がないと0を返すので、0でなくなるまでポーリングすることで、車両が来るまで待つことができます。これを利用すると、プログラムはリスト3のようになります。

リスト3 位置検出ルーチンを付加
#! /usr/local/bin/php
<?php
$url = "http://192.168.0.100/";

for (;;) {
	file_get_contents($url."?00=C");
	file_get_contents($url."?01=D");
	file_get_contents($url."?02=D");
	file_get_contents($url."?03=C");
	while (file_get_contents($url."?04=S") + 0 == 0)
		;
	file_get_contents($url."?00=A");
	file_get_contents($url."?01=A");
	file_get_contents($url."?02=A");
	file_get_contents($url."?03=A");
	
	file_get_contents($url."?04=c");
	file_get_contents($url."?03=d");
	file_get_contents($url."?02=d");
	file_get_contents($url."?01=c");
	while (file_get_contents($url."?00=S") + 0 == 0)
		;
	file_get_contents($url."?04=A");
	file_get_contents($url."?03=A");
	file_get_contents($url."?02=A");
	file_get_contents($url."?01=A");
}

?>

なお、このコントローラは内部の通信をシリアルでおこなっているため、1回のリクエストの処理に0.3秒くらいかかります。また、複数のリクエストを同時に受け付けることはできません。

ポイントも動かそう

ポイントの制御も、コマンドを送るだけです。ポイントが1つのレイアウトを見てみましょう。

図4 引き込み線のあるレイアウト
図4 引き込み線のあるレイアウト
図4 引き込み線のあるレイアウト

リスト4のプログラムでは、引き込み線から車両が出て、レールを2周して、また引き込み線に戻ります。

リスト4 引き込み線。車輪が絶縁レールをまたぐ瞬間があるため、駅に着いたことを検出したあと待ちが必要
#! /usr/local/bin/php
<?php

$url = "http://192.168.0.100/";

#
# +--------|---------+
# |                  |
# +---03---|<<<02<<<<p1
#                    <<<<<<<|<<<00<<<|
#
file_get_contents($url."?01=p");
file_get_contents($url."?00=D");
file_get_contents($url."?02=D");
while (file_get_contents($url."?03=S") + 0 == 0)
	;
file_get_contents($url."?00=A");
file_get_contents($url."?02=A");
sleep(5);	# wait in station

#
# +>>>>>>>>|---------+
# |                  |
# +<<<03<<<|---02---<p1
#                    -------|---00---|
#
file_get_contents($url."?01=P");
file_get_contents($url."?03=D");
sleep(5);	# make sure of leaving rail 02
while (file_get_contents($url."?02=S") + 0 == 0)
	;
file_get_contents($url."?03=A");
sleep(5);	# wait in station

#
# +--------|>>>>>>>>>+
# |                  |
# +---03---|<<<02<<<<p1
#                    -------|---00---|
#
file_get_contents($url."?01=P");
file_get_contents($url."?02=D");
sleep(5);	# make sure of leaving rail 03
while (file_get_contents($url."?03=S") + 0 == 0)
	;
file_get_contents($url."?02=A");
sleep(5);	# wait in station

#
# +>>>>>>>>|---------+
# |                  |
# +<<<03<<<|---02---<p1
#                    -------|---00---|
#
file_get_contents($url."?01=P");
file_get_contents($url."?03=D");
sleep(5);	# make sure of leaving rail 02
while (file_get_contents($url."?02=S") + 0 == 0)
	;
file_get_contents($url."?03=A");
sleep(5);	# wait in station

#
# +--------|>>>>>>>>>+
# |                  |
# +---03---|<<<02<<<<p1
#                    -------|---00---|
#
file_get_contents($url."?01=P");
file_get_contents($url."?02=D");
sleep(5);	# make sure of leaving rail 03
while (file_get_contents($url."?03=S") + 0 == 0)
	;
file_get_contents($url."?02=A");
sleep(5);	# wait in station

#
# +<<<<<<<<|---------+
# |                  |
# +>>>03>>>|>>>02>>><p1
#                    >>>>>>|---00---|
#
file_get_contents($url."?01=p");
file_get_contents($url."?03=d");
file_get_contents($url."?02=d");
while (file_get_contents($url."?00=S") + 0 == 0)
	;
file_get_contents($url."?03=A");
file_get_contents($url."?02=A");

?>

リスト4の実行結果を動画で見てみましょう。

引き込み線プログラムの実行
ニコニコ動画:https://www.nicovideo.jp/watch/sm7797189

車両が進むまで待って、次のコマンドを送るだけですから、特に難しいものではありませんね。しかし、ちょっとソースが見にくくなってきました。そこで、次回はオブジェクト指向スタイルに移行することにしましょう。

おすすめ記事

記事・ニュース一覧