VB2013でSWRをビジュアル表示
自作工程のメモとして
Feb.2015
Edit by SeaMonkey Composer.
1.仕様 |
ソフトを作成するにしても、 実現したいことが明確になっていないと始まりませんので、次のような目標を立てました。
また、ソフト名称は、SDAAtool (Screw Driver Antenna Analysis tool)としています。
■ 目標
使用しているScrewdriverアンテナのSWR特性をビジュアル表示する。
■ 仕様
1.別掲載の「Hi-Q-4/160 コントローラ製作」 で使用しているコントローラを使用する。■ CI-Vコマンドの拡張
2.コントロールは、CI-Vを拡張して使用する。
3.CI-V拡張コマンドは、アドレス部やコマンドを変更できるようにする。
4.コントローラを操作している赤外線リモコンと同じ動作をパソコン(以降PCと略す)からも操作できるようにする。
5.
1.コントローラ側のアドレスを"E1"、PC側を"E2"とする。(変更可能)
2.拡張コマンドを"AA"とする。(変更可能)
3.サブコマンドを使用して各々の指示をする。
4.コマンドの確認は、コントローラ側のレスポンスではなく、送出信号の衝突を検出して再送をする。
■ CI-Vコマンド・レスポンスのデータ形式
*周波数は、百Hzまでとし、実際の送出はKHzまでのデータを送出している。
*連番は、00〜99を繰り返し、レスポンス(返送されるデータ)の欠落を検出するため付加している。
2.Hi-Q-4/160 コントローラ側の処理 |
Hi-Q-4/160 コントローラ側は、ハードの変更は無くソフトの追記のみで実現できましたが、手間がかかったのが可変長のコマンドを受け取るCI-Vの受信(割り込み)処理でした。
■ 割り込みによる受信処理(PIC 18F452 , MikroC PRO for PIC 6.4)
void interrupt() {
if (INTCON.TMR0IF) {
t0_count++;
TMR0L = 131; // 131 to 256 = 125count(≒0.1mS)
INTCON.TMR0IF = 0;
}
if(PIR1.RCIF){
if (UART1_Data_Ready() == 1) { // If data is received,
uart_rd = UART1_Read(); // read the received data,
switch (civ_count) {
case 10: if (uart_rd == 0xFD)
civ_count++;
else civ_count = 0;
break;
case 9: if (extn_count == 4)
Ext_bcd[0] = uart_rd;
civ_bcd[3] = 0;
civ_count++;
break;
case 8: civ_bcd[0] = uart_rd;
civ_count++;
break;
case 7: civ_bcd[1] = uart_rd;
civ_count++;
break;
case 6: if (extn_count == 4){
if(uart_rd == 0xfd) {
civ_count = 11;
break;
}
}
civ_bcd[2] = uart_rd;
civ_count++;
break;
case 5: if (extn_count == 3){
switch (uart_rd ){
case 0x01:
case 0x02:
case 0x03:
case 0xF1:
case 0xF2:
Extn_sub = uart_rd;
extn_count++;
break;
default:
Extn_sub = 0;
extn_count = 0;
break;
}
}
if(uart_rd == 0xfd)
civ_count = 0;
else civ_count++;
break;
case 4: if (uart_rd == ExtnCIVcmd) // 拡張 自作CI-Vコマンドなら
extn_count++;
else extn_count = 0;
if(uart_rd == 0xfd)
civ_count = 0;
else civ_count++;
break;
case 3: if (uart_rd == HostCIVadd) // 拡張 PCからのコマンドなら
extn_count++;
else extn_count = 0;
if(uart_rd == 0xfd)
civ_count = 0;
else civ_count++;
break;
case 2: if (uart_rd == ContCIVadd) // 拡張 Hi-Q_CONTへのコマンドなら
extn_count = 1;
else extn_count = 0;
if(uart_rd == 0xfd)
civ_count = 0;
else civ_count++;
break;
case 1: if (uart_rd == 0xFE)
civ_count++;
else civ_count = 0;
break;
case 0: if (uart_rd == 0xFE)
civ_count++;
else civ_count = 0;
break;
default: break;
}
}
PIR1.RCIF = 0;
}
if(INTCON.INT0IF == 1) { //RB0/INT割込み 赤外線リモコン
INTCON.INT0IE = 0; //RB0/INT割込みの禁止
switch(IN_red) {
case 0:
t0_count = 0;
IN_red++;
TMR0L = 131; // 131 to 256 = 125count(≒0.1mS)
INTCON.TMR0IE = 1; //Timer0/INT割込みの許可
break;
case 1:
if(xxx == 0) xxx = t0_count;
if((t0_count >= 40) && (t0_count <= 62)){ //実測4.9mS
t0_count = 0;
IN_red++;
}else{ //範囲を外れた
IN_red = 0;
INTCON.TMR0IE = 0; //Timer0/INT割込みの禁止
}
break;
case 66:
IR_flag = 1;
IN_red = 0;
// SENS_1 = 0; // Debug用LED点灯●
break;
default:
if((IN_red >= 2) && (IN_red <= 65)) { // 8Byte = 64bit
if(t0_count >= 21){ // 2.1mS以上なら無効
IN_red = 0;
INTCON.TMR0IE = 0; //Timer0/INT割込みの禁止
}else{
irx = (IN_red - 2) / 8;
IR_buff[irx] = IR_buff[irx] >> 1;
if(t0_count <= 12){ // 1.2mSが敷居値
IR_buff[irx].B7 = 0;
}else{
IR_buff[irx].B7 = 1;
}
t0_count = 0;
IN_red++;
}
}
break;
}
INTCON.INT0IF = 0; //RB0/INT0割込みフラグクリアー
INTCON.INT0IE = 1; //RB0/INT0割込みの許可
}
if(INTCON3.INT1IF == 1) { //回転検出
INTCON3.INT1IE = 0; //RB1/INT1割込みの禁止
switch(Motor_U1D2 ) { // 方向レジスター
case 1: // UP方向
SENSOR_SW_CNT++;
// if ( SENSOR_SW_CNT >= 0 ) { Limit_U1D2 = 0; }
break;
case 2: // DW方向
SENSOR_SW_CNT--;
// if ( SENSOR_SW_CNT < SENSOR_MAX ) { Limit_U1D2 = 0; }
break;
default:
break;
}
INTCON3.INT1IF = 0; //RB1/INT1割込みフラグクリアー
INTCON3.INT1IE = 1; //RB1/INT1割込みの許可
}
if(INTCON3.INT2IF == 1) { //電流オーバー
INTCON3.INT2IE = 0; //RB2/INT2割込みの禁止
M_shut(); // モーターを即時遮断
switch(Motor_U1D2 ) { // 方向レジスター
case 1: // UP方向
Limit_U1D2 = 1;
break;
case 2: // DW方向
Limit_U1D2 = 2;
SENSOR_SW_CNT = 0; // 回転カウンターをゼロにする。
break;
default:
break;
}
INTCON3.INT2IF = 0; //RB2/INT2割込みフラグクリアー
INTCON3.INT2IE = 1; //RB2/INT2割込みの許可
}
}
3.PC側のソフト |
VBを初めて使うため、Web上の諸先輩が公開されている記述を参考にして自分流に変更を加えてみました。
■ データの送信・受信の処理
文頭の 「VisualBasic2013逆引き大全555の極意」本よりはるかに参考になり、90%以上はWeb上からの引用で、極意本は必要とする関数(古い 言い方ですが)を調べるのに役立ちました。
何かの参考になればと、一部を掲載しておきます。
'--------------------------------------------------------------------------------------
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'■ [Start]ボタンを押して、データ送信を行う
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'
Private Sub SndButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SndButton.Click
'シリアルポートのオープン確認
If SerialPort1.IsOpen = False Then
Return
End If
OpenJob(sender, e)
RecvJob10()
'周波数・スイープ幅情報を読み取る
FMaxIdx = 0 ' FreqVal(65000) 配列の指標をゼロにする ***
RMaxIdx = 0 ' RetnVal(65000) 配列の指標をゼロにする ***
Dim FreqDiv As Integer
'CenterFreqBoxに数字以外の文字が有れば除外する
Dim str As String = ""
Dim c As Char
For Each c In CenterFreqBox.Text
If c >= "0" And c <= "9" Then
str = str & c
End If
Next
'指定周波数が1,700KHz〜60,000KHzの範囲外なら、14,000にする。
FreqCenter = Integer.Parse(str)
If FreqCenter < LowerLimitFreq Or FreqCenter > UpperLimitFreq Then '下限設定 = 1.7MHz
FreqCenter = 14000
End If
'テキストBOXに書き戻す ("#,0")は、カンマ付書式
CenterFreqBox.Text = FreqCenter.ToString("#,0")
'周波数の幅をコンボボックスから取り出す.
Dim fwidth As FreqWidthItem
fwidth = CmbFreqWidth.SelectedItem
FreqWidth = fwidth.FREQWIDTH
'ビューの分割ステップをコンボボックスから取り出す.
Dim dvstep As VewCivNumbItem
dvstep = CmbDivNumb.SelectedItem
XstepMax = dvstep.VEWDIVNUMB
'周波数の上限・下限を算出し、ステップを算出し表示する
FreqLow = FreqCenter - FreqWidth
FreqHigh = FreqCenter + FreqWidth
FreqStep = FreqWidth * 2 / XstepMax '単位は KHz◆■◆
FreqDiv = FreqWidth / 5 '表示用
LabelLowF.Text = FreqLow.ToString("#,0") & "KHz"
LabelHighF.Text = FreqHigh.ToString("#,0") & "KHz"
LabelCenterF.Text = FreqCenter.ToString("#,0") & "KHz"
LabelDiv.Text = "(" & FreqDiv.ToString() & "KHz/Div)"
Dim i As Integer, ix As Integer, iy As Integer, tmp As Integer
FreqNow = FreqLow
' While FreqNow <= FreqHigh
exi = 0 '送出データの連番
While FreqNow <= FreqHigh + (FreqStep * 1)
If exi = 100 Then exi = 0 '■ exi ■ が100を超えたら0にする
If FreqNow >= LowerLimitFreq And FreqNow <= UpperLimitFreq Then
i = FreqNow
tmp = i \ 1000
VfoNow(0) = IntToBcd(tmp)
i = i - (tmp * 1000)
tmp = i \ 10
VfoNow(1) = IntToBcd(tmp)
i = i - (tmp * 10)
tmp = i * 10
VfoNow(2) = IntToBcd(tmp)
VfoNow(3) = IntToBcd(exi)
'TxBuf = {&HFE, &HFE, &HE1, &HE2, &HAA, &H3, &H30, &H20, &H14, &H0, &HFD}
TxBuf = {&HFE, &HFE, ConAdr, My_Adr, ConCmd, &H3, VfoNow(2), VfoNow(1), VfoNow(0), VfoNow(3), &HFD}
'----------------------------------------------------------------
'Txバッファの中身をHexの文字に変換(1バイト=2文字)
TxComp = ""
For i = 0 To 10
TxComp = TxComp & ByteToHex(TxBuf(i))
Next i
TxCmdNo = 3
'----------------------------------------------------------------
Try
'----------------------------------------------------------------
'送出文字が受信バッファに入ったのを確認する
'TxCmdNoがゼロ(受信処理)にならなければ再送(3回)
i = 0
iy = 0
While i < 3
While iy < 3
'バイナリデータ送出
SerialPort1.Write(TxBuf, 0, 11)
'RecvJob()
For ix = 0 To 30
If TxCmdNo = 0 Then '戻り信号が合致した
Exit While
Else
RecvJob0()
End If
Next ix
RecvJob()
iy += 1
End While
'RecvJob()
For ix = 0 To 30
If exi = retex Then
Exit While
Else
RecvJob0()
End If
Next ix
'MsgBox("RET Time Over ")
RecvJob()
i += 1
End While
'----------------------------------------------------------------
Catch ex As Exception
MsgBox(TxCmdNo & "SndButton_Click:" & ex.Message)
End Try
'RecvJob()
Else
RetnVal(RMaxIdx) = 1000
RMaxIdx += 1
End If
FreqVal(FMaxIdx) = FreqNow
FMaxIdx += 1 '指標に1プラス
FreqNow += FreqStep
exi += 1
If (CheckBreak.Checked) Then '途中で停止する処理
Exit While
End If
End While
RecvJob10()
CloseJob(sender, e)
RecvJob()
'MsgBox("FMaxIdx=" & FMaxIdx & " RMaxIdx= " & RMaxIdx)
'MsgBox("FMaxIdx=" & FMaxIdx & " FreqNow= " & FreqNow)
ImgPlot() '描画
End Sub
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
' データ受信が発生したときのイベント処理
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim data As String = ""
Dim Freqdata As String = ""
Dim tmprx As Integer = 0
Dim PosFD As Integer = 0
Dim PosFE03 As Integer = 0
Dim PosFE7A03 As Integer = 0
Dim PosRdo As Integer = 0
Dim HitPtn As String = "FEFE"
Dim BgnCIV As String = "FEFE"
Dim BgnPos As Integer = 0
Dim BgnFlg As String = "FEFE"
Dim FreqPtn2 As String = 0
Dim RetInt As Integer = 0
Dim msgmsg As String = "" 'デバッグ用
'Dim HitByte As String
'Dim i As Integer
'シリアルポートのオープン確認
If SerialPort1.IsOpen = False Then
Return
End If
AdrSet()
'HitByte = "&HFE" & "&HFE" & My_Adr & ConAdr & ConCmd & "&H3"
HitPtn = HitPtn & ByteToHex(My_Adr) & ByteToHex(ConAdr) & ByteToHex(ConCmd) & "03"
BgnFlg = BgnFlg & ByteToHex(My_Adr) & ByteToHex(RdoAdr)
Try
'受信データを読み込む
'data = SerialPort1.ReadExisting()
tmprx = SerialPort1.Read(RxBuf, 0, 1000)
'MsgBox(tmprx)
'受信バッファの中身をHexの文字に変換(1バイト=2文字)
For i As Integer = 0 To tmprx - 1
CEdata = CEdata & ByteToHex(RxBuf(i))
'CEdata = CEdata & RxBuf(i)
'i += 1
Next i
'Private FreqVal(65000)
'Private RetnVal(65000)
'Private FMaxIdx As Integer
'Private RMaxIdx As Integer
'Private CEdata As String 'Constant extraction 定数抽出
'文字列 data ConstExtdata に指定した文字 "&HFD" が含まれるかを調べ、
' あれば位置を格納する=>PosFD
'
PosFD = 0
msgmsg = "f1 "
While 1
PosFD = CEdata.IndexOf("FD", 0)
If PosFD = -1 Then
Exit While
End If
If TxCmdNo = 0 Then
PosFE03 = CEdata.IndexOf(HitPtn, 0)
If PosFE03 > -1 And (PosFE03 + 18) = PosFD Then
retex = Val(CEdata.Substring(PosFE03 + 16, 2)) '送出順 10 20...90 10
RetInt = Val(CEdata.Substring(PosFE03 + 14, 2)) * 100
RetInt += Val(CEdata.Substring(PosFE03 + 12, 2))
RetnVal(RMaxIdx) = RetInt
RMaxIdx += 1
If (CheckVew.Checked) Then
data = data & CEdata.Substring(PosFE03 + 14, 2)
data = data & CEdata.Substring(PosFE03 + 12, 2)
data = data & CEdata.Substring(PosFE03 + 16, 2) & " "
End If
End If
msgmsg = "f2 "
'自動的にRigの周波数を取り込むチェックがされていたら
If (CheckAutoF.Checked) Then
'If (CheckAutoF.Checked) And OneTime = 1 Then
PosFE7A03 = CEdata.IndexOf(BgnFlg, 0) 'FEFE007A ?
'Rigからの周波数データを取り込む=>Freqdata
If PosFE7A03 > -1 And (PosFE7A03 + 20) = PosFD Then
FreqVFO = Val(CEdata.Substring(PosFE7A03 + 16, 2)) * 1000
FreqVFO = FreqVFO + Val(CEdata.Substring(PosFE7A03 + 14, 2)) * 10
FreqVFO = FreqVFO + Val(CEdata.Substring(PosFE7A03 + 12, 1))
Freqdata = FreqVFO.ToString()
TxCmdNo = 0
'Invokeを使って中心周波数の入力兼表示Boxに書き込む
Dim args(0) As Object
args(0) = Freqdata
Invoke(New Delegate_RcvDataToCenterFreqBox(AddressOf Me.RcvDataToCenterFreqBox), args)
OneTime = 0
End If
End If
End If
msgmsg = "f3 "
If TxCmdNo >= 1 And TxCmdNo < 9 Then
BgnPos = CEdata.IndexOf(BgnCIV, 0)
If BgnPos > -1 And BgnPos < PosFD Then
'If TxComp = CEdata.Substring(BgnPos, PosFD + 2) Then
If TxComp = CEdata.Substring(BgnPos, PosFD - BgnPos + 2) Then
'MsgBox(TxComp & "aaaaa" & CEdata.Substring(BgnPos, PosFD + 2))
TxCmdNo = 0
End If
End If
End If
msgmsg = "f4 "
'処理したFDまでを削除して詰める
CEdata = CEdata.Remove(0, PosFD + 2)
'MsgBox(CEdata)
End While
msgmsg = "f5 "
'
If (CheckVew.Checked) Then
'受信したデータをテキストボックスに書き込む()
Dim args(0) As Object
args(0) = data
Invoke(New Delegate_RcvDataToTextBox(AddressOf Me.RcvDataToTextBox), args)
End If
Catch ex As Exception
MsgBox(msgmsg & TxCmdNo & "SerialPort1_DataReceived:" & ex.Message)
End Try
End Sub
'--------------------------------------------------------------------------------------
*受信部は、1バイトをHexで表し英数2文字に拡張して処理を実施しています。
3.実行時のノートン Sonar による不具合 |
開発したソフトを実行しようとすると、Norton Internet Security の Sonar が、怪しいファイルとして認識し、実行ファイルが削除されます。
そこで、以下のように実行許可を設定する必要があります。
4.測定時のサンプル |
今までは、スポットで見たSWR特性を目安に運用していましたが、ビジュアルで確認すると安心感が増します。
サンプルは、良い特性を示していますがSDアンテナを振り出す角度によってはSWR特性が悪化するため、今後はその対策をテーマとしたい と考えています。■ 7MHzを中心に、1MHzに亘って測定したSWR特性(SWR値は、目安です)
■ 7MHzを中心に、250KHzに亘って測定したSWR特性(SWR値は、目安です)
■ アイコンも作ってみました。
99.追記用(予備) |