PageTopへ戻る
10.8区間でループ運転
●次はいよいよ8区間を使って1ループ運転します。
・ブレッドボードを目いっぱい使用してドライブ回路を8区間分用意します。
・今回は、1列車のみの運転で、8区間に分けて制御するご利益がありませんが、 1ループに2列車同時運転の前段階として、すべてのドライブ回路の試験として行います。
【dsPICのコード】
・コードの変更はありません。
【PC側のソフト】
・前回からフォームデザインの変更はありません。
・すべてのコードを削除し、下記のコードを貼り付けます。
Imports System.IO.Ports Public Class Form1 Const Tx_Byte = 102 Const Rx_Byte = 102 Class 位置情報 Public 区間 As Integer Public 路線 As Integer Public 方向 As Integer Sub New(ByVal 区 As Integer, ByVal 路 As Integer, ByVal 向 As Integer) 区間 = 区 路線 = 路 方向 = 向 End Sub Public ReadOnly Property Byte情報() As Byte Get Return 区間 + 路線 * 8 + 方向 * &H80 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 End Class Class train Public 現位置 As 位置情報 Public 前位置 As 位置情報 Public 次位置 As 位置情報 Public 区間変化 As Byte Public speed As Single Public 逆転 As Integer Public 設定speed As Integer Sub New(ByVal 現 As 位置情報) 現位置 = 現 前位置 = 現位置.copy 前位置.前区間() 次位置 = 現位置.copy 次位置.次区間() End Sub Sub New(ByVal 現 As 位置情報, ByVal 前 As 位置情報, ByVal 次 As 位置情報) 現位置 = 現 前位置 = 前 次位置 = 次 End Sub Sub 区間変更() 前位置 = 現位置.copy 現位置 = 次位置.copy 次位置.次区間() End Sub Sub 逆転処理() '現位置を前位置に、前位置を現位置に 現位置.逆転() 前位置.逆転() 次位置 = 現位置.copy '前位置に入れるため 現位置 = 前位置.copy 前位置 = 次位置.copy 次位置 = 現位置.copy 次位置.次区間() End Sub End Class Dim 列車(8) As train 'デリゲートの宣言 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 p As Integer Label1.Text = byteArray.Length If byteArray.Length <> Rx_Byte Then Exit Sub 'ポートのバッファから読み込み SerialPort1.Read(byteArray, 0, SerialPort1.BytesToRead) 'ヘッダーチェック If (byteArray(0) <> &H55) Or (byteArray(1) <> &HAA) Then Exit Sub 'ADCの値 Dim ADC As Integer = byteArray(2) * 256 + byteArray(3) Dim speed_max = 500 Dim speed As Integer 'TrackBarが0のとき2.5VGND基準電圧を読み込みます。 If TrackBar1.Value = 0 Then '10回の移動平均をとります。 GND_Level(p) = ADC p += 1 If p > 9 Then p = 0 TrackBar1.Enabled = True '最初の平均が出てからTrackBarをEnableします。 End If End If If TrackBar1.Enabled Then 'スピードメータ− speed = Math.Abs(ADC - GND_Level.Average) RectangleShape2.Height = speed / speed_max * RectangleShape1.Height RectangleShape2.Top = RectangleShape1.Top + RectangleShape1.Height - RectangleShape2.Height End If '区間変化の確認 If byteArray(4) = &H80 Then '区間変化 列車(0).区間変更() 列車(0).区間変化 = 1 Else '区間変化フラグクリア 列車(0).区間変化 = 0 End If 'ラベルに位置表示 Label1.Text = "現:" & 列車(0).現位置.区間 & " 前:" & 列車(0).前位置.区間 & " 次:" & 列車(0).次位置.区間 End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'ポート接続処理 SerialPort1.PortName = ComboBox1.Text 'SerialPort1.PortName = "COM5" '決まっている場合は直接指定 SerialPort1.BaudRate = 115200 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 TrackBar1.Enabled = False End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick '200msタイマー Dim Txdata(Tx_Byte) As Byte Const 加速 As Single = 0.3 '加速割合 'ヘッダーとして&H55,&HAAを送る Txdata(0) = &H55 Txdata(1) = &HAA 'speed 加速・減速 列車(0).speed += (TrackBar1.Value - 列車(0).speed) * 加速 If 列車(0).逆転 = 1 Then If Int(列車(0).speed) = 0 Then '列車が停止したら逆転 列車(0).逆転処理() 列車(0).逆転 = 0 'スピード戻し TrackBar1.Value = 列車(0).設定speed '逆転ボタン戻し CheckBox1.Checked = False End If End If 'speed値を送信します。 Txdata(2) = Int(列車(0).speed) 'speed data Txdata(3) = 列車(0).現位置.Byte情報 Txdata(4) = 列車(0).前位置.Byte情報 Txdata(5) = 列車(0).次位置.Byte情報 Txdata(6) = 列車(0).区間変化 Try SerialPort1.Write(Txdata, 0, Tx_Byte) 'Tx_BYTEデータ送信 Catch ex As Exception 'エラーのとき Button2_Click(Nothing, Nothing) '切断 MsgBox(ex.Message) End Try End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '列車情報設定 列車(0) = New train(New 位置情報(1, 0, 0)) Dim ports As String() = SerialPort.GetPortNames() If ports.Count = 0 Then MsgBox("シリアルポートが見つかりません。") : End '使用可能なシリアルポートをコンボボックスに登録 ComboBox1.Items.AddRange(ports) ComboBox1.SelectedIndex = 0 Me.Text = "PC Remote" Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Fixed3D Me.MinimizeBox = False Me.MaximizeBox = False Button1.Text = "接続" Button2.Text = "切断" Button2.Enabled = False '切断ボタンdisable '逆転ボタン用checkboxの設定 CheckBox1.Appearance = Appearance.Button CheckBox1.AutoSize = False CheckBox1.Size = Button1.Size CheckBox1.TextAlign = ContentAlignment.MiddleCenter CheckBox1.Text = "逆転" 'スピードメーターの設定 RectangleShape2.FillStyle = PowerPacks.FillStyle.Solid RectangleShape2.FillColor = Color.Pink RectangleShape2.Left = RectangleShape1.Left RectangleShape2.Width = RectangleShape1.Width RectangleShape2.Height = 0 RectangleShape2.Top = RectangleShape1.Top + RectangleShape1.Height - RectangleShape2.Height TrackBar1.Enabled = False TrackBar1.Maximum = 255 TrackBar1.TickFrequency = 10 Timer1.Interval = 200 'タイマーインターバル200ms End Sub Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged '逆転ボタン確認 If CheckBox1.Checked Then '列車逆転のため停止させる 列車(0).逆転 = 1 列車(0).設定speed = TrackBar1.Value TrackBar1.Value = 0 End If End Sub End Class
・VB2013の場合のコード
Imports System.IO.Ports Public Class Form1 Const Tx_Byte = 102 Const Rx_Byte = 102 Class 位置情報 Public 区間 As Integer Public 路線 As Integer Public 方向 As Integer Sub New(ByVal 区 As Integer, ByVal 路 As Integer, ByVal 向 As Integer) 区間 = 区 路線 = 路 方向 = 向 End Sub Public ReadOnly Property Byte情報() As Byte Get Return 区間 + 路線 * 8 + 方向 * &H80 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 End Class Class train Public 現位置 As 位置情報 Public 前位置 As 位置情報 Public 次位置 As 位置情報 Public 区間変化 As Byte Public speed As Single Public 逆転 As Integer Public 設定speed As Integer Sub New(ByVal 現 As 位置情報) 現位置 = 現 前位置 = 現位置.copy 前位置.前区間() 次位置 = 現位置.copy 次位置.次区間() End Sub Sub New(ByVal 現 As 位置情報, ByVal 前 As 位置情報, ByVal 次 As 位置情報) 現位置 = 現 前位置 = 前 次位置 = 次 End Sub Sub 区間変更() 前位置 = 現位置.copy 現位置 = 次位置.copy 次位置.次区間() End Sub Sub 逆転処理() '現位置を前位置に、前位置を現位置に 現位置.逆転() 前位置.逆転() 次位置 = 現位置.copy '前位置に入れるため 現位置 = 前位置.copy 前位置 = 次位置.copy 次位置 = 現位置.copy 次位置.次区間() End Sub End Class Dim 列車(8) As train 'デリゲートの宣言 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 p As Integer Label3.Text = byteArray.Length If byteArray.Length <> Rx_Byte Then Exit Sub 'ポートのバッファから読み込み SerialPort1.Read(byteArray, 0, SerialPort1.BytesToRead) 'ヘッダーチェック If (byteArray(0) <> &H55) Or (byteArray(1) <> &HAA) Then Exit Sub 'ADCの値 Dim ADC As Integer = byteArray(2) * 256 + byteArray(3) Dim speed_max = 500 Dim speed As Integer 'TrackBarが0のとき2.5VGND基準電圧を読み込みます。 If TrackBar1.Value = 0 Then '10回の移動平均をとります。 GND_Level(p) = ADC p += 1 If p > 9 Then p = 0 TrackBar1.Enabled = True '最初の平均が出てからTrackBarをEnableします。 End If End If If TrackBar1.Enabled Then 'スピードメータ− speed = Math.Abs(ADC - GND_Level.Average) Label2.Height = speed / speed_max * Label1.Height Label2.Top = Label1.Top + Label1.Height - Label2.Height End If '区間変化の確認 If byteArray(4) = &H80 Then '区間変化 列車(0).区間変更() 列車(0).区間変化 = 1 Else '区間変化フラグクリア 列車(0).区間変化 = 0 End If 'ラベルに位置表示 Label3.Text = "現:" & 列車(0).現位置.区間 & " 前:" & 列車(0).前位置.区間 & " 次:" & 列車(0).次位置.区間 End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'ポート接続処理 SerialPort1.PortName = ComboBox1.Text 'SerialPort1.PortName = "COM5" '決まっている場合は直接指定 SerialPort1.BaudRate = 115200 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 TrackBar1.Enabled = False End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick '200msタイマー Dim Txdata(Tx_Byte) As Byte Const 加速 As Single = 0.3 '加速割合 'ヘッダーとして&H55,&HAAを送る Txdata(0) = &H55 Txdata(1) = &HAA 'speed 加速・減速 列車(0).speed += (TrackBar1.Value - 列車(0).speed) * 加速 If 列車(0).逆転 = 1 Then If Int(列車(0).speed) = 0 Then '列車が停止したら逆転 列車(0).逆転処理() 列車(0).逆転 = 0 'スピード戻し TrackBar1.Value = 列車(0).設定speed '逆転ボタン戻し CheckBox1.Checked = False End If End If 'speed値を送信します。 Txdata(2) = Int(列車(0).speed) 'speed data Txdata(3) = 列車(0).現位置.Byte情報 Txdata(4) = 列車(0).前位置.Byte情報 Txdata(5) = 列車(0).次位置.Byte情報 Txdata(6) = 列車(0).区間変化 Try SerialPort1.Write(Txdata, 0, Tx_Byte) 'Tx_BYTEデータ送信 Catch ex As Exception 'エラーのとき Button2_Click(Nothing, Nothing) '切断 MsgBox(ex.Message) End Try End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '列車情報設定 列車(0) = New train(New 位置情報(1, 0, 0)) 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 Me.Text = "PC Remote" Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Fixed3D Me.MinimizeBox = False Me.MaximizeBox = False Button1.Text = "接続" Button2.Text = "切断" Button2.Enabled = False '切断ボタンdisable '逆転ボタン用checkboxの設定 CheckBox1.Appearance = Appearance.Button CheckBox1.AutoSize = False CheckBox1.Size = Button1.Size CheckBox1.TextAlign = ContentAlignment.MiddleCenter CheckBox1.Text = "逆転" 'スピードメーターの設定 Label1.Text = "" Label2.Text = "" Label2.BackColor = Color.Pink Label2.Left = Label1.Left Label2.Width = Label1.Width Label2.Height = 0 Label2.Top = Label1.Top + Label1.Height - Label2.Height TrackBar1.Enabled = False TrackBar1.Maximum = 255 TrackBar1.TickFrequency = 10 Timer1.Interval = 200 'タイマーインターバル200ms End Sub Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged '逆転ボタン確認 If CheckBox1.Checked Then '列車逆転のため停止させる 列車(0).逆転 = 1 列車(0).設定speed = TrackBar1.Value TrackBar1.Value = 0 End If End Sub End Class
・前回からの変更は、区間が変わっても逆転しないことと、逆転ボタンを生かして、押した時に逆転処理をすることです。
・列車の初期位置は区間1になっていますので、区間0か1に列車を置いてスタートしてください。
・逆転ボタンを押すと、減速、停止してから逆転します。
11.1ループ2列車同時運転
●次は1つのループに2台の列車を同時に走行させます。
・互いの列車は相手列車の位置を確認しあいながら衝突しないように走行します。
・2台の列車を動かす為、それぞれの区間をONにしますが、電源への負荷を考えてスピードパルスのONの時期を A相、B相にずらします。
・A相はIntCountが0から、B相は256(0x100)からパルスONします。
【dsPICのコード】
※2013/12/7 一部変更
// PCリモートによるモーター制御 // 2列車同時制御 #include
#include
#include
#include
//16bitのINT型の上位H byte、下位L byte読み込み用共用体 union byte_access { int INT; // Int Access struct{ // byte Access unsigned char L; unsigned char H; }BYTE; }; //位置情報の構造体 struct PSI_BIT{ unsigned char KUKAN:3; /* 区間 Bit 0-2 */ unsigned char ROSEN:3; /* 路線 Bit 3-5 */ unsigned char SOU:1; /* 相 Bit 6 */ unsigned char DIR:1; /* 方向 Bit 7 */ }; //列車の位置情報の構造体 struct st_position { //現在位置 union { /* Position */ unsigned char BYTE; /* Byte Access */ struct PSI_BIT BIT; /* Bit Access */ } NOW; //前の位置 union { /* Position */ unsigned char BYTE; /* Byte Access */ struct PSI_BIT BIT; /* Bit Access */ } BEFORE; //次の位置 union { /* Position */ unsigned char BYTE; /* Byte Access */ struct PSI_BIT BIT; /* Bit Access */ } NEXT; //次の次の位置 union { /* Position */ unsigned char BYTE; /* Byte Access */ struct PSI_BIT BIT; /* Bit Access */ } ANEXT; unsigned int speed; unsigned char henka; unsigned char safe; union byte_access speed_ret; //読み取りスピード }; //監視区間設定用の共用体 union scan_port { unsigned char BYTE; /* Byte Access */ struct { unsigned char DUMMY:2; /* Bit 0-1 */ unsigned char KUKAN:3; /* Bit 2-4 監視区間*/ unsigned char DISABLE:1; /* Bit 5 */ unsigned char B6:1; /* Bit 6 */ } BIT; }; // A/D control register unsigned int _ADCON1; unsigned int _ADCON2; unsigned int _ADCON3; unsigned int _ADCHS; unsigned int _ADPCFG; unsigned int _ADCSSL ; // UART control register unsigned int _U1BRG; unsigned int _U1MODE; unsigned int _U1STA; #define Fcy 7370000*4 #define BaudRate 115200 #define RX_BYTE 100 //RS232C受信バイト数 #define TX_BYTE 100 //RS232C送信バイト数 #define RX_DATA_BYTE 12 #define TX_DATA_BYTE 12 #define TR_COUNT 2 #define ROSEN_NUM 0 unsigned char RxData[RX_BYTE]; //RS232C受信用メモリ unsigned char TxData[TX_BYTE]; //RS232C送信用メモリ unsigned char EnableBit[] ={1,2,4,8,16,32,64,128}; unsigned int int_counter; //インタラプトカウンタ unsigned int speed_pw[2]; //スピードパルス幅 unsigned int speed_set; //スピード設定 unsigned char direction; //方向 struct st_position train[TR_COUNT]; //列車位置情報 unsigned char kukan[2]; //区間 unsigned char kanshi_now[2]; //区間 unsigned char kanshi_before[2]; //区間 union scan_port kanshi; //区間監視用 unsigned char cont_train[2]; //相 unsigned char pre_cont_train[2]; unsigned char lock_chg; union byte_access gnd_level; unsigned int gnd_sum; unsigned char sum_count; unsigned int speed_peak; union byte_access adc_ret; //ADC値 void kukan_ON(unsigned char,unsigned char); void kukan_OFF(unsigned char); int main(void) { unsigned char n; unsigned char p; //dsPIC基板のブートローダーの制約によりAIVTを使用 INTCON2bits.ALTIVT=1; // A/D変換モジュールオフ確認 _ADON=0; // A/D変換モジュール初期化 (PB9をADCに使用) _ADCHS= ADC_CH0_POS_SAMPLEA_AN9 & ADC_CH0_NEG_SAMPLEA_NVREF; SetChanADC12(_ADCHS); // ADC割り込み禁止 ConfigIntADC12(ADC_INT_DISABLE); _ADCON1=ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_OFF & ADC_SAMP_OFF; _ADCON2=ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF; _ADCON3=ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_10Tcy; _ADPCFG=ENABLE_AN9_ANA; _ADCSSL=SCAN_NONE; OpenADC12(_ADCON1, _ADCON2, _ADCON3, _ADPCFG, _ADCSSL); //Timer1設定 OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_1 & T1_SYNC_EXT_OFF & T1_SOURCE_INT, 586); ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON); // UART1モジュールのオフを確認します CloseUART1(); // UART1割り込み禁止 ConfigIntUART1(UART_RX_INT_DIS & UART_TX_INT_DIS); // UART1の初期化 _U1BRG=((Fcy/BaudRate)/16); // パリティなし、データ8bit、ストップ1bit _U1MODE=UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT; _U1STA= UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR; // Open UART1 OpenUART1(_U1MODE, _U1STA, _U1BRG); TRISB=0xff; //PB:IN Portに設定 _TRISB9=1; //PB9:ADC入力端子 In Portに設定 TRISF=0; //RFポート OutPortに設定 cont_train[0]=0xff; //A相列車:0 cont_train[1]=0xff; //B相列車:なし //main loop while(1) { //RS232Cの受信 //ヘッダー確認 while(U1STAbits.URXDA==0); // wait RX data if(U1RXREG == 0x55){ while(U1STAbits.URXDA==0); // wait RX data if(U1RXREG == 0xAA){ //0x55,0xAAが続けてきたら正しいデータとして受信 for(n=0;n
0x1ff){ int_counter = 0; } //インタラプトカウンタが0のときA相のspeedパルスON n=0xff; if(int_counter == 0){ sou=0; //A相 cont_train[0] = pre_cont_train[0]; n=cont_train[0]; } //インタラプトカウンタが0x100のときB相のspeedパルスON if(int_counter == 0x100){ sou=1; //B相 cont_train[1] = pre_cont_train[1]; n=cont_train[1]; } if(n != 0xff){ speed_pw[sou] = train[n].speed; //speedパルス幅のセット //区間メモリに現・前位置の区間を設定し区間ON if(train[n].NOW.BIT.ROSEN==ROSEN_NUM){ kukan[sou] = EnableBit[train[n].NOW.BIT.KUKAN]; kanshi_now[sou] = train[n].NOW.BIT.KUKAN; } if(train[n].BEFORE.BIT.ROSEN==ROSEN_NUM){ kukan[sou] |= EnableBit[train[n].BEFORE.BIT.KUKAN]; kanshi_before[sou] = train[n].BEFORE.BIT.KUKAN; } // 区間ON kukan_ON(kukan[sou] , train[n].NOW.BIT.DIR); } //インタラプトカウンタが0x1のときA相の区間変化監視(B相は0x102のとき) n=0xff; if(int_counter == 2){ n=cont_train[0]; } if(int_counter ==0x102){ n=cont_train[1]; } if(n != 0xff){ if(train[n].safe) if(!train[n].henka ){ if(train[n].NEXT.BIT.ROSEN==ROSEN_NUM){ //次位置区間の監視 kanshi.BIT.KUKAN=train[n].NEXT.BIT.KUKAN; LATF &= 0xC0; LATF |= kanshi.BYTE; //ADC読み込み _SAMP=1; while(!ADCON1bits.DONE); adc_ret.INT = ADCBUF0; if(train[n].NOW.BIT.DIR==0){ //正方向のとき if(adc_ret.BYTE.H > 0xB){ train[n].henka=0x80; //区間変化 } } else{ //逆方向のとき if(adc_ret.BYTE.H < 0x4){ train[n].henka=0x80; //区間変化 } } //GND_LEVEL設定 if(!train[n].henka){ //区間変更なしのときのADC値をGND Levelにします。 //16回たして4bit右シフトで平均をとります。 if(adc_ret.INT>0x780 && adc_ret.INT<0x880){ gnd_sum += adc_ret.INT; if(sum_count++ == 15){ gnd_level.INT=gnd_sum >> 4; sum_count=0; gnd_sum=0; } } } } } } //インタラプトカウンタが3のときNEXT区間パルスON(B相は0x103のとき) //区間変化確認後に次区間もON n=0xff; if(int_counter == 3){ n=cont_train[0]; } if(int_counter == 0x103){ n=cont_train[1]; } if(n != 0xff){ if(train[n].safe){ //安全でないときは次区間に他の列車がかかっているのでONしない。 if(train[n].NEXT.BIT.ROSEN==ROSEN_NUM) kukan[sou] |= EnableBit[train[n].NEXT.BIT.KUKAN]; kukan_ON(kukan[sou] , train[n].NOW.BIT.DIR); } } //インタラプトごとにspeedをマイナス1して0になったらパルスOFF for(n=0; n<2; n++){ if(cont_train[n] != 0xFF){ if(speed_pw[n] == 0){ //speedが0で区間パルスOFF TRISB |= kukan[n]; } else{ speed_pw[n]--; //speedをマイナス1 } } } //インタラプトカウンタが0x1F8?0x1ffのときA相のモーターの発電電圧を8回読み込み //(B相は0xf8?0xff) n=0xff; if((int_counter & 0x1f8) == 0x1f8){ n=cont_train[0]; sou=0; } if((int_counter & 0x1f8) == 0xf8){ n=cont_train[1]; sou=1; } if(n != 0xff){ //現位置と前位置を交互に読み込み if(int_counter & 0x1) kanshi.BIT.KUKAN=kanshi_now[sou]; else kanshi.BIT.KUKAN=kanshi_before[sou]; LATF &= 0xC0; LATF |= kanshi.BYTE; //ADC読み込み _SAMP=1; while(!ADCON1bits.DONE); adc_ret.INT = ADCBUF0; //ADC値からGND値を引いて絶対値をとります。 adc_ret.INT = adc_ret.INT - gnd_level.INT; if(adc_ret.INT < 0) adc_ret.INT = -adc_ret.INT; //8回のピーク値をスピードデータにします。 if(adc_ret.INT > speed_peak) speed_peak = adc_ret.INT; train[n].speed_ret.INT=speed_peak; } else speed_peak=0; //変更禁止セット(232C受信データを設定するタイミングを指定します。) switch(int_counter){ case 0x110: lock_chg=0; break; case 0x120: lock_chg=1; break; } _RF6=0;//割り込み終了監視 _T1IF = 0; //割り込みフラグ解除 } //区間ON用 void kukan_ON(unsigned char kukan,unsigned char d){ // d=0:正回転, 1:負回転 if(d==0) LATB |= kukan; else LATB &= ~kukan; TRISB &= ~kukan; } //区間OFF用 void kukan_OFF(unsigned char kukan){ TRISB |= kukan; }
【PC側のソフト】
【Form1用コード】
※テキスト部分を右クリック、すべて選択してまた右クリックし、コピーします。
Imports System.IO.Ports Public Class Form1 Const Tx_Byte As Integer = 102 Const Rx_Byte As Integer = 102 Const TxData数 As Integer = 12 Const RxData数 As Integer = 12 Const 列車数 As Integer = 2 Private Remcon As List(Of ContPanel) = New List(Of ContPanel)() 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 End Class Class train Public 現位置 As 位置情報 Public 前位置 As 位置情報 Public 次位置 As 位置情報 Public 区間変化 As Boolean Public 安全 As Boolean Public speed As Single Public 逆転 As Integer Public 設定speed As Integer Sub New(ByVal 現 As 位置情報) 現位置 = 現 前位置 = 現位置.copy 前位置.前区間() 次位置 = 現位置.copy 次位置.次区間() End Sub Sub New(ByVal 現 As 位置情報, ByVal 前 As 位置情報, ByVal 次 As 位置情報) 現位置 = 現 前位置 = 前 次位置 = 次 End Sub Sub 区間変更() 前位置 = 現位置.copy 現位置 = 次位置.copy 次位置.次区間() End Sub Sub 逆転処理() '現位置を前位置に、前位置を現位置に 現位置.逆転() 前位置.逆転() 次位置 = 現位置.copy '前位置に入れるため 現位置 = 前位置.copy 前位置 = 次位置.copy 次位置 = 現位置.copy 次位置.次区間() End Sub Public ReadOnly Property Status As Byte Get Dim ret As Byte If 区間変化 Then ret = 1 If 安全 Then ret += &H80 Return ret End Get End Property End Class Dim 列車(8) As train 'デリゲートの宣言 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 Label1.Text = byteArray.Length If byteArray.Length <> Rx_Byte Then Exit Sub 'ポートのバッファから読み込み SerialPort1.Read(byteArray, 0, SerialPort1.BytesToRead) 'ヘッダーチェック If (byteArray(0) <> &H55) Or (byteArray(1) <> &HAA) Then Exit Sub Dim GND As Integer = byteArray(22) * 256 + byteArray(23) Label1.Text = "GND値:" & Hex(GND) Dim speed As Integer For n = 0 To 列車数 - 1 Dim pos As Integer = RxData数 * n 'スピードメータ− speed = byteArray(pos + 2) * 256 + byteArray(pos + 3) Remcon(n).Speed_Meter = speed '区間変化の確認 If byteArray(pos + 4) = &H80 Then '区間変化 列車(n).区間変更() 列車(n).区間変化 = True Else '区間変化フラグクリア 列車(n).区間変化 = False End If 'ラベルに位置表示 Remcon(n).Label1.Text = "現:" & 列車(n).現位置.区間 & " 前:" & 列車(n).前位置.区間 & " 次:" & 列車(n).次位置.区間 Next '安全確認 For n = 0 To 列車数 - 1 Select Case 安全確認(n) Case "停止" 列車(n).安全 = False 列車(n).設定speed = 0 Remcon(n).信号 = 2 Case "安全" Remcon(n).信号 = 0 列車(n).安全 = True '逆転フラグが1なら逆転のため停止 If 列車(n).逆転 = 1 Then 列車(n).設定speed = 0 Else 列車(n).設定speed = Remcon(n).Speed_Cont End If End Select Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'ポート接続処理 SerialPort1.PortName = ComboBox1.Text 'SerialPort1.PortName = "COM5" '決まっている場合は直接指定 SerialPort1.BaudRate = 115200 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 '200msタイマー Dim Txdata(Tx_Byte) As Byte Const 加速 As Single = 0.3 '加速割合 'ヘッダーとして&H55,&HAAを送る Txdata(0) = &H55 Txdata(1) = &HAA For n = 0 To 列車数 - 1 'speed 加速・減速 列車(n).speed += (列車(n).設定speed - 列車(n).speed) * 加速 '逆転フラグ確認 If 列車(n).逆転 = 1 Then If Int(列車(n).speed) = 0 Then '列車が停止したら逆転 列車(n).逆転処理() 列車(n).逆転 = 0 '逆転ボタン戻し Remcon(n).CheckBox1.Checked = False Remcon(n).CheckBox1.Enabled = True 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 Next Try SerialPort1.Write(Txdata, 0, Tx_Byte) 'Tx_BYTEデータ送信 Catch ex As Exception 'エラーのとき Button2_Click(Nothing, Nothing) '切断 MsgBox(ex.Message) End Try 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("シリアルポートが見つかりません。") : End '使用可能なシリアルポートをコンボボックスに登録 ComboBox1.Items.AddRange(ports) ComboBox1.SelectedIndex = 0 Me.Text = "PC Remote" Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Fixed3D Me.MinimizeBox = False Me.MaximizeBox = False Button1.Text = "接続" Button2.Text = "切断" Button2.Enabled = False '切断ボタンdisable '列車情報設定 列車(0) = New train(New 位置情報(1, 0, 0, 0)) 列車(1) = New train(New 位置情報(4, 0, 0, 1)) For n As Integer = 0 To 列車数 - 1 Remcon.Add(New ContPanel(n)) Remcon(n).Left = Remcon(0).Width * n + 2 Controls.Add(Remcon(n)) AddHandler Remcon(n).逆転_Click, AddressOf 逆転_Click Next Timer1.Interval = 200 'タイマーインターバル200ms End Sub Function 安全確認(ByVal n As Integer) As String 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).次位置.路線 = 列車(m).次位置.路線) And _ (列車(n).次位置.区間 = 列車(m).次位置.区間) Then 停止 = True End If Next If 減速 Then Return "減速" If 停止 Then Return "停止" Return "安全" End Function Private Sub 逆転_Click(ByVal index As Integer) '逆転ボタン確認 If Remcon(index).CheckBox1.Checked Then '列車逆転のため停止させる 列車(index).逆転 = 1 Remcon(index).CheckBox1.Enabled = False End If End Sub End Class
【ユーザーコントロールContPanel用コード】
Public Class ContPanel Public Index As Integer Public Event 逆転_Click(ByVal index As Integer) Public Sub New(ByVal i As Integer) ' The Me.InitializeComponent call is required for Windows Forms designer support. Me.InitializeComponent() ' ' TODO : Add constructor code after InitializeComponents ' Index = i 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 Speed_Meter() As Integer 'Speed メーター Set(ByVal Value As Integer) Dim speed_max As Integer = 500 RectangleShape2.Height = CInt(Value / speed_max * RectangleShape1.Height) RectangleShape2.Top = RectangleShape1.Top + RectangleShape1.Height - RectangleShape2.Height End Set End Property Public WriteOnly Property 信号() As Integer Set(ByVal value As Integer) Select Case value Case 0 Label1.BackColor = Color.LightGreen Case 1 Label1.BackColor = Color.LightYellow Case 2 Label1.BackColor = Color.LightPink End Select End Set End Property Private Sub ContPanel_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load TrackBar1.Maximum = 255 TrackBar1.TickFrequency = 10 'スピードメーターの設定 RectangleShape2.FillStyle = PowerPacks.FillStyle.Solid RectangleShape2.FillColor = Color.Pink RectangleShape2.Left = RectangleShape1.Left RectangleShape2.Width = RectangleShape1.Width RectangleShape2.Height = 0 RectangleShape2.Top = RectangleShape1.Top + RectangleShape1.Height - RectangleShape2.Height '逆転ボタン用checkboxの設定 CheckBox1.Appearance = Appearance.Button CheckBox1.AutoSize = False CheckBox1.Size = Button1.Size CheckBox1.TextAlign = ContentAlignment.MiddleCenter CheckBox1.Text = "逆転" Button1.Text = "停止" Label1.BackColor = Color.LightGreen End Sub Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged RaiseEvent 逆転_Click(Index) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click '停止ボタンでスライダーを0にする() TrackBar1.Value = 0 End Sub End Class
実行画面
・2台の列車の初期位置は区間1と区間4です。
・VB2013の場合
・Form1のデザインはVB2010と同様に行います。Labelはすべて削除してからLabel1を追加します。
・Form1用のコードはVB2010と同じです。
・ユーザーコントロールのContPanelのスピードメーターはRectangleShapeの代わりにLabelを使用します。
LabelのAutoSizeプロパティはFalse、BorderStileはFixedSingleに変更します。
【VB2013用ContPanel用コード】
Public Class ContPanel Public Index As Integer Public Event 逆転_Click(ByVal index As Integer) Public Sub New(ByVal i As Integer) ' The Me.InitializeComponent call is required for Windows Forms designer support. Me.InitializeComponent() ' ' TODO : Add constructor code after InitializeComponents ' Index = i 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 Speed_Meter() As Integer 'Speed メーター Set(ByVal Value As Integer) Dim speed_max As Integer = 500 Label3.Height = CInt(Value / speed_max * Label2.Height) Label3.Top = Label2.Top + Label2.Height - Label3.Height End Set End Property Public WriteOnly Property 信号() As Integer Set(ByVal value As Integer) Select Case value Case 0 Label1.BackColor = Color.LightGreen Case 1 Label1.BackColor = Color.LightYellow Case 2 Label1.BackColor = Color.LightPink End Select End Set End Property Private Sub ContPanel_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load TrackBar1.Maximum = 255 TrackBar1.TickFrequency = 10 'スピードメーターの設定 Label2.Text = "" Label3.Text = "" Label3.BackColor = Color.Pink Label3.Left = Label2.Left Label3.Width = Label2.Width Label3.Height = 0 Label3.Top = Label2.Top + Label2.Height - Label3.Height '逆転ボタン用checkboxの設定 CheckBox1.Appearance = Appearance.Button CheckBox1.AutoSize = False CheckBox1.Size = Button1.Size CheckBox1.TextAlign = ContentAlignment.MiddleCenter CheckBox1.Text = "逆転" Button1.Text = "停止" Label1.BackColor = Color.LightGreen End Sub Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged RaiseEvent 逆転_Click(Index) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click '停止ボタンでスライダーを0にする() TrackBar1.Value = 0 End Sub End Class
・下記からVB2010プロジェクトをダウンロード出来ます。
・remote.lzhを解凍し、フォルダー内の"remote.vbproj"をダブルクリックしてプロジェクトを開いてください。
remote.lzhのダウンロード
●安全確認
次へ
PageTopへ戻る