車両基地
車両基地のコントローラーを作ります。

・車両基地はループ区間を切り替えて作ります。列車がギャップを跨いだのを検知して車止め手前で停止させます。


【KiCadの回路図】
【基板】
レイアウト全体図
【PIC16F1827のコード】
//
//2021_0606
#include <xc.h>
#define _XTAL_FREQ 4000000
#define ADR 0x7C
#define RTC_ADR 0x64
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
//#pragma config DEBUG = OFF
#pragma config FOSC =INTOSC //HS
#pragma config FCMEN = OFF
#pragma config MCLRE = OFF
#pragma config WDTE = OFF //ON
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON
#define ExtInt RB0
#define ExtData RB1
int IntCount;
unsigned char bit_p;
unsigned char receive_data;
unsigned char data_p;
unsigned char RxData[128];
unsigned char send_data;
unsigned char busy;
unsigned char p_counter;
unsigned char EnableBit[] = {1, 2, 4, 8, 16, 32, 64, 128};
unsigned char yard_req;
unsigned char yard_num;
//********************************************************
void main(void) {
//最高速32MHz
OSCCONbits.SPLLEN = 1; //×4 PLL
OSCCONbits.IRCF = 14; //8MHz
ANSELA = 0; // アナログ入力 AN8からAN13 を無効
ANSELB = 0; // アナログ入力 AN0からAN7 を無効
PORTA = 0;
PORTB = 0;
TRISA = 0x00; //All Input (FET OFF)
TRISB = 0x03; // RB0,1 Input
OPTION_REG = 0x0f; // WDT,Int Fall, pulup
OPTION_REGbits.nWPUEN = 1;
INTE = 1; // RB0 割り込み許可
GIE = 1; // 割り込み許可
__delay_ms(10); // 10msec
while (1) {
CLRWDT();
if (yard_req & 0x80) { //リクエスト確認
if (!busy) {
busy = yard_req;
yard_num = (yard_req & 0x70) >> 4; //yard番号
switch (yard_num) {
case 0:
PORTA = yard_req & 0xf;
break;
case 1:
PORTB = (yard_req & 0xf) << 4;
break;
}
}
} else {
busy = 0; //busy off
}
}
}
void __interrupt() ISR_ExtInt(void) {
//void interrupt ISR_ExtInt(void) {
unsigned char inp_bit;
inp_bit = ExtData;
INTF = 0; // 割り込みフラグクリア
//RB4 = 1;
IntCount++;
if (ExtInt == 0) {
//--- IntCount 0 ---
IntCount = 0;
if (p_counter)
p_counter--;
}
//受信
TRISB1 = 1; //PortInput
data_p = (IntCount - 1) >> 3;
bit_p = EnableBit[(IntCount - 1) & 0b111];
if (inp_bit)
receive_data |= bit_p;
else
receive_data &= ~bit_p;
if (bit_p == 0x80) {
RxData[data_p] = receive_data; //DataSet
if (data_p == 0x61) {//0x61 yard
yard_req = RxData[0x61]; //DataSet
}
}
data_p = IntCount >> 3;
if (data_p == 0x71) {//0x71 yard send
//送信
TRISB1 = 0; //PortOutput
bit_p = EnableBit[IntCount & 0b111];
send_data = busy;
if (send_data & bit_p)
ExtData = 1;
else
ExtData = 0;
}
//RB4 = 0;
}
【PIC32のソフト】
・PIC32のプロジェクトはSUBボードの製作で作ったプロジェクトのソースに統合しました。(2021_0606)
PC側ソフト
・YARDの番号と線番号を指定してYARDボタンを押すと指定のYardの線番号から発車します。
・走行中にYARDボタンを押すと指定したYARDの入り口に来たときに指定の線番号に入線して停車します。
・YARD2は、通過型で空いている線を通過できます。YARDを2に指定してボタンを押した時は停止位置で停車します。
VB Formのデザイン
UserControl ContPanelのデザイン
Form1のコード
Imports System.IO.Ports
Imports System.Runtime.Serialization.Formatters.Binary
Public Class Form1
Const Tx_Byte As Integer = 128
Const Rx_Byte As Integer = 230
Const TxData数 As Integer = 12
Const RxData数 As Integer = 12
Private 列車数 As Integer = 3
Const 最大列車数 As Integer = 8
Public ポイント数 As Integer
Const yard数 As Integer = 1
Private TM(列車数) As Integer
Private TM2 As Boolean
Private 減速時スピード = 40
Private PlayStep As Integer
Private csv_writer As IO.StreamWriter
Private Remcon As List(Of ContPanel) = New List(Of ContPanel)()
Public Event yard_chg()
Public Enum p処理 'ポイント処理定数
なし
ボタンON
切替要求
通過待ち
切替中
End Enum
Public Enum y処理 'Yard処理定数
なし
Yard要求
Yard発車要求
Yard切替完了
Yardポイント切替完了
Yard停止
Yard完全停止
Yardポイント戻し完了
Yard発車要求受付
Yard発車準備完了
Yard発車出口
Yard終了
End Enum
<Serializable()> Class 位置情報
Public 区間 As Integer
Public 路線 As Integer
Public 方向 As Integer
Public 相 As Integer
Sub New(ByVal 区 As Integer, ByVal 路 As Integer, ByVal 向 As Integer, ByVal sou As Integer)
区間 = 区
路線 = 路
方向 = 向
相 = sou
End Sub
Public ReadOnly Property Byte情報() As Byte
Get
Return 区間 + 路線 * 8 + 方向 * &H80 + 相 * &H40
End Get
End Property
Sub 次区間()
If 方向 = 0 Then
区間 = (区間 + 1) And &H7
Else
区間 = (区間 - 1) And &H7
End If
End Sub
Sub 前区間()
If 方向 = 0 Then
区間 = (区間 - 1) And &H7
Else
区間 = (区間 + 1) And &H7
End If
End Sub
Function copy()
Return New 位置情報(区間, 路線, 方向, 相)
End Function
Sub 逆転()
If 方向 = 0 Then
方向 = 1
Else
方向 = 0
End If
End Sub
' = 演算子をオーバーロード
Public Shared Operator =(ByVal c1 As 位置情報, ByVal c2 As 位置情報) As Boolean
If (c1.路線 = c2.路線) And (c1.区間 = c2.区間) And (c1.方向 = c2.方向) Then
Return True
Else
Return False
End If
End Operator
Public Shared Operator <>(ByVal c1 As 位置情報, ByVal c2 As 位置情報) As Boolean
Return Not c1 = c2
End Operator
End Class
Class train
Public 現位置 As 位置情報
Public 前位置 As 位置情報
Public 次位置 As 位置情報
Public 次々位置 As 位置情報
Public 区間変化 As Boolean
Public 安全 As Boolean
Public speed As Single
Public 逆転 As Integer
Public 設定speed As Integer
Public ポイント As Integer
Public point処理状況 As p処理
Public yard処理状況 As y処理
Public ポイント番号 As Integer
Public yard番号 As Integer
Public 相変更FLAG As Boolean
Public Power As Integer
Public yard As Integer
Sub New()
'Dummyで登録(路線=7)
現位置 = New 位置情報(0, 7, 0, 0)
前位置 = 現位置.copy
次位置 = 現位置.copy
次々位置 = 現位置.copy
End Sub
Sub New(ByVal 現 As 位置情報)
現位置 = 現
前位置 = 現位置.copy
前位置.前区間()
次位置 = 現位置.copy
次位置.次区間()
次々位置 = 次位置.copy
次々位置.次区間()
区間変化 = True
End Sub
Sub New(ByVal 現 As 位置情報, ByVal 前 As 位置情報, ByVal 次 As 位置情報, ByVal 次々 As 位置情報)
現位置 = 現
前位置 = 前
次位置 = 次
次々位置 = 次々
End Sub
Sub 区間変更()
前位置 = 現位置.copy
現位置 = 次位置.copy
次位置 = 次々位置.copy
次々位置.次区間()
区間変化 = True
End Sub
Sub 逆転処理()
'現位置を前位置に、前位置を現位置に
現位置.逆転()
前位置.逆転()
次位置 = 現位置.copy '前位置に入れるため
現位置 = 前位置.copy
前位置 = 次位置.copy
次位置 = 現位置.copy
次位置.次区間()
次々位置 = 次位置.copy
次々位置.次区間()
End Sub
Sub 相変更()
If 現位置.相 = 0 Then
現位置.相 = 1
前位置.相 = 1
次位置.相 = 1
次々位置.相 = 1
Else
現位置.相 = 0
前位置.相 = 0
次位置.相 = 0
次々位置.相 = 0
End If
相変更FLAG = True
区間変化 = True
End Sub
Public ReadOnly Property Status As Byte
Get
Dim ret As Byte
If 区間変化 Then ret = 1
If Not 相変更FLAG Then
'相変更中は区間変更しない
If 安全 Then ret += &H80
End If
Return ret
End Get
End Property
Public ReadOnly Property Enable As Boolean
'列車運転中Enable
Get
If 現位置.路線 = 7 Then
Return False
Else
Return True
End If
End Get
End Property
End Class
Class PointClass
Public 進入位置1 As 位置情報
Public 進入位置2 As 位置情報
'Public 出口位置1 As 位置情報
'Public 出口位置2 As 位置情報
Public 番号 As Integer
Sub New(ByVal 位置1 As 位置情報, ByVal 位置2 As 位置情報, ByVal n As Integer)
進入位置1 = 位置1
進入位置2 = 位置2
番号 = n
End Sub
Public ReadOnly Property 進入位置(ByVal 位置 As 位置情報) As 位置情報
Get
'進入位置なら対向進入位置を返す
If (位置.路線 = 進入位置1.路線) And
(位置.区間 = 進入位置1.区間) And
(位置.方向 = 進入位置1.方向) Then
Dim ret As 位置情報 = 進入位置2.copy
ret.逆転()
ret.相 = 位置.相
Return ret
End If
If (位置.路線 = 進入位置2.路線) And
(位置.区間 = 進入位置2.区間) And
(位置.方向 = 進入位置2.方向) Then
Dim ret As 位置情報 = 進入位置1.copy
ret.逆転()
ret.相 = 位置.相
Return ret
End If
Return Nothing
End Get
End Property
Public ReadOnly Property 出口位置(ByVal 現位置 As 位置情報) As Boolean
Get
'出口位置ならTRUEを返す
Dim 位置 As 位置情報 = 現位置.copy
位置.前区間()
If 位置.方向 = 0 Then
If (位置.路線 = 進入位置2.路線) And (位置.区間 = 進入位置2.区間) Then
Return True
End If
Else
If (位置.路線 = 進入位置1.路線) And (位置.区間 = 進入位置1.区間) Then
Return True
End If
End If
Return False
End Get
End Property
End Class
Class YardClass
Public 発車位置 As 位置情報
Public 進入位置 As 位置情報
Public 停止位置 As 位置情報
Public 出口位置 As 位置情報
Public 停止位置1 As 位置情報
Public 停止位置2 As 位置情報
Public 出口位置1 As 位置情報
Public 出口位置2 As 位置情報
Public 進入位置2 As 位置情報
Public 発車位置2 As 位置情報
Public 分線 As Byte
Public 列車 As Byte
Public ポイント番号 As Integer
Public type As Integer
Public y制御Byte As Byte
Public p制御Byte As Byte
Sub New(ByVal 位置 As 位置情報, point As Integer, p As String, t As String, tp As Integer)
分線 = Convert.ToInt32(p, 2)
列車 = Convert.ToInt32(t, 2)
発車位置 = 位置.copy '位置は発車位置
進入位置 = 位置.copy
停止位置 = 位置.copy
出口位置 = 位置.copy
進入位置.逆転() '進入位置は発車位置の逆転
停止位置.逆転()
停止位置.次区間() '停止位置は発車位置の逆の次区間
出口位置.次区間() '出口位置は発車位置の次区間
停止位置1 = 停止位置.copy
出口位置1 = 出口位置.copy
進入位置2 = 停止位置.copy
進入位置2.逆転()
発車位置2 = 停止位置.copy
停止位置2 = 発車位置.copy
出口位置2 = 発車位置2.copy
出口位置2.次区間()
ポイント番号 = point
type = tp
End Sub
Public ReadOnly Property 空線 As Array
Get
Dim ret(7) As Integer
Dim pos As Byte
pos = Not (分線 And 列車) And 分線
Dim c As Integer
Dim num As Integer
For n = 0 To 7
If (分線 And 2 ^ n) <> 0 Then
num += 1
If (pos And 2 ^ n) <> 0 Then
ret(c) = num
c += 1
End If
End If
Next
ReDim Preserve ret(c - 1)
Array.Reverse(ret)
Return ret
End Get
End Property
Public ReadOnly Property 在線 As Array
Get
Dim ret(7) As Integer
Dim c As Integer
Dim num As Integer
For n = 0 To 7
If (分線 And 2 ^ n) <> 0 Then
num += 1
If (列車 And 2 ^ n) <> 0 Then
ret(c) = num
c += 1
End If
End If
Next
ReDim Preserve ret(c - 1)
Array.Reverse(ret)
Return ret
End Get
End Property
Function 番号位置変換(i As Integer)
'bit 位置に変換
Dim c As Integer
For n = 0 To 7
If (分線 And 2 ^ n) <> 0 Then
c += 1
If i = c Then
Return n
End If
End If
Next
Return i
End Function
Public WriteOnly Property 列車Set(io As Boolean) As Integer
Set(value As Integer)
Dim pos = 番号位置変換(value)
If io Then
'入線時
列車 = 列車 Or 2 ^ pos
Else
'発車時
Dim p As Byte = Not 2 ^ pos And &HFF
列車 = 列車 And p
End If
End Set
End Property
Public ReadOnly Property 進入位置確認(位置 As 位置情報, pos As Integer) As Boolean
Get
Dim n = ポイント番号 - 3
Dim p = 番号位置変換(pos)
If type = 0 Then
y制御Byte = &H88 + n * &H10 + p
p制御Byte = &HC0 + ポイント番号
Return 位置 = 進入位置
Else
If 位置 = 進入位置 Then
停止位置 = 停止位置1.copy
'y制御Byte = &H80 + n * &H10 + &H2 + p * 4
y制御Byte = &H80 + n * &H10 + &H1 + p * 2
p制御Byte = &H80 + p * &H40 + ポイント番号
Return True
ElseIf 位置 = 進入位置2 Then
'逆進入
停止位置 = 停止位置2.copy
'y制御Byte = &H80 + n * &H10 + p * 4
y制御Byte = &H80 + n * &H10 + p * 2
p制御Byte = &H80 + p * &H40 + ポイント番号
Return True
Else
Return False
End If
End If
End Get
End Property
Public Sub Yard終了処理()
p制御Byte = p制御Byte Xor &H40
If type = 0 Then
y制御Byte = y制御Byte And &HF0
Else
'反対側の線に切り替え
'y制御Byte = y制御Byte Xor &H4
y制御Byte = y制御Byte Xor &H2
End If
End Sub
Public Sub Yard発車処理(pos As Integer, d As Integer)
Dim n = ポイント番号 - 3
Dim p = 番号位置変換(pos)
If type = 0 Then
y制御Byte = &H88 + n * &H10 + p
p制御Byte = &HC0 + ポイント番号
Else
y制御Byte = &H80 + n * &H10 + p * 2 '*4
p制御Byte = &H80 + p * &H40 + ポイント番号
If d = 1 Then
出口位置 = 出口位置2.copy
Else
出口位置 = 出口位置1.copy
End If
End If
End Sub
Public Sub Yard発車終了処理()
If type = 0 Then
y制御Byte = y制御Byte And &HF0
p制御Byte = p制御Byte Xor &H40
Else
If 列車 <> 3 Then
'0側空くときは0側へ切り替え
y制御Byte = y制御Byte And &HF8 '***
p制御Byte = p制御Byte And &HBF
End If
End If
End Sub
End Class
Class 停止位置class
Public 位置 As 位置情報
Public ポイント番号 As Integer
Sub New(p As 位置情報, n As Integer)
位置 = p
ポイント番号 = n
End Sub
End Class
<Serializable()> Class Record
Public 位置 As 位置情報
Public ポイント番号 As Integer
Public 逆転 As Boolean
Public Yard番号 As Integer
Public 線番号 As Integer
Public 停止時間 As Integer
Public スピード As Integer
Sub New(ByRef tr As train)
位置 = tr.現位置.copy
ポイント番号 = -2
Yard番号 = -1
If tr.逆転 = 1 Then
逆転 = True
End If
End Sub
End Class
<Serializable()> Class Rec_List
Inherits List(Of Record)
'最後の要素の逆転Set・Get 要素なしでFalse
Public Property 逆転() As Boolean
Get
If Count > 0 Then
Return Last.逆転
End If
Return False
End Get
Set(value As Boolean)
If Count > 0 Then
Last.逆転 = value
End If
End Set
End Property
Public Property ポイント() As Integer
'最後の要素のポイント番号Set・Get 要素なしでFalse
Get
If Count > 0 Then
Return Last.逆転
End If
Return False
End Get
Set(value As Integer)
If Count > 0 Then
Last.ポイント番号 = value
End If
End Set
End Property
Public Sub point_yard_set(ByRef tr As train)
'Static Dim 切替中 As Boolean
If Count > 0 Then
'If Not 切替中 Then
If tr.point処理状況 = p処理.切替中 Then
If Count > 1 Then
If Item(Count - 2).ポイント番号 <> tr.ポイント番号 Then
Last.ポイント番号 = tr.ポイント番号
'切替中 = True
End If
Else
Last.ポイント番号 = tr.ポイント番号
End If
Else
Last.ポイント番号 = -2
End If
'Last.ポイント番号 = tr.point処理状況
'Else
' If tr.point処理状況 = p処理.なし Then
' 切替中 = False
' End If
'End If
If tr.yard処理状況 = y処理.Yardポイント切替完了 Then
Last.Yard番号 = tr.yard番号
End If
If Last.Yard番号 < 0 Then
Last.線番号 = 0
End If
End If
End Sub
End Class
Public 列車(8) As train
Public ポイント(4) As PointClass
Public yard(1) As YardClass
Public 車止位置(1) As 停止位置class
Public 記録 As Rec_List = New Rec_List()
'デリゲートの宣言
Public Delegate Sub RsDelegate()
'データーの受信
Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
Handles SerialPort1.DataReceived
'データの受信はマルチスレッドで行われる為にデリゲートを使用して
'メインのスレッドでデータ処理の必要があります。
Me.Invoke(New RsDelegate(AddressOf receive_data), New Object() {})
End Sub
'受信データー
Public Sub receive_data()
Dim byteArray(SerialPort1.BytesToRead - 1) As Byte
Static GND_Level(9) As Integer
Static c As Integer
If byteArray.Length <> Rx_Byte Then
Exit Sub
End If
'ポートのバッファから読み込み
SerialPort1.Read(byteArray, 0, SerialPort1.BytesToRead)
'ヘッダーチェック
If (byteArray(0) <> &H55) Or (byteArray(1) <> &HAA) Then Exit Sub
'Comm_data表示
Dim data_txt As String = ""
For n = 0 To 127
Dim hex_str = "0" + Hex(byteArray(100 + n))
data_txt += hex_str.Substring(hex_str.Length - 2, 2) + " "
If n Mod 8 = 7 Then
data_txt += vbCrLf
End If
Next
Label3.Text = data_txt
Dim 変化 As Byte = byteArray(4)
For n = 0 To 列車数 - 1
Dim pos As Integer = RxData数 * n
Dim speed As Integer = 0
Dim power As Integer = 0
If 列車(n).Enable Then
'スピードメータ-
speed = byteArray(pos + 2) * 256 + byteArray(pos + 3)
power = byteArray(pos + 7) * 256 + byteArray(pos + 8)
End If
Remcon(n).Speed_Meter = speed
Remcon(n).Power_Meter = power
'csv 出力
'If n = 0 Then
' csv_writer.Write(speed.ToString + "," + power.ToString + ",")
' csv_writer.WriteLine(byteArray(pos + 4).ToString)
'End If
Dim 区間byte(3) As Byte
区間byte(0) = 列車(n).現位置.Byte情報
区間byte(1) = 列車(n).次位置.Byte情報
Remcon(n).区間表示 = 区間byte
列車(n).Power = power
'区間変化の確認
If byteArray(pos + 4) = &H80 Then
If Not 列車(n).区間変化 Then
'立ち上がりのみ
列車(n).区間変更()
'全ての列車の情報更新
For m = 0 To 列車数 - 1
列車(n).区間変化 = True
Next
'c += 1
'Label2.Text = c
If 列車(n).point処理状況 = p処理.ボタンON Then
'区間頭でポイント切り替え要求
列車(n).point処理状況 = p処理.切替要求
End If
End If
Else
'区間変化フラグクリア
列車(n).区間変化 = False
End If
'Point_Clr
If 列車(n).ポイント <> 0 Then
If byteArray(pos + 5) = 列車(n).ポイント Then
列車(n).ポイント = 0 'point clr
End If
End If
'yard_Clr
If 列車(n).yard <> 0 Then
If byteArray(pos + 6) = 列車(n).yard Then
列車(n).yard = 0 'yard clr
End If
End If
'相変更FLAG CLR
列車(n).相変更FLAG = False
Next
記録再生()
'停止位置がポイントの時、ポイント切り替えON
停止位置ポイント処理()
'ポイント処理
For n = 0 To 列車数 - 1
Select Case 列車(n).point処理状況
Case p処理.切替要求, p処理.通過待ち
'Point位置確認
For p As Integer = 0 To ポイント数 - 1
Dim 次位置 As 位置情報 = ポイント(p).進入位置(列車(n).現位置)
'ポイント番号確認
Select Case Remcon(n).point_num
Case -1, ポイント(p).番号 '-1は次のポイント
If Not 次位置 Is Nothing Then
Select Case ポイント安全確認(n, 次位置)
Case "安全"
'ポイント切り替え
列車(n).ポイント = &HC0 + ポイント(p).番号
列車(n).次位置 = 次位置.copy
次位置.次区間()
列車(n).次々位置 = 次位置.copy
列車(n).区間変化 = True
列車(n).point処理状況 = p処理.切替中
列車(n).ポイント番号 = p
Remcon(n).CheckBox2.Enabled = False 'ポイントボタン不可
Remcon(n).DomainUpDown1.Enabled = False
Case "不可"
Case "通過待ち"
列車(n).point処理状況 = p処理.通過待ち
End Select
Exit For
End If
End Select
Next
Case p処理.切替中
'出口位置確認
If ポイント(列車(n).ポイント番号).出口位置(列車(n).現位置) Then
'ポイント戻し
列車(n).ポイント = &H80 + ポイント(列車(n).ポイント番号).番号
列車(n).point処理状況 = p処理.なし
Remcon(n).CheckBox2.Enabled = True 'ポイントボタン可
Remcon(n).DomainUpDown1.Enabled = True 'ポイント選択可
Remcon(n).CheckBox2.Checked = False 'ポイントボタン戻し
End If
End Select
Yard処理(n)
Next
'安全確認
For n = 0 To 列車数 - 1
If 列車(n).Enable Then
Select Case 安全確認(n)
Case "停止"
列車(n).安全 = False
列車(n).設定speed = 0
Remcon(n).信号 = "赤"
Case "減速"
Dim 減速速度 As Integer = 減速時スピード '減速時のスピード
列車(n).安全 = True
If Remcon(n).Speed_Cont > 減速速度 Then
列車(n).設定speed = 減速速度
Else
列車(n).設定speed = Remcon(n).Speed_Cont
End If
Remcon(n).信号 = "黄"
Case "安全"
Remcon(n).信号 = "緑"
列車(n).安全 = True
If 列車(n).逆転 = 1 Then
'逆転フラグが1なら逆転のため停止
列車(n).設定speed = 0
ElseIf 列車(n).point処理状況 = p処理.通過待ち Then
'ポイント通過待ちのため停止
列車(n).設定speed = 0
ElseIf 列車(n).yard処理状況 = y処理.Yard停止 Then
'Yardで停止
列車(n).設定speed = 0
Remcon(n).Speed_Cont = 0
Else
列車(n).設定speed = Remcon(n).Speed_Cont
End If
Case "向合停止"
列車(n).安全 = False
列車(n).設定speed = 0
Remcon(n).信号 = "赤"
Remcon(n).CheckBox1.Checked = True '強制逆転
End Select
Else
Remcon(n).信号 = "灰"
End If
Next
End Sub
Sub Yard処理(n As Integer)
Select Case 列車(n).yard処理状況
Case y処理.Yard要求
Dim p = Remcon(n).NumericUpDown1.Value - 1
If 列車(n).区間変化 Then
If yard(p).進入位置確認(列車(n).現位置, Val(Remcon(n).DomainUpDown2.Text)) Then
'yard切り替え
列車(n).yard = yard(p).y制御Byte
列車(n).yard処理状況 = y処理.Yard切替完了
列車(n).yard番号 = p
Remcon(n).Yard_Cont = False 'yard cont desable
End If
End If
Case y処理.Yard切替完了
'ポイント切り替え
If 列車(n).yard = 0 Then 'yard 切り替え確認
列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
列車(n).yard処理状況 = y処理.Yardポイント切替完了
End If
Case y処理.Yardポイント切替完了
If 列車(n).現位置 = yard(列車(n).yard番号).停止位置 Then
'yard停止
列車(n).yard処理状況 = y処理.Yard停止
End If
Case y処理.Yard完全停止
'Yardポイント戻し
yard(列車(n).yard番号).Yard終了処理()
列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
列車(n).yard処理状況 = y処理.Yardポイント戻し完了
'Timer2.Interval = 1000
'Timer2.Enabled = True 'ポイント切り替え待ち
TM(n) = 10
Case y処理.Yardポイント戻し完了
If TM(n) = 0 Then
'TM(n) = False
'yard戻し
列車(n).yard = yard(列車(n).yard番号).y制御Byte
列車(n).yard処理状況 = y処理.Yard終了
End If
Case y処理.Yard終了
If 列車(n).yard = 0 Then 'yard 切り替え確認
yard(列車(n).yard番号).列車Set(True) = Val(Remcon(n).DomainUpDown2.Text)
列車(n) = New train() '列車Disable
Remcon(n).Yard_Cont = True 'yard cont enable
RaiseEvent yard_chg()
End If
Case y処理.Yard発車要求
Dim p = Remcon(n).NumericUpDown1.Value - 1
'yard切り替え
If yard(p).type = 1 Then
If Remcon(n).CheckBox4.Checked Then '発車方向
列車(n) = New train(yard(p).発車位置2)
Else
列車(n) = New train(yard(p).発車位置)
End If
Else
列車(n) = New train(yard(p).発車位置)
End If
If Yard安全確認(n) Then
If Remcon(n).CheckBox4.Checked Then
'逆転戻し
Remcon(n).CheckBox4.Checked = False
End If
yard(p).Yard発車処理(Val(Remcon(n).DomainUpDown2.Text), 列車(n).現位置.方向)
列車(n).yard = yard(p).y制御Byte
列車(n).yard処理状況 = y処理.Yard発車要求受付
列車(n).yard番号 = p
Remcon(n).Yard_Cont = False 'yard cont desable
Else
列車(n) = New train() '列車Disable
列車(n).yard処理状況 = y処理.Yard発車要求
End If
Case y処理.Yard発車要求受付
'ポイント切り替え
If 列車(n).yard = 0 Then 'yard 切り替え確認
列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
列車(n).yard処理状況 = y処理.Yard発車準備完了
End If
Case y処理.Yard発車準備完了
If 列車(n).現位置 = yard(列車(n).yard番号).出口位置 Then
If 列車(n).ポイント = 0 Then
'Yardポイント戻し
yard(列車(n).yard番号).Yard発車終了処理()
列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
列車(n).yard処理状況 = y処理.Yard発車出口
'Timer2.Interval = 1000
'Timer2.Enabled = True 'ポイント切り替え待ち
TM(n) = 10
End If
End If
Case y処理.Yard発車出口
If TM(n) = 0 Then
'TM(n) = False
'yard戻し
列車(n).yard = yard(列車(n).yard番号).y制御Byte
yard(列車(n).yard番号).列車Set(False) = Val(Remcon(n).DomainUpDown2.Text)
列車(n).yard処理状況 = y処理.なし
Remcon(n).Yard_Cont = True
RaiseEvent yard_chg()
End If
End Select
End Sub
Sub 停止位置ポイント処理()
'停止位置がポイントの時、ポイント切り替えON
For n = 0 To 列車数 - 1
If 列車(n).point処理状況 = p処理.なし Then
For Each p As 停止位置class In 車止位置
If 列車(n).現位置 = p.位置 Then
If p.ポイント番号 >= 0 Then
'ポイント切り替えON
Remcon(n).DomainUpDown2.Text = p.ポイント番号
'Remcon(n).CheckBox2.Checked = True
列車(n).point処理状況 = p処理.切替要求
End If
End If
Next
End If
Next
End Sub
Function 安全確認(ByVal n As Integer) As String
Dim 停止 As Boolean = False
Dim 減速 As Boolean = False
Dim 向合停止 As Boolean = False
For m As Integer = 0 To 列車数 - 1
If m <> n Then
'次位置が他の列車の現、前、次位置と同じなら停止
If (列車(n).次位置.路線 = 列車(m).現位置.路線) And
(列車(n).次位置.区間 = 列車(m).現位置.区間) Then 停止 = True
If (列車(n).次位置.路線 = 列車(m).前位置.路線) And
(列車(n).次位置.区間 = 列車(m).前位置.区間) Then 停止 = True
If 列車(n).point処理状況 = p処理.切替中 Then
'ポイント切り替え中
If 列車(n).現位置.方向 <> 列車(m).現位置.方向 Then
If (列車(n).次位置.路線 = 列車(m).次位置.路線) And
(列車(n).次位置.区間 = 列車(m).次位置.区間) Then 停止 = True
End If
Else
If (列車(n).次位置.路線 = 列車(m).次位置.路線) And
(列車(n).次位置.区間 = 列車(m).次位置.区間) Then 停止 = True
End If
'次々位置が他の列車の現、前、次位置と同じなら減速
If (列車(n).次々位置.路線 = 列車(m).現位置.路線) And
(列車(n).次々位置.区間 = 列車(m).現位置.区間) Then 減速 = True
If (列車(n).次々位置.路線 = 列車(m).前位置.路線) And
(列車(n).次々位置.区間 = 列車(m).前位置.区間) Then 減速 = True
If (列車(n).次々位置.路線 = 列車(m).次位置.路線) And
(列車(n).次々位置.区間 = 列車(m).次位置.区間) Then 減速 = True
If 停止 Then
If (n > m) And (列車(n).現位置.方向 <> 列車(m).現位置.方向) Then
向合停止 = True '方向逆で優先順位低いとき
Return "向合停止"
End If
Exit For
End If
End If
Next
For Each p As 停止位置class In 車止位置
If p.ポイント番号 < 0 Then
'ポイントのない停止位置
If 列車(n).現位置 = p.位置 Then
'現位置なら停止
停止 = True
Exit For
ElseIf 列車(n).次位置 = p.位置 Then
'次位置なら減速
減速 = True
Exit For
End If
End If
Next
'通過形ヤードで空き線なしは通過不可
For Each p As YardClass In yard
If p.type = 1 Then
'通過形ヤードの時
If p.空線.Length = 0 Then
'空線なしの時
If (列車(n).現位置 = p.進入位置) Or (列車(n).現位置 = p.進入位置2) Then
停止 = True
Exit For
End If
End If
End If
Next
'Yard減速
If 列車(n).yard処理状況 = y処理.Yardポイント切替完了 Then
減速 = True
End If
If 停止 Then Return "停止"
If 減速 Then Return "減速"
Return "安全"
End Function
Function ポイント安全確認(ByVal n As Integer, ByVal 位置 As 位置情報) As String
Dim 相手路線列車数 As Integer
Dim 相手 As Integer
Dim 停止 As Boolean
For m As Integer = 0 To 列車数 - 1
If m <> n Then
'位置が他の列車の現、前、次位置と同じなら非安全
If (位置.路線 = 列車(m).現位置.路線) And
(位置.区間 = 列車(m).現位置.区間) Then 停止 = True
If (位置.路線 = 列車(m).前位置.路線) And
(位置.区間 = 列車(m).前位置.区間) Then 停止 = True
If (位置.路線 = 列車(m).次位置.路線) And
(位置.区間 = 列車(m).次位置.区間) Then 停止 = True
If (位置.路線 = 列車(m).次々位置.路線) And
(位置.区間 = 列車(m).次々位置.区間) Then 停止 = True
'相手路線の列車数確認
If 位置.路線 = 列車(m).現位置.路線 Then
相手路線列車数 += 1
相手 = m
End If
End If
Next
'路線に列車が2台いるときはポイント切り替え不可
If 相手路線列車数 >= 2 Then Return "不可"
If 停止 Then Return "通過待ち"
'列車が1台いるときは相手の相を確認
If 相手路線列車数 = 1 Then
'相が同じなら相手の相を変更
If 列車(相手).現位置.相 = 列車(n).現位置.相 Then 列車(相手).相変更()
End If
Return "安全"
End Function
Function Yard安全確認(ByVal n As Integer) As Boolean
Dim 相手路線列車数 As Integer
Dim 相手 As Integer
Dim 停止 As Boolean
For m As Integer = 0 To 列車数 - 1
If m <> n Then
'現位置が他の列車の現、前、次位置、次々位置と同じなら停止
If (列車(n).現位置.路線 = 列車(m).現位置.路線) And
(列車(n).現位置.区間 = 列車(m).現位置.区間) Then 停止 = True
If (列車(n).現位置.路線 = 列車(m).前位置.路線) And
(列車(n).現位置.区間 = 列車(m).前位置.区間) Then 停止 = True
If (列車(n).現位置.路線 = 列車(m).次位置.路線) And
(列車(n).現位置.区間 = 列車(m).次位置.区間) Then 停止 = True
If (列車(n).現位置.路線 = 列車(m).次々位置.路線) And
(列車(n).現位置.区間 = 列車(m).次々位置.区間) Then 停止 = True
'前位置が他の列車の現、前、次位置、次々位置と同じなら停止
If (列車(n).前位置.路線 = 列車(m).現位置.路線) And
(列車(n).前位置.区間 = 列車(m).現位置.区間) Then 停止 = True
If (列車(n).前位置.路線 = 列車(m).前位置.路線) And
(列車(n).前位置.区間 = 列車(m).前位置.区間) Then 停止 = True
If (列車(n).前位置.路線 = 列車(m).次位置.路線) And
(列車(n).前位置.区間 = 列車(m).次位置.区間) Then 停止 = True
If (列車(n).前位置.路線 = 列車(m).次々位置.路線) And
(列車(n).前位置.区間 = 列車(m).次々位置.区間) Then 停止 = True
'相手路線の列車数確認
If 列車(n).現位置.路線 = 列車(m).現位置.路線 Then
相手路線列車数 += 1
相手 = m
End If
End If
Next
'路線に列車が2台いるときはポイント切り替え不可
If 相手路線列車数 >= 2 Then Return False
If 停止 Then Return False
'列車が1台いるときは相手の相を確認
If 相手路線列車数 = 1 Then
'相が同じなら相を変更
If 列車(相手).現位置.相 = 列車(n).現位置.相 Then 列車(n).相変更()
End If
Return True
End Function
Private Sub 記録再生()
Static Dim 変化 As Boolean
If 列車(0).区間変化 And Not 変化 Then
変化 = True
'区間変更時
If Remcon(0).CheckBox5.Checked Then
'列車0の記録
If 記録.逆転 And (列車(0).逆転 = 1) Then
'逆転後区間変更のとき1つ前の逆転はFalse
記録.逆転 = False
DomainUpDown1.Items(DomainUpDown1.Items.Count - 1) = 記録msg(記録.Last, 記録.Count)
End If
'一時停止後は次区間のスピードをセット
If 記録.Last.スピード = -1 Then
記録.Last.スピード = Remcon(0).Speed_Cont
End If
記録.Last.線番号 = Remcon(0).線番号
記録.point_yard_set(列車(0))
記録.Add(New Record(列車(0)))
記録.Last.スピード = Remcon(0).Speed_Cont
DomainUpDown1.Items.Add(記録msg(記録.Last, 記録.Count))
DomainUpDown1.SelectedIndex = DomainUpDown1.Items.Count - 1
End If
If Remcon(0).CheckBox6.Checked Then
'列車0のPlay
If 記録(PlayStep).位置 = 列車(0).現位置 Then
Remcon(0).Speed_Cont = 記録(PlayStep).スピード
'逆転
If 記録(PlayStep).逆転 Then
列車(0).逆転 = 1
End If
'ポイント切り替え
If 記録(PlayStep).ポイント番号 > -2 Then
列車(0).point処理状況 = p処理.切替要求
Remcon(0).point_num = ポイント(記録(PlayStep).ポイント番号).番号
End If
'Yard切り替え
If 記録(PlayStep).Yard番号 > -1 Then
列車(0).yard処理状況 = y処理.Yard要求
Remcon(0).NumericUpDown1.Value = 記録(PlayStep).Yard番号 + 1
Remcon(0).線番号 = 記録(PlayStep).線番号
End If
'停止時間ありでstep中止
If 記録(PlayStep).停止時間 = 0 Then
PlayStep += 1
End If
If 記録.Count <= PlayStep Then
'Play終了
Remcon(0).CheckBox6.Checked = False
Remcon(0).Speed_Cont = 0
PlayStep = 0
Else
Label2.Text = PlayStep
DomainUpDown1.SelectedIndex = PlayStep
End If
End If
End If
Else
変化 = False
End If
If Remcon(0).CheckBox5.Checked Then
'Yard発車記録
If 列車(0).yard処理状況 = y処理.Yard発車要求受付 Then
記録.Add(New Record(列車(0)))
記録.Last.Yard番号 = 列車(0).yard番号
記録.Last.線番号 = Remcon(0).線番号
記録.Last.スピード = Remcon(0).Speed_Cont
'Dim mes As String = String.Format("{0} 路線{1} 区間{2} 逆転{3} ポイント{4} Yard{5}", 記録.Count, 記録.Last.位置.路線, 記録.Last.位置.区間, 記録.Last.逆転, 記録.Last.ポイント番号, 記録.Last.Yard番号)
'DomainUpDown1.Items.Add(mes)
DomainUpDown1.Items.Add(記録msg(記録.Last, 記録.Count))
End If
'Yard停車記録
If 列車(0).yard処理状況 = y処理.Yard終了 Then
記録.Last.停止時間 = 5
End If
'停止の記録 走行中スピード0
If 列車(0).Enable Then
If 列車(0).yard処理状況 = y処理.なし Then
If Remcon(0).Speed_Cont = 0 Then
If 列車(0).Power = 0 Then
If 記録.Last.スピード <> -1 Then
記録.Last.スピード = 0
記録.Last.停止時間 = 5
記録.Add(New Record(列車(0)))
記録.Last.スピード = -1
End If
End If
End If
End If
End If
End If
If Remcon(0).CheckBox6.Checked Then
'Yard発車PLAY
If 列車(0).Enable = False Then
'Yard切り替え
If 記録(PlayStep).Yard番号 > -1 Then
列車(0).yard処理状況 = y処理.Yard発車要求
Remcon(0).NumericUpDown1.Value = 記録(PlayStep).Yard番号 + 1
Remcon(0).線番号 = 記録(PlayStep).線番号
Remcon(0).Speed_Cont = 記録(PlayStep).スピード
PlayStep += 1
Label2.Text = PlayStep
DomainUpDown1.SelectedIndex = PlayStep
TM2 = False
End If
End If
'停止タイマーON
If 列車(0).yard処理状況 = y処理.Yard終了 Then
If 記録(PlayStep).停止時間 > 0 Then
Timer2.Interval = 記録(PlayStep).停止時間 * 1000
Timer2.Enabled = True
Label4.Text = "TimerON"
End If
End If
'一時停止時
If 列車(0).Enable And Not Timer2.Enabled Then
If Remcon(0).Speed_Cont = 0 Then
If 列車(0).Power = 0 Then
If 記録(PlayStep).停止時間 > 0 Then
Timer2.Interval = 記録(PlayStep).停止時間 * 1000
Timer2.Enabled = True
Label4.Text = "TimerON"
End If
End If
End If
End If
'一時停止からの起動
If TM2 Then
Remcon(0).Speed_Cont = 記録(PlayStep).スピード
PlayStep += 1
Label2.Text = PlayStep
DomainUpDown1.SelectedIndex = PlayStep
TM2 = False
End If
End If
End Sub
Function 記録msg(ByRef rec As Record, c As Integer) As String
Dim rev As String = "OFF"
If rec.逆転 Then rev = "ON"
Dim point As String = rec.ポイント番号
If rec.ポイント番号 = -2 Then point = "OFF"
Dim yard As String = rec.Yard番号 + 1
If rec.Yard番号 = -1 Then yard = "OFF"
Dim ret As String = String.Format("{0} 路線{1} 区間{2} 逆転{3} ポイント{4} Yard{5} 線番号{6} 停止時間{7} Speed{8}",
c, rec.位置.路線, rec.位置.区間, rev, point, yard, rec.線番号, rec.停止時間, rec.スピード)
Return ret
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'ポート接続処理
SerialPort1.PortName = ComboBox1.Text
SerialPort1.BaudRate = 115200
'SerialPort1.BaudRate = 9600
SerialPort1.Parity = IO.Ports.Parity.None
SerialPort1.DataBits = 8
SerialPort1.StopBits = IO.Ports.StopBits.One
SerialPort1.ReceivedBytesThreshold = Rx_Byte
SerialPort1.ReadTimeout = 500
SerialPort1.WriteTimeout = 500
SerialPort1.Open()
Timer1.Enabled = True
Button1.Enabled = False
Button2.Enabled = True
ComboBox1.Enabled = False
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'ポート切断処理
Timer1.Enabled = False
SerialPort1.Close()
ComboBox1.Enabled = True
Button1.Enabled = True
Button2.Enabled = False
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim Txdata(Tx_Byte) As Byte
Dim 加速 As Single = 0.3
'ヘッダーとして&H55,&HAAを送る
Txdata(0) = &H55
Txdata(1) = &HAA
For n = 0 To 列車数 - 1
If 列車(n).Enable Then
'speed 加速・減速
If 列車(n).設定speed - 列車(n).speed < 0 Then
If 列車(n).yard処理状況 = y処理.Yard停止 Then
加速 = 1
Else
加速 = 0.5
End If
End If
列車(n).speed += (列車(n).設定speed - 列車(n).speed) * 加速
'逆転フラグ確認
If 列車(n).逆転 = 1 Then
If Int(列車(n).speed) = 0 Then
If 列車(n).Power = 0 Then
'列車が停止したら逆転
列車(n).逆転処理()
列車(n).逆転 = 0
列車(n).区間変化 = True '位置情報更新の為
'逆転ボタン戻し
Remcon(n).CheckBox1.Checked = False
Remcon(n).CheckBox1.Enabled = True
End If
End If
End If
'Yardでの停止確認
If 列車(n).yard処理状況 = y処理.Yard停止 Then
If Int(列車(n).speed) = 0 Then
If 列車(n).Power = 0 Then
列車(n).yard処理状況 = y処理.Yard完全停止
End If
End If
End If
End If
Next
For n = 0 To 最大列車数 - 1
Dim p As Integer = n * TxData数 + 2
Txdata(p) = Int(列車(n).speed) 'speed data
Txdata(p + 1) = 列車(n).現位置.Byte情報
Txdata(p + 2) = 列車(n).前位置.Byte情報
Txdata(p + 3) = 列車(n).次位置.Byte情報
Txdata(p + 4) = 列車(n).Status
Txdata(p + 5) = 列車(n).ポイント
Txdata(p + 6) = 列車(n).yard
Next
Try
SerialPort1.Write(Txdata, 0, Tx_Byte) 'データ送信
Catch ex As Exception
'エラーのとき
Button2_Click(Nothing, Nothing) '切断
MsgBox(ex.Message)
End Try
'YARD用タイマー
For n = 0 To 列車数 - 1
If TM(n) > 0 Then
TM(n) -= 1
End If
Next
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ports As String() = SerialPort.GetPortNames()
If ports.Count = 0 Then
MsgBox("シリアルポートが見つかりません。")
Button1.Enabled = False
Else
'使用可能なシリアルポートをコンボボックスに登録
ComboBox1.Items.AddRange(ports)
ComboBox1.SelectedIndex = 0
End If
'ComboBox1.SelectedIndex = 2
ComboBox1.Text = "COM11"
Me.Text = "PC Remote"
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Fixed3D
Me.MinimizeBox = False
Me.MaximizeBox = False
Button1.Text = "接続"
Button2.Text = "切断"
Button3.Text = "切替"
Button4.Text = "戻し"
Button5.Text = "開く"
Button6.Text = "保存"
GroupBox1.Text = ""
GroupBox2.Text = "ポイントテスト"
GroupBox3.Text = "プログラム運転"
CheckBox1.Text = "メモリ表示"
CheckBox1.Checked = True
CheckBox1.Appearance = Appearance.Button
CheckBox2.Text = "Repeat"
DomainUpDown1.Text = ""
Label1.Text = ""
Label2.Text = ""
Label3.Text = ""
Label4.Text = ""
Button2.Enabled = False '切断ボタンdisable
Timer1.Interval = 200 'タイマーインターバル200ms
'Dummy Data
For n = 0 To 最大列車数 - 1
列車(n) = New train()
Next
'列車情報設定
'列車(0) = New train(New 位置情報(1, 0, 0, 0))
'列車(1) = New train(New 位置情報(4, 0, 0, 1))
'列車(2) = New train(New 位置情報(1, 1, 0, 0))
'ポイント情報設定
'ポイント(0) = New PointClass(New 位置情報(4, 0, 0, 0), New 位置情報(5, 1, 1, 0), 0)
'ポイント(1) = New PointClass(New 位置情報(4, 1, 0, 0), New 位置情報(5, 0, 1, 0), 0)
ポイント(0) = New PointClass(New 位置情報(1, 0, 0, 0), New 位置情報(3, 1, 1, 0), 0)
ポイント(1) = New PointClass(New 位置情報(2, 1, 0, 0), New 位置情報(2, 0, 1, 0), 0)
ポイント(2) = New PointClass(New 位置情報(0, 1, 0, 0), New 位置情報(0, 2, 1, 0), 1)
ポイント(3) = New PointClass(New 位置情報(3, 2, 0, 0), New 位置情報(7, 0, 1, 0), 2)
ポイント数 = 4
yard(0) = New YardClass(New 位置情報(7, 1, 1, 0), 3, "11010101", "01010001", 0)
yard(1) = New YardClass(New 位置情報(0, 0, 0, 0), 4, "11", "01", 1)
'行き止まり位置
車止位置(0) = New 停止位置class(New 位置情報(0, 2, 1, 0), 1)
車止位置(1) = New 停止位置class(New 位置情報(3, 2, 0, 0), 2)
For n As Integer = 0 To 列車数 - 1
Remcon.Add(New ContPanel(n))
Remcon(n).Top = 10
Remcon(n).Left = Remcon(0).Width * n + 2
Controls.Add(Remcon(n))
AddHandler Remcon(n).逆転_Click, AddressOf 逆転_Click
AddHandler Remcon(n).ポイント_Click, AddressOf ポイント_Click
AddHandler Remcon(n).Yard_Click, AddressOf Yard_Click
Remcon(n).add_point(ポイント) 'リモコンにポイント番号登録
Next
'rec_click
AddHandler Remcon(0).Rec_Click, AddressOf Rec_Click
Me.Height = Remcon(0).Height + GroupBox3.Height + 70
GroupBox1.Left = Remcon(0).Width * 列車数 + 20
Label3.Left = GroupBox1.Left + GroupBox1.Width + 20
Me.Width = Label3.Left + Label3.Width + 40
GroupBox3.Top = Remcon(0).Height + 20
'Log用
csv_writer = New IO.StreamWriter("out.csv", False, System.Text.Encoding.GetEncoding("Shift_JIS"))
End Sub
Private Sub 逆転_Click(ByVal index As Integer)
'逆転ボタン確認
If Remcon(index).CheckBox1.Checked Then
'列車逆転のため停止させる
列車(index).逆転 = 1
Remcon(index).CheckBox1.Enabled = False
End If
End Sub
Private Sub ポイント_Click(ByVal index As Integer)
'ポイントボタン確認
If Remcon(index).CheckBox2.Checked Then
'ポイント切り替え要求
'列車(index).point処理状況 = p処理.切替要求
列車(index).point処理状況 = p処理.ボタンON
列車(index).ポイント番号 = Remcon(index).point_num
Else
列車(index).point処理状況 = p処理.なし
End If
End Sub
Private Sub Yard_Click(ByVal index As Integer)
'Yardボタン確認
Dim y As y処理
If 列車(index).Enable Then
y = y処理.Yard要求
Else
y = y処理.Yard発車要求
End If
If Remcon(index).CheckBox3.Checked Then
'Yard要求
列車(index).yard処理状況 = y
End If
End Sub
Private Sub Rec_Click()
'Rec開始時記録Clear
If Remcon(0).CheckBox5.Checked Then
記録.Clear()
DomainUpDown1.Items.Clear()
DomainUpDown1.Text = ""
End If
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs)
列車(0).区間変化 = True
列車(1).区間変化 = True
End Sub
Private Sub Button3_Click_1(sender As Object, e As EventArgs) Handles Button3.Click
列車(0).ポイント = &HC0 + NumericUpDown1.Value
'列車(0).区間変化 = True
'列車(1).区間変化 = True
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
列車(0).ポイント = &H80 + NumericUpDown1.Value
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs)
'TM = True
'Timer2.Enabled = False
End Sub
Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
csv_writer.Close()
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
Label3.Visible = CheckBox1.Checked
If CheckBox1.Checked Then
Me.Width = Label3.Left + Label3.Width + 40
Else
Me.Width = GroupBox1.Left + GroupBox1.Width + 40
End If
End Sub
Private Sub Timer2_Tick_1(sender As Object, e As EventArgs) Handles Timer2.Tick
'停車時間タイマー
PlayStep += 1
If 記録.Count <= PlayStep Then
PlayStep = 0
If CheckBox2.Checked Then
'repeat
TM2 = True
Else
'Play終了
Remcon(0).CheckBox6.Checked = False
Remcon(0).Speed_Cont = 0
End If
End If
Label2.Text = PlayStep
DomainUpDown1.SelectedIndex = PlayStep
Timer2.Enabled = False
Label4.Text = "TimerOFF"
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
'OpenFileDialogクラスのインスタンスを作成
Dim ofd As New OpenFileDialog()
ofd.Filter =
"Playファイル(*.dat)|*.dat|すべてのファイル(*.*)|*.*"
ofd.FilterIndex = 1
'タイトルを設定する
ofd.Title = "開くファイルを選択してください"
'ダイアログを表示する
If ofd.ShowDialog() = DialogResult.OK Then
'OKボタンがクリックされたとき
Dim formatter As New BinaryFormatter()
Dim inputStream As New IO.FileStream(ofd.FileName, IO.FileMode.Open)
DomainUpDown1.Items.Clear()
Try
Dim c As Integer = 0
記録 = CType(formatter.Deserialize(inputStream), Rec_List)
For Each rec As Record In 記録
'Dim rev As String = "OFF"
'If rec.逆転 Then rev = "ON"
'Dim point As String = rec.ポイント番号
'If rec.ポイント番号 = -2 Then point = "OFF"
'Dim yard As String = rec.Yard番号
'If rec.Yard番号 = -1 Then yard = "OFF"
'Dim mes As String = String.Format("{0} 路線{1} 区間{2} 逆転{3} ポイント{4} Yard{5} 停止時間{6} Speed{7}", _
' c, rec.位置.路線, rec.位置.区間, rev, point, yard, rec.停止時間, rec.スピード)
DomainUpDown1.Items.Add(記録msg(rec, c))
c += 1
Next
DomainUpDown1.SelectedIndex = 0
Finally
inputStream.Close()
PlayStep = 0
Remcon(0).CheckBox6.Enabled = True 'Play可
End Try
End If
End Sub
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
'SaveFileDialogクラスのインスタンスを作成
Dim sfd As New SaveFileDialog()
'はじめのファイル名を指定する
sfd.FileName = "新規.dat"
'はじめに表示されるフォルダを指定する
'sfd.InitialDirectory = "C:\"
'[ファイルの種類]に表示される選択肢を指定する
sfd.Filter = "Playファイル(*.dat)|*.dat|すべてのファイル(*.*)|*.*"
'[ファイルの種類]ではじめに
'「すべてのファイル」が選択されているようにする
sfd.FilterIndex = 1
'タイトルを設定する
sfd.Title = "保存先のファイルを選択してください"
'ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする
'sfd.RestoreDirectory = True
'既に存在するファイル名を指定したとき警告する
'デフォルトでTrueなので指定する必要はない
'sfd.OverwritePrompt = True
'存在しないパスが指定されたとき警告を表示する
'デフォルトでTrueなので指定する必要はない
'sfd.CheckPathExists = True
'ダイアログを表示する
If sfd.ShowDialog() = DialogResult.OK Then
'OKボタンがクリックされたとき
Console.WriteLine(sfd.FileName)
Dim formatter As New BinaryFormatter()
Dim outputStream As New IO.FileStream(sfd.FileName, IO.FileMode.Create)
Try
formatter.Serialize(outputStream, 記録)
Finally
outputStream.Close()
End Try
End If
End Sub
End Class
ContPanelのコード
Public Class ContPanel
Public Index As Integer
Public Event 逆転_Click(ByVal index As Integer)
Public Event ポイント_Click(ByVal index As Integer)
Public Event Yard_Click(ByVal index As Integer)
Public Event Rec_Click()
Private MaxSpeed As Integer = 150
Private PowerMeter_max As Integer = &HE8
Private SpeedMeter_max As Integer = &HA0
Public Sub New(id As Integer)
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
Index = id
End Sub
Public Property Speed_Cont() As Integer 'Speed コントローラ
Get
Return TrackBar1.Value
End Get
Set(ByVal Value As Integer)
TrackBar1.Value = Value
End Set
End Property
Public WriteOnly Property Yard_Cont() As Boolean
'Yard ボタンなどの操作可否
Set(ByVal Value As Boolean)
CheckBox3.Enabled = Value
CheckBox4.Enabled = Value
NumericUpDown1.Enabled = Value
DomainUpDown2.Enabled = Value
If Value Then
CheckBox3.Checked = False
End If
End Set
End Property
Public WriteOnly Property 信号() As String
Set(ByVal value As String)
Select Case value
Case "緑"
Label1.BackColor = Color.LightGreen
Case "黄"
Label1.BackColor = Color.Yellow
Case "赤"
Label1.BackColor = Color.LightPink
Case "灰"
Label1.BackColor = Color.LightGray
End Select
End Set
End Property
Public WriteOnly Property 区間表示() As Byte()
Set(ByVal value As Byte())
Dim 区間 = value(0) And &H7
Dim 路線 = (value(0) And &H38) / 8
If 路線 <> 7 Then
Label1.Text = String.Format("現 路線:{0} 区間:{1}", 路線, 区間)
区間 = value(1) And &H7
路線 = (value(1) And &H38) / 8
Label1.Text += String.Format(vbCrLf + "次 路線:{0} 区間:{1}", 路線, 区間)
Else
Label1.Text = ""
End If
End Set
End Property
Public WriteOnly Property Speed_Meter() As Integer 'Speed メーター
Set(ByVal Value As Integer)
Dim speed_max As Integer = SpeedMeter_max
Dim sp As Integer = (1 - Value / speed_max) * PictureBox1.Height
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
g.Clear(Color.White)
Dim pen As Pen = New Pen(Color.Red, 3)
Dim brush As Brush = Brushes.Pink
Dim p1 As Point = New Point(0, sp)
Dim p2 As Point = New Point(PictureBox1.Width, sp)
Dim rect As Rectangle = New Rectangle(p1, New Size(PictureBox1.Width, PictureBox1.Height - sp))
g.FillRectangle(brush, rect)
'PictureBox1.Refresh()
End Set
End Property
Public WriteOnly Property Power_Meter() As Integer 'Power メーター
Set(ByVal Value As Integer)
Dim speed_max As Integer = PowerMeter_max
Dim sp As Integer = (1 - Value / speed_max) * PictureBox1.Height
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
'g.Clear(Color.White)
Dim pen As Pen = New Pen(Color.Red, 3)
Dim brush As Brush = Brushes.Pink
Dim p1 As Point = New Point(0, sp)
Dim p2 As Point = New Point(PictureBox1.Width, sp)
g.DrawLine(pen, p1, p2)
PictureBox1.Refresh()
End Set
End Property
Public Sub add_point(p() As Form1.PointClass)
Dim n As Integer
DomainUpDown1.Items.Add("次")
While p(n) IsNot Nothing
Dim p_num = p(n).番号
If Not DomainUpDown1.Items.Contains(p_num) Then
DomainUpDown1.Items.Add(p(n).番号)
End If
n += 1
End While
DomainUpDown1.Items.Reverse()
DomainUpDown1.SelectedIndex = DomainUpDown1.Items.Count - 1
End Sub
Public Property point_num As Integer
Get
If DomainUpDown1.Text = "次" Then
Return -1
Else
Return Val(DomainUpDown1.Text)
End If
End Get
Set(value As Integer)
If value = -1 Then
DomainUpDown1.SelectedIndex = DomainUpDown1.Items.Count '次
Else
DomainUpDown1.Text = value
End If
End Set
End Property
Private Sub ContPanel_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TrackBar1.Maximum = MaxSpeed
TrackBar1.TickFrequency = 10
'スピードメーター用
Dim bmp As New Bitmap(PictureBox1.Size.Width, PictureBox1.Size.Height)
PictureBox1.Image = bmp
NumericUpDown1.Maximum = Form1.yard.Length
NumericUpDown1.Minimum = 1
NumericUpDown1_ValueChanged(Nothing, Nothing)
AddHandler Form1.yard_chg, AddressOf Yard_chg
If Index = 0 Then
'Recボタン用checkboxの設定
'CheckBox5.AutoSize = False
CheckBox5.Size = New Size(40, 25)
CheckBox5.TextAlign = ContentAlignment.MiddleCenter
'Playボタン用checkboxの設定
'CheckBox6.AutoSize = False
CheckBox6.Size = New Size(40, 25)
CheckBox6.TextAlign = ContentAlignment.MiddleCenter
CheckBox6.Enabled = False
Else
CheckBox5.Visible = False
CheckBox6.Visible = False
End If
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
RaiseEvent 逆転_Click(Index)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'停止ボタンでスライダーを0にする()
TrackBar1.Value = 0
End Sub
Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
RaiseEvent ポイント_Click(Index)
End Sub
Private Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
RaiseEvent Yard_Click(Index)
End Sub
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
Yard_chg()
End Sub
Private Sub Yard_chg()
'yard状況変化
DomainUpDown2.Items.Clear()
DomainUpDown2.SelectedIndex = -1
If Form1.列車(Index).Enable Then
'入線時
For Each s In Form1.yard(NumericUpDown1.Value - 1).空線
DomainUpDown2.Items.Add(s)
Next
Else
'発車時
For Each s In Form1.yard(NumericUpDown1.Value - 1).在線
DomainUpDown2.Items.Add(s)
Next
End If
If DomainUpDown2.Items.Count = 0 Then
DomainUpDown2.Text = "-"
Else
DomainUpDown2.SelectedIndex = DomainUpDown2.Items.Count - 1
End If
End Sub
Public Property 線番号 As Integer
Get
Return Val(DomainUpDown2.Text)
End Get
Set(value As Integer)
If DomainUpDown2.Items.Contains(value) Then
DomainUpDown2.Text = value
End If
End Set
End Property
Private Sub CheckBox5_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox5.CheckedChanged
'Rec
RaiseEvent Rec_Click()
End Sub
End Class








