jl7gmnのblog

yahooブログから移行してきました。アマチュア無線を中心としたブログです。

VC++

vbausbio.dllをVisual C++2010Express その16

イメージ 1

イメージ 2

最近少しシリアルポートの列挙方法についていろいろと試していたが、どれが一番良いのかわからない。とりあえず2種類ほど試してはある。レジストリ情報からの列挙とserialPort->GetPortNames()の2つだ。今は固定のCOMポートでやっているが、汎用性を持たせるには現状のポート状態がいるからだ。とまずはうまくいったことから書いた。実はもう一つの方法を試しているが、うまくいっていないのがある。ManagementClassを使う方法だ。WMIを使うのだが、C++/CLIでは、なぜかうまく動かない。C#2010とVB2010では問題なく動く。ManagementClassの定義が呼び出せない状態だ。ということで、一旦保留とした。
今回は、今までより簡単な内容である。マウスホイールの周波数制御の部分を展開させてみた。先に書いたようにホイールの回転方向の値をラジオボタンで選択したステップに変えて周波数制御ステップを変えると言うことです。なぜこのようなことを行ったかというと実は理由があるのです。周波数を制御している無線機FT-1000MPのCATコントロールコマンド表上のコマンド群中の周波数制御コマンドでは10Hz単位のアップダウン、100KHzのアップダウン、1MHzのアップダウンしかないのです。ということでマウスホイールでの周波数ステップをうまく使い、ないところの1KHz、5KHz、10KHzのアップダウンを行ってみたわけです。特にSSBの復調には1KHzのアップダウンが意外と重宝します。(もう少し細かいほうが良いが。。。)内容的にはラジオボタンの使い方みたいなものです。あとは初期化ルーチンForm_Load(System::Object^ sender,System::EventArgs^ e){内にラジオボタンの1KHzが初期値として必ず設定される状態にしておくことも忘れないように一行追加しておきます。radioButton3->Checked=true;
コマンド表上の周波数制御は先のft-1000mpcomのファンクション化したサブルーチンを使いコマンドとパラメータを送るだけですみます。送った後は周波数を表示させるために周波数読み取りボタンをコールします。Button21_Click(sender,e);同様にファンクションを使ってFT-1000MPのVFO-AとVFO-Bの切り替えコマンドもつけました。ここいら変は単純に一方的な設定コマンド送出だけなので、ファンクションに設定して送るだけで簡単にできます。無線機のフィルター設定関係も同様にできることになります。
VisualC++2008Expressで行った読み取った周波数をハムログに送る部分も今回追加しました。コードは2008のものがそのまま問題なく使えます。そのほかに試してみたこととして周波数の読み取りコマンドをVFO-A とVFO-Bの2つを同時に読み取るコマンドを使い確認だけしてみました。先の表示周波数周波数読み取りはVFO-Aのみでしたが、次のコマンド
10,03,00,00,00,00 を送ると32バイトのデータでVFO-A、VFO-Bの周波数データの順番で戻ってきました。このコマンドでのパラメータ1が00では全データ読み出し、01ではメモリチャンネル番号読み出し、04では指定メモリチャンネル読み出し設定可能です。今までは02の表示データ読み出しで使用しています。03での2VFOデータの読み出しが可能なことが確認できました。プログラム上では32バイト読み取り最初の16バイトでのVFO-Aの周波数データのみを表示するようにしておきます。VFO-Bの周波数表示は今はできません。プログラムの周波数計算部をファンクション化して投げてやる必要があります。今回はデータの確認のみで対応は行いません。また今回周波数の変更の確認を行うことが多く短波ラジオの周波数帯で確認したりするので、ラジオを聴くためにAMのモードも追加しました。Hi。なんだかフォームが大きくなってきたので、一旦今までのフォームを終了して新たにFT-1000MPのコントロール用として作り直したい気がそろそろしてきた。そうなるとフィルタ選択とか送受信ボタンとかいろいろとレイアウトの検討がいる。もう少し考えてみるか? まず本日は終了。寝ます。

vbausbio.dllをVisual C++2010 その14のつづきです。

イメージ 1

vbausbio.dllをVisual C++2010 その14のつづきです。
-------------------------------------------------------------------------------
上記の3種類の周波数桁文字周波数をポインタからのデータとしてmojiwheel[]配列に入れましたのでマウスホイールイベント内で次の処理を行います。以下省略コード部
--------------------------------------------------------------------------------
//アスキーコードの文字化 例)コード53は アスキー文字 ’5’に変換
     Char charkhz0=(Char)int::Parse(mojiwheel[0].ToString());
Char charkhz1=(Char)int::Parse(mojiwheel[1].ToString());
Char charkhz2=(Char)int::Parse(mojiwheel[2].ToString());
Char charkhz3=(Char)int::Parse(mojiwheel[3].ToString());
Char charkhz4=(Char)int::Parse(mojiwheel[4].ToString());
     String^ allcharkhz;
allcharkhz=(charkhz0.ToString())+(charkhz1.ToString())+(charkhz2.ToString())+(charkhz3.ToString())+(charkhz4.ToString());
textBox17->Text=allcharkhz;
// アスキー文字の1khz代を整数数字化
int suuji;
suuji=(int::Parse(textBox17->Text));
int calsuuji;
calsuuji = suuji + cv; // 新しい周波数の数字 例5khzが 4khzまたは6khzになる
int lenFread;
lenFread = lenF;// 6 or 7 or 8 936,1503,21255

String^ mvFreq;
switch (lenFread)
{
case 8:
mvFreq="0A0"+calsuuji.ToString()+"00";
break;
case 7:
mvFreq="0A00"+calsuuji.ToString()+"00";
break;
case 6:
mvFreq="0A000"+calsuuji.ToString()+"00";
break;
}
textBox18->Text=mvFreq;
// +-の周波数を送信
String^ retda;
String^ cntcomdat;
cntcomdat=mvFreq;
retda="NONE";// コマンド送りのみの場合に"NONE"に設定する
String^ backdata;
backdata=ft1000mpcom(cntcomdat,retda);
// 周波数が変わったのを受信します。
button21_Click(sender,e);
}
------------------------------------------------------------------------------
周波数の1khz台までの数字データをドットなしの文字列にて取得してこれを数字化しホイールの±1を加算して新しい周波数を決めます。これを0Aの運用周波数設定コマンドで無線機へ関数化したft1000mpcomを使い送り周波数設定をします。周波数設定が無線機で行われたのを周波数取得コマンド(タイマーでコールするのと同じ)をコールしてフォーム上に変更された周波数を表示させます。上記でマウスホイールをまわすと無線機の周波数が回転方向により±1khzずつ変わります。変化させる周波数のデータをドットなしの文字で取得して加工するところがキーポイントです。c++ではポインタを使ってデータを入れ込み、配列(mojiwheel[])をグローバル的に使用するところでしょうか。ポインターの開放も忘れないようにします。やはり型変換が至る所で使われています。今回はVBのときと違い、桁処理なしで行う、もっともシンプルな新しい方法で周波数を変えるやり方になったと思います。最後のコマンドとして送るところは同じ方法ですが... とにかくマウスホイールでの周波数可変は完成ということにしました。つづく

vbausbio.dllをVisual C++2010 その14

イメージ 1

イメージ 2

FT-1000MPトランシーバーのマウスホイールの制御での周波数コントロールを検討してみた。以前のVisualBasicでもマウスホイールでの周波数コントロールを行ったが今回は同じ方法で制御できないことが判った。VisualBasicでの次のイベント制御での取得値が異なるのだ。
以下はVBコード
--------------------------------------------------------------------------------
Private Sub Form1_MouseWheel(ByVal sender As Object,ByVal e As System.Windows.Forms.MouseEventArgs)Handles Me.MouseWheel
wa = e.Delta.ToString()
End sub
--------------------------------------------------------------------------------
この中で次の様にマウスホイールのDelta値を取得していたが、VisualBasicの場合は取得値がマウスホイールを回転する割合で値が120の倍数で取得できていた。ホイールを奥方向に強く回すとwaが600とかの値が取れていた。逆方向ではwa=-600とかの値

wa=e.Delta.ToString()

VisualC++2010ExpressでのForm1イベントでのMouseWheelはVisualBasicの様にイベントが表示されていない。VBでのイベント選択画像添付
なのでVisualC++2010Expressでは以下のようにイベントを手動で書きます。
-------------------------------------------------------------------------------
private: System::Void Form1_MouseWheel(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e){
 int wv = (e->Delta)/120;
if(wv < 0 ) {
  cv = -1;
}else{
cv = 1;
}
.
.
以下処理コード省略(後で記載しています。)
.
.
}
-------------------------------------------------------------------------------
上記のwvの値がVBだと ±10ぐらいまでの値が取れているのだが、VisualC++2010Expressだといくらホイール回転を強く回してもいいところ±2であった。VisualBasicのようにホイールの回転クリック度にあわせたリニアなデータは取れない。VBでの動作がうそだったのか?MSDNヘルプではやはりマウスホイールの回転方向を取得が目的であり値は環境で変わるとの事である。つまり回転方向を取得するのが主なのである。だから値は符号がついた数字でプラスかマイナスかがわかればよいということなのだ。ということでVBの書き換えと言うわけにはいかなくなりました。いろいろと考えているうちに上記の方向の値が変わるのが(±1と±2)気に入らないので、最初に上記コード中のように正負を判定し値をプラス1とマイナス1の2つに限定するようにしました。周波数はマウスホイールの1クリックで回転方向により±1khzとなる事をもとに上記の限定を行っています。ですからこの値を10とかにすると1クリックあたり10khzにすることも可能ということです。
あとは先の周波数読み取りのところにて周波数を計算で求めた次のコードの後に無線機の周波数範囲に合わせた1khz台の場合の計算用の周波数データを文字化してSwitchで周波数桁に合わせて計算用周波数データを設定します。
------------------------------------------------------------------------------
//従来の周波数計算コードの部分
int Frequency=0;
Frequency=(GOUKEI * 0.625); //周波数を求めます。小数点等はなしの数値のみ
String^ mojiFreq; //周波数を文字化して入れる変数
mojiFreq=Frequency.ToString(); //文字化します。
int lenFrequency=0; //文字化の長さ用
lenFrequency=mojiFreq->Length; //長さを求めます。
-------以下追加コード---------------------------------------------------------
lenF = lenFrequency; //グローバルエリアでlenFはint宣言してあります。

// 周波数のkhz情報のみ取り出しておきます。後でのマウスwheelでの周波数制御用 khz代のup down
String^ mousewheel1khz;
switch(lenFrequency)
{
   case 8://14252 周波数14.252MHzの桁の場合
mousewheel1khz=mojiFreq->Substring(0,lenFrequency-3);
break;
   case 7://1503 周波数1.503MHzの桁の場合
mousewheel1khz=mojiFreq->Substring(0,lenFrequency-3);
break;
   case 6://646 周波数.646MHzの桁の場合
mousewheel1khz=mojiFreq->Substring(0,lenFrequency-3);
break;
}
char* p1=(char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(mousewheel1khz).ToPointer();
mojiwheel[0]=*p1;
mojiwheel[1]=*(p1+1);
mojiwheel[2]=*(p1+2);
mojiwheel[3]=*(p1+3);
mojiwheel[4]=*(p1+4);
System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr)p1);
//以下従来コード
--------------------------------------------------------------------------------
以上5000文字制限がかかったので続きは次に記載します。

vbausbio.dllをVisual C++2010 その13

イメージ 1

シリアル通信を使ったコマンド送出によるFT-1000MPのモード制御は問題なく一方的なデータの送出のみで行えるわけですが、Sメータ値を読み取る場合はコマンドを送った後にデータが返ってきます。これを行うコマンドはCATコントロールコマンド表のNo.27のS/POメータ・リクエストが該当します。
F7, ※, ※, ※, P4
ここでのパラメータP4は00がメイン(VFO-A)Sメータです。ちなみにSUB(VFO-B)Sメータは01、POメータが80、....と割り当てられています。
今回は00のメインVFO-AのSメータですので、コマンドは
F7,00,00,00,00
になります。このコマンドをft1000mpcomで送出します。
String^ cntcomdat;
String^ retda;
String^ backdata;
cntcomdat="F700000000";
retda="NONE";
backdata=ft1000mpcom(cntcomdat,retda);
このbackdataにシリアル通信でのSメータ値が返るように関数化したft-1000mpcom上で処理を行い値を返すようにします。
コマンドに対するFT-1000mpからのCATデータは4バイト+1バイトの値が返ってきます。最初の4バイトはSメータの値を4バイト分と、送ったSメータコマンドF7がそのまま返ってきます。
例)8C8C8C8CF7
ここでft-1000mpcom関数ではSメータリクエストのF7をチェックして、該当するコマンドの場合は上記データ5バイトを読み取りを行います。他にもデータを返すものとして、CATコントロールコマンド表のNo.29の内部ステータスの呼び出しFAがありますので、後々様にこれも検出できるように次のようにしておきます。
以下主要部コードです。
------------------------------------------------------------------------------
array<Byte>^ bin;
bin=gcnew array<Byte>(5);
array<String^>^ binasc=gcnew array<String^ >(5);
array<String^>^ ainasc=gcnew array<String^ >(5);
int rbuf;
int i;
int j;
int k;
int ad;
String^ retdat;

if ((kako[4] == 0xFA) | (kako[4] == 0xF7)){
int ac=0;
for(ac=0;ac<=4;ac++){
bin[ac]=_serialPort1->ReadByte(); //ここで返り値を読み取ります
}
//ここにはbin[ac]を加工するルーチンがあります。 
// 16進の文字列化、一桁のデータを2桁にする
//1バイトずつ読み取ったデータを連結する処理など 8C8C8C8CF7
 for (i=0; i<=4 ; i++){
binasc[i]=bin[i].ToString("X");
}
int lenasc;
for(j=0 ; j<=4 ; j++){
lenasc=binasc[j]->Length;
if(lenasc==1){
ainasc[j]="0"+binasc[j];
{else{
ainasc[j]=binasc[j];
}
}
txretda="";
retdat="";
for (k=0 ; k<=4 ; k++){
txretda=txretda+ainasc[k];
}
retdat=txretda;
_serialPort1->Close();
textBox15->Text=retdat;
 return retdat;
}else{
retdat=txretda;
textBox15->Text=retdat;
_serialPort1->Close();
return retdat;
}
_serialPort1->Close();
------------------------------------------------------------------------------
該当コマンド以外は通常の処理で"NONE"を返します。
以上でSメータコマンドがくると現在のSメータ値とコマンドの5バイトが返ってくるようになります。この5バイトをSメータの表示用に利用するわけです。いろいろな方法があるとは思いますが、まずこの返ってくる値5バイト中の最初の1バイト分の(HEX)を使いました。単純に00からFFまでの範囲をとる値です。これがわかるとプログレスバーに単純にMAX値を設定し後は読み取った値をValue設定するだけでSメータらしく動きます。以下プログレスバーのコードです。
------------------------------------------------------------------------------
int sdat;
int snagasa;
String^ picksdat;
snagasa=(backdata)->Length;
picksdat=backdata->Substring(0,2);
sdat=(Int32::Parse(picksdat,System::Globalization::NumberStyles::HexNumber));
progressBar1->Maximum=0xFF;
progressBar1->Value=sdat;
------------------------------------------------------------------------------
厳密にはSGで信号を入れて無線機でのSメータの正確なポイントデータを取得してSメータ表示させると精度が良くなります。今回はコード中のコメント整理ができてない為、主要部を手打ちコピペしました。先のタイマーコマンドの周波数読みボタンでタイマーを使うと周波数データ表示とSメータ表示がリアルタイムで表示できます。周波数の読み取りルーチンにSメータ読み取り処理を入れることがミソかと思います。だいぶ古い無線機ですのでCATシステムの情報がもう少しあってもいいのではないかと思いますが、プログラム内容を書いているものがほとんどないと思います。できたユーザとしてしか使えないアプリがアマチュア無線家としては寂しいですね。もちろんよくできたプログラムは勿論ありますが、できれば自分でプログラムできるほうが、楽しみも倍増すると思います。しかも無償の言語提供もされているわけですので、是非ともトライしてほしいと思います。とにかく自分で制御できることが最高です。つづく

vbausbio.dllをVisual C++2010 その12

イメージ 1

イメージ 2

VisualC++2010Expressでの周波数の読み取りができたので、これをVisualC++2008Expressでも同様に行ってみた。相変わらずノートパソコンはちんたら動いて多少のストレスが感じれれる状態だ。2008での作成は昨日というか今朝というか確認したものをその日の夜にアップしているんです。少し酔っ払っていますが、何とかまとめねば。これからカラオケに向かうのだが、その前に少しまとめをアップするつもりでアクセスしました。
単純に周波数の制御のコードは問題なくVisualC++2010Expressでのコードと同じもので動きます。ですのでコードは省略します。画像と無線機の周波数を取り込んだ値をハムログに送る部分を2008でのみ先行確認しましたのでこれを説明します。
読み取った周波数をどうするかというと、周波数の桁を出してその桁に合わせて抜き出す部分を決めるということを行います。ハムログに記入する仕様を決めるということです。
読み取った周波数は桁が10Hz 代まであります。このためハムログではうまくありません。
標準でもバンドの21とか14とか7とかでなければなりません。これでは実際の運用した周波数がわかりませんので、せめてKhzまでは出したいということでコーディングしています。たとえば21.234.56という読み取りですが、ハムログへは21.234にして送り自動入力させるということです。FT-1000MPのトランシーバーでは先のブログにもかきましたが、周波数範囲は100Khzから30Mhzです。この周波数範囲での周波数の表記は3種類となります。この分類にあわせて桁処理を行いそれをハムログへおくる段取りをします。この処理で使用するのは構造化プログラムに適したSwitchを使います。文字化した周波数の抜き出しはSubstring(,)を使い抜き出しします。問題となるのがString値になっている値をchar配列に変換して送らなければなりません。結論から言うとポインタを使います。周波数の情報は6個のchar 配列で宣言してあるので、最初のデータの位置にポインタを持ってきポインタのアップ+1で次のデータを配列に入れていく用にします。このためにStringデータを次のようにポインタに変換します。
char* p=(char*)System::Runtime::IterropServices::Marshal::StringToHGlobalAnsi(kakotxFtoHamlog).ToPointer();
後は先に説明したように最初の周波数をChar配列にポインタで入れていきます。
入れてあるデータの例として周波数が21.234Mhzがはいっていることになります。
hamdat5[0]=*p; // "2"
hamdat5[1]=*(p+1); // "1"
hamdat5[2]=*(p+2); // "."
hamdat5[3]=*(p+3); // "2"
hamdat5[4]=*(p+4); // "3"
hamdat5[5]=*(p+5); // "4"
ここで割り当てたポインタは必ず開放します
System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr)p);
あとは作成した関数に送るだけです。
hamlogTX_datvc2008(dcode,hamdat5);
以上で終わります。カラオケへゆかなければおそくなる~!!
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード
  • ライブドアブログ