プラレールの自動制御
大学生にもなって、文化祭で鉄道研究部の展示を見てからというもの、プラレールにはまっています。
既に多くの方がプラレールの自動制御を行っていますが、今回は、Raspberry Pi による自動制御で、
「通過待ち」や「行先分類」などを行ってみます。
インフラ編
配線図
これはかなり悩みました。部屋の広さと相談し、今回は下の図のような配線図にしました。
複線のレイアウトです。
Sと書かれている個所は、ストップレールです。
車両を一時停止させることができます。
実際のレールで作ると、このようになります。
ポイント
ポイントの種類
今回、ポイントを3種類に分類しました。
-
サーボモータ付きポイント
今回の自動制御において、中心となるサーボモータ付きのポイントです。Raspberry Pi から自由自在に制御することができます。 -
スプリングポイント(発条転轍器)(輪ゴムで方向を固定したポイントのことです。)
必ず決められた方向に列車を導くポイントです。直前にどの方向から列車が来たかに関わらず、決められた方向に列車を誘導します。 -
元々のポイント
手を一切加えていないポイントです。分岐線の合流箇所で使用しています。
先ほどの配線図の各ポイントを次のように分類します。
赤:サーボモータ付きポイント
緑:スプリングポイント
青:元々のポイント
なにも印のついてないポイントは、サーボモータの個数の都合上、今回は見送りました。
輪ゴム・サーボモータの取り付け
ポイントに、輪ゴム・サーボモータを取り付けます。
下の画像のように、ポイントレールの裏面に輪ゴムを取り付けることで、進行方向を常に固定することができました。
さらに、反対側に引っ張るための糸を取り付け、サーボモータで引っ張ることで、進行方向を変更できるようになります。
ストップレール
続いて、ストップレールです。
ストップレールの黄色いレバーの部分に、サーボモータをセロハンテープで固定しました。
光センサ
列車の存在確認及び、列車の編成長の識別のため、光センサとしてCdSセルを使用しています。
レール接続部分に裏側から光センサを取り付けることで、レールを加工せずとも光センサを取り付けることができました。
編成長の識別
光センサが2つ同時に隠れるか否かにより、2両編成か3両編成かを判定しています。
Raspberry Pi
ここまでに作成した下記のものを接続しました。
- ポイント用サーボモータ:3個
- ストップレール用サーボモータ:2個
- 光センサ:4個
モータや抵抗の接続は、ソフトウェア編に記載した記事を参考に行いました。
もう少しきれいに見えるよう、コーディングの技術を上達させたいですね。
どのモータがどのピンに接続されているかは、下記のソフトウェア編に記載します。
ソフトウェア編
続いて、ソフトウェア編です。
- 光センサーCdSセルでLEDをコントロールする(RaspberryPi3)
- wiringPi: Access GPIO pins on Raspberry Pi via wiringPi library
- Raspberry Piでサーボモーターを回す
といった記事を参考に、次のようなプログラムを書きました。
import RPi.GPIO as GPIO
import wiringpi as w
import time
GPIO.setmode(GPIO.BCM)
w.wiringPiSetup()
#w.pipMode(22, 0)
#w.pipMode(23, 0)
#w.pipMode(24, 0)
#w.pipMode(25, 0)
gp_out_2 = 2
gp_out_3 = 3
gp_out_4 = 4
gp_out_17 = 17
gp_out_27 = 27
GPIO.setup(gp_out_2, GPIO.OUT)
GPIO.setup(gp_out_3, GPIO.OUT)
GPIO.setup(gp_out_4, GPIO.OUT)
GPIO.setup(gp_out_17, GPIO.OUT)
GPIO.setup(gp_out_27, GPIO.OUT)
servo_2 = GPIO.PWM(gp_out_2, 50)
servo_3 = GPIO.PWM(gp_out_3, 50)
servo_4 = GPIO.PWM(gp_out_4, 50)
servo_17 = GPIO.PWM(gp_out_17, 50)
servo_27 = GPIO.PWM(gp_out_27, 50)
servo_2.start(0)
servo_3.start(0)
servo_4.start(0)
servo_17.start(0)
servo_27.start(0)
wait=0
servo_2_off = 0
servo_3_off = 0
servo_27_off = 0
servo_4_on = 0
servo_4_off = 0
servo_17_on = 0
servo_27_on = 0
nocount=0
servo_17.ChangeDutyCycle(2.5)
while True:
print('loop')
print(w.digitalRead(29))
print(w.digitalRead(23))
print(w.digitalRead(24))
print(w.digitalRead(25))
time.sleep(0.1)
servo_2_off=servo_2_off-1
servo_27_off=servo_27_off-1
servo_27_on=servo_27_on-1
servo_4_off=servo_4_off-1
servo_4_on=servo_4_on-1
servo_17_on=servo_17_on-1
servo_3_off=servo_3_off-1
wait=wait-1
nocount=nocount-1
if(servo_2_off==0):
servo_2.ChangeDutyCycle(7.25)
if(servo_3_off==0):
servo_3.ChangeDutyCycle(7.25)
if(servo_27_off==0):
servo_27.ChangeDutyCycle(7.25)
if(servo_27_on==0):
servo_27.ChangeDutyCycle(2.5)
if(servo_4_off==0):
servo_4.ChangeDutyCycle(7.25)
if(servo_4_on==0):
servo_4.ChangeDutyCycle(2.5)
if servo_17_on == 0:
servo_17.ChangeDutyCycle(2.5)
if w.digitalRead(24) == 0:
wait=30
if w.digitalRead(29) == 0:
if w.digitalRead(23) == 0:
print('3 cars')
nocount=15
if wait > 0:
servo_3.ChangeDutyCycle(2.5)
servo_3_off=30
else:
servo_4_on = 70
servo_4_off = 80
else:
if nocount < 0:
print('2 cars')
servo_2.ChangeDutyCycle(2.5)
servo_2_off = 30
servo_27_on = 20
servo_27_off = 50
servo_4_on = 40
servo_4_off = 60
if w.digitalRead(25) == 0:
servo_17.ChangeDutyCycle(7.25)
servo_17_on = 70
for i in range(1):
servo_2.ChangeDutyCycle(2.5)
servo_3.ChangeDutyCycle(2.5)
servo_4.ChangeDutyCycle(2.5)
servo_17.ChangeDutyCycle(2.5)
servo_27.ChangeDutyCycle(2.5)
time.sleep(5)
# time.sleep(0.5)
servo_2.ChangeDutyCycle(7.25)
servo_3.ChangeDutyCycle(7.25)
servo_4.ChangeDutyCycle(7.25)
servo_17.ChangeDutyCycle(7.25)
servo_27.ChangeDutyCycle(7.25)
time.sleep(0.5)
# servo.ChangeDutyCycle(12)
# time.sleep(0.5)
# servo.ChangeDutyCycle(7.25)
# time.sleep(0.5)
servo_2.stop()
GPIO.cleanup()
複数の列車を運行するため、ポイントやストップレールの制御を約0.1秒ごとのclock式としました。
各サーボモータは下図のピン番号のように配線されています。
また、光センサは下図のwiringpiピン番号に配線されています。
なお、これらのセンサは次のような働きをしています。
番号 | 役割 |
---|---|
24 | 通過待ちをするか否かの判定 |
23 | 3両編成か2両編成かの判定 |
29 | 列車接近検知 |
25 | 合流箇所における列車接近の検知 |
判定基準
2両編成の場合
最も早い車両を2両編成にしているため、2両編成の場合には通過待ちはありません。
29番センサに列車が検知された瞬間に、23番センサに列車が検知されていない場合は、2両編成です。
2両編成の場合は、問答無用に退避せず、分岐を右側に曲がるように誘導します。
3両編成通過待ちなし
29番センサに列車が検知された瞬間に、23番センサでも列車が検知された場合は、3両編成です。最後に24番センサを列車が通過してから3秒以上経過していれば、通過待ちはしません。ここで判定基準を3秒としているのは、3秒以上前の場合は、自分自身の通貨である可能性があるからです。ポイントの状態は変えず、列車を直進させます。また、通過待ち中の列車がいる可能性を考慮し、3秒後にストップレールを「進む」とし、
3両編成通過待ちあり
29番センサに列車が検知された瞬間に、23番センサでも列車が検知された場合は、3両編成です。最後に24番センサを列車が通過してから3秒以内であれば、通過待ちをするようにします。
走行動画
これらがどのような動きをするか、YouTubeに動画をアップしましたので、よろしければご覧ください。
2編成の通過待ち及び行先分岐
https://youtu.be/2Cd-xgwB5wY
3編成の通過待ち及び行先分岐
https://youtu.be/wQ6l39p_Mcw
※3編成だと、現状の設備・プログラムだと、しばらくたつと追突してしまいます。もう少し信号設備を増やすか、プログラムを改良する必要がありそうです。
今後の展望
- プラレール車体へのカメラの搭載
- 信号装置の追加
- 単線入れ替えの導入
- カメラ画像による識別
- 行先表示パネルの設置
などができればより面白くなるかなと思います。
まあ、部屋の広さ的に、線路の拡張は厳しそうですけど。