02-01-2016 07:03 AM
UDP通信に関する質問です.
現在,LabVIEWのUDP通信を使い,他のパソコンとの相互通信を考えています.
Labo viewの送信にはDAQmxから得たAIやDIOなどの値の情報を,
受信にはDAQmxへAO,DIOなどの値を書き込むと言った具合です.
相互通信するPCではC/C++言語を用いて,
typedef struct {
float finput[4];
bool binput[32];
}NIINPUT;
typedef struct {
float foutput[8];
bool boutput[32];
}NIOUTPUT;
などのような構造体を文字列に変換して,送受信を考えています.
そこで,LabVIEWにおいて,
http://zone.ni.com/reference/ja-XX/help/371361M-0112/lvhowto/using_the_flatten_to_string_function/
を参考に送受信の数値を文字列に変換しようと思っています.
しかしながら,上記のDocumentにある
「平坦化されたLabVIEWデータをバイナリ文字列形式から英数字文字列形式に変換」
の仕方が今ひとつわかりません.
上記の変換の仕方について方法またはSampleなどありましたら,
お教えいただけたら嬉しいです.
また,上記の変換以外の方法でもC/C++と構造体の文字列のような(上記イタリック体部分)
ものと通信が可能な方法がありましたらご教授いただけたら幸いです.
宜しくお願い致します.
解決済! 解決策の投稿を見る。
02-01-2016 11:46 PM
クラスタデータを一度文字列に変換され、C++側で構造体に変換されることが目的でしょうか?
このサンプルがお役にたてればよいのですがいかがでしょう。
Community: クラスタを数値に変換 - National Instruments
上記サンプルは文字列に変換後、さらに数値データに変換していますが、
下記のように数値変換の部分を削除すれば、クラスタを文字列に変換して受け渡すことが可能です。
02-03-2016 03:17 AM
Ytochigiさん
返信ありがとうございます.
添付のデータをクラスタデータにし,文字列に変換するところ
についてはとても参考になりました.
クラスタデータを文字列に変換までのプロセスは上記のやり方で行いたいと思います.
しかし,上記のやり方ですと,文字列に平滑化した後の文字列を用いてUDP通信を行うと,
C/C++側で文字列をうまくデコードできませんでした.
原因としては,LabVIEWで「文字列に平滑化」すると文字列が "LabVIEW文字列"
になるため,C/C++側ではうまくデコードできなかったのではと考えています.
参考1:http://zone.ni.com/reference/ja-XX/help/371361M-0112/lvhowto/using_the_flatten_to_string_function/
そこで,
LabVIEWで16進数からASCIIへ(または、ASCIIから16進数へ)変換するにはどうすれば良いですか?
を参考に
クラスタデータを文字列に変換までのプロセスの後に,
一度10進数にキャストし,その後10進数を16進数変数文字列にしてから
UDP通信を行うようにしました.
ですが,現状変わらずで,C/C++側ではうまくデコードできず,
デタラメな値となってしまっています.
図1 型変換のイメージ
ここで新たな疑問なのですが,
参考1の「平坦化されたLabVIEWデータをバイナリ文字列形式から英数字文字列形式に変換」
とは図1の手順で正しいのでしょうか?
また,LabVIEWで用いられている数字や文字は英数字文字列形式に変換した場合,
C/C++と同様の型なのでしょうか?
例えば,図1のピンク色の文字列 = C/C++でのchar型,
図1の緑色のbool型 = C/C++でのbool型
この辺りで何か知見のある方がいらっしゃいましたら,
お教えいただけたらと思います.
宜しくお願い致します.
02-03-2016 06:52 AM
図1の手順ではなく、以下のようになると思います。
図1のだと、長い文字列を得ても、数値1個にしかcastできないので、ほとんどの情報が失われます。
(参照なさったやりかたは、「1文字」だけ変換する方法です)
平坦化文字列を、U8の配列に変換し、それを、配列丸ごと(=要素1個1個順に)16進数文字列に変換します。
このとき、16進数文字列の幅を「2」にしておくことを忘れないようにします。
最後に、出てきた文字列配列を全部くっつければ、英数字文字列形式になります。
このままC/C++に渡してもいいかと思いますが(たしか、最後にnull文字はくっついた状態になるので)、
気になる場合はさらに末尾にnull文字を付けても良いかと思います。
参考まで、これを、元に戻すところもつけたviを添付します。
(C/C++で処理するだけで、戻すのは要らないのかも知れませんが・・・・)
02-04-2016 08:49 PM
ちと失礼します。
>C/C++側で文字列をうまくデコードできませんでした.
・データ型が合っていない
・構造体内の変数の位置が合っていない
・LabVIEW側で配列を使って受渡している
・バイト順の違いによる影響(ちなみにLabVIEWは、big-endian)
が考えられる原因かと思います。
(C/C++とLabVIEWでデータの受け渡しが合っていない)
*LabVIEW側がどのようにデータが格納される(ている)かは下記URL参照
C/C++側が
・float(32bit単精度浮動小数点数)
・bool(8bit:0=False/1:True?)
・little-endian
だとして
配列要素がそれほど多くなければ、UDP受信後の処理はサンプルになるかと思います。
・平坦化・非平坦化でC/C++側のバイト順を指定
・LabVIEW側で送受信するクラスタは配列を使用しない(配列使う場合は、C/C++側でLabVIEW側に合わせた構造体で *要注意)
後、送受信データ(C/C++/LabVIEW両方)を16進数でDumpしてデータを確認することをお勧めします。
*LabVIEW側は、文字列の表示スタイルを変更
LabVIEWのデータストラクチャ
http://www.ni.com/getting-started/labview-basics/ja/data-structures#boolean
LabVIEW数値データタイプ表
http://zone.ni.com/reference/ja-XX/help/371361J-0112/lvhowto/numeric_data_types_table/
05-06-2016 07:33 PM
返信が遅くなりました.
検討に少し時間がかかりました
M.Shiraishiさん
16進数への変換サンプルありがとうございました.
su-sann5073
アドバイスとサンプルをありがとうございました.
自己解決いたしました!
ここで頂いたサンプルやアドバイスを参考にして
下記で通信できることを確認しました.
LabVIEW送信の図
C/C++で受信するための構造体
typedef struct {
double dValue[16];
bool bValue[32];
char mojihead[4];
char moji[8];
}RECV;
LabVIEW受信の図
C/C++で送信するための構造体
typedef struct {
double dValue[4];
bool bValue[32];
}SEND;
C/C++との通信で気をつける点は
・文字列にフォーマットする際のバイト順の指定(little-endianにする)
・配列からクラスタに変換する場合は,必ずクラスタサイズを変更する.(デフォルトサイズは9)
・LabVIEW配列の型をC/C++側と同じ型にする.
http://zone.ni.com/reference/ja-XX/help/371361L-0112/lvhowto/numeric_data_types_table/
上記リンクを参考に,C/C++側がdoubleであればLabVIEW側でも倍精度浮動小数点数(DBL)型にする.
・LabviewからC/C++側で文字列を受信する場合は,LabVIEW文字列に合わせた形で受信する.
http://www.ni.com/white-paper/4877/ja/
上記リンクの図3を参考に,C/C++側では最初に4byte分の文字列配列を作り読み飛ばす.
送信は確認していませんが,逆に4byte分の文字列サイズを加えて送信すればOKだと思います.