From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
05-28-2017 04:35 AM
はじめまして、USB-8502/1を購入しました
VisualC#からUSB-8502/1(nixnet.dll)を介してCAN通信を行いたいと思っています
資料が少なく非常に難航しています
NI-CANでは、
辺りが参考になりますがNI-XNETは新しい技術ということもあってか情報が殆ど
ありません
当方、CANの知識も経験もないため易しめのサンプルがあると助かるのですが、
お薦めの文献などありましたら紹介いただきたいと思います
先ずは固定フレームの定期送信から始めたいと考えています
また、nixnet.hにも情報があるようですが残念ながら当該ファイルの入手方法も
わかっていません
よろしくお願いします
05-28-2017 07:46 PM
newon1さん、
最新版NI-XNETもNI-CANもC#などの.NET環境を正式にサポートしていないようです。
http://download.ni.com/support/softlib//embedded%20networks/NI-XNET/Driver/17.0.1/readme_jpn.htm
ご紹介なさっているフォーラムページではNI-CANのC APIをC#から呼び出すために独自に作成したラッパーライブラリを使っているようです。XNETでもそういったことができるのかもしれませんが、Cであればサンプルもありますし、可能であればCで作成するほうがよいのではないかと思います。
NI-XNETドライバをインストールするときにC言語サンプルをインストールするように選択すれば、
C:\Users\Public\Documents\National Instruments\NI-XNET\Examples\MS Visual C\CAN
にCANのC言語サンプルがインストールされるようです。
nixnet.hは
C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include
nixnet.libは
C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\lib32\msvc
にあります。
05-29-2017 08:27 AM
情報ありがとうございます
色々調べてみたところ、「LabWindows/CVIサポート」を選択すると次の場所でも
見つけられました
C:\Program Files\National Instruments\Shared\CVI\include\nixnet.h
Cサンプルも見てはいますが、そのまま実行できるのかよくわかりません
当面、C#で継続して行きます(Cが不得手というのも理由です)
05-29-2017 08:57 PM
CサンプルはVisual BasicなどのIDEで読み込んでEXEを作る必要がありますね。そのときには.hファイルと.libファイルを参照項目に入れてからビルドをします。C#で継続なされるというのは、なにか良い方法を見つけられたのでしょうか?
06-04-2017 05:19 AM
引き続き情報収集を進めております
全体を統括するプログラムがC#(WPF)なのでNI-XNETもC#内で処理したいという狙いです
現在参考にしているのが、
http://forums.ni.com/t5/Automotive-and-Embedded-Networks/Net-wrapper-for-XNET-API/td-p/3249494
http://forums.ni.com/t5/Automotive-and-Embedded-Networks/Using-X-NET-C-API/td-p/2391466
辺りです
手始めにnixnet.dllと会話するとこから研究しています
DLL内の関数を処理した際に出力されるステータスを文章に変換してくれる
nxStatusToStringの取り込みをしてみました
NI-CANのncStatusToStringと全く同じ呼び出しですが、CallingConventionを
省略すると正しくないみたいです(スタックが不安定~とか不気味な警告が出ます)
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void nxStatusToString(
int Status, //nxStatus_t
uint SizeofString, //u32
StringBuilder StatusDescription //char*
);
使い方は、
int status = 0;
StringBuilder status_str = new StringBuilder(1024);
nxStatusToString(status, (uint)(status_str.Capacity), status_str);
みたいな感じで、status_strの中に解説が書き込まれます
当面の目標が固定フレームの定期送信なのでセッション生成が必要だと思います
次のような感じで一応動くっぽいです
呼び出し関数は参考サイトを見て
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxCreateSession(
string DatabaseName, //const char*
string ClusterName, //const char*
string List, //const char*
string Interface, //const char*
uint Mode, //u32
out IntPtr SessionRef //nxSessionRef_t*
);
という感じにしました
int status = 0;
string DBName = "nixnet_example";
string CluName = "CAN_Cluster";
string SignalArray = "TestSignal1,TestSignal2";
string IFName = "CAN0";
status = nxCreateSession(DBName, CluName, SignalArray, IFName, 11, out SessionRef);
という感じで構文エラーは出ていないみたいです
まだ実機で試していないので正しくないかもしれません
なお、Modeの11はnxMode_FrameOutSinglePointのことです
また、DatabaseName、ClusterName、Listに代入する内容がまだわかっていないので
上記では適当な文字を入れています
上記内容への指摘や情報を提供頂けますと幸いです
06-11-2017 08:48 AM
次の様なサイトを見つけましたが、残念ながらそのまま使えない感じでした
http://www.seqzap.com/SeqZapManuals/SeqZapTools/ni-xnet.html
https://github.com/seqzap/ni-xnet-dot-net
前回の続きですが、DatabaseName、ClusterName、Listに適当な名前は使えませんでした
エラーメッセージは、
「フレームはデータベースで見つかりませんでし た。解決策: データベースで
定義されたセッションのフレームのみを初期化して いることを確認してください。」
との内容です
NI-XNETではデータベースがないと何もできないっぽいです
先ずはメモリデータベースを研究してみました
参考にしたサイトは次です
呼び出し関数は次の3つで行けそうです
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxdbOpenDatabase(
string DatabaseName, //const char*
out uint DatabaseRef //nxDatabaseRef_t*(=u32*)
);
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxdbCreateObject(
uint DatabaseRef, //nxDatabaseRef_t(=u32)
uint ObjectClass, //u32
string ObjectName, //const char*
out uint DbObjectRef //nxDatabaseRef_t*(=u32*)
);
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxdbSetProperty(
uint DbObjectRef, //nxDatabaseRef_t(=u32)
uint PropertyID, //u32
uint PropertySize, //u32
[MarshalAs(UnmanagedType.AsAny)] object PropertyValue //void*
);
メモリデータベースでは名前として「:memory:」を使うみたいです
データベースの下にクラスタ、その下にフレーム、その下に信号(シグナル)を作ることになる感じです
以下の要領で作成ができるみたいです
今回はフレームまでで止めています
static uint DatabaseRef;
static uint ClusterRef;
static uint FrameRef;
string DBName = ":memory:";
string CluObject = "CAN_Cluster";
string FrObject = "CAN_Frame";
int status = 0;
//データベースオープン
status = nxdbOpenDatabase(DBName, out DatabaseRef);
//クラスタ作成(0x00010000)
status = nxdbCreateObject(DatabaseRef, 0x00010000, CluObject, out ClusterRef);
//フレーム作成(0x00020000)
status = nxdbCreateObject(ClusterRef, 0x00020000, FrObject, out FrameRef);
//クラスタ通信速度設定(0x00010001)
uint BaudRate = 500000;
status = nxdbSetProperty(ClusterRef, 0x00010001, 4, BaudRate);
//フレーム拡張ID設定(0x02020010)
byte ExtID = 1;
status = nxdbSetProperty(FrameRef, 0x02020010, 1, ExtID);
//フレームID設定(0x00020003)
uint FrameID = 357827584;
status = nxdbSetProperty(FrameRef, 0x00020003, 4, FrameID);
//フレームペイロード長設定(0x00020007)
uint PayloadLength = 2;
status = nxdbSetProperty(FrameRef, 0x00020007, 4, PayloadLength);
//フレームタイミングタイプ設定(0x00020011)
uint TimingType = 0;
status = nxdbSetProperty(FrameRef, 0x00020011, 4, TimingType);
//フレーム送信時間間隔設定(0x01020012)
double TransmitTime = 0.1;
status = nxdbSetProperty(FrameRef, 0x01020012, 8, TransmitTime);
//フレームデフォルトペイロード設定(0x0A020005)
nxCAN_Payload DefaultPayload = new nxCAN_Payload();
DefaultPayload.Payload0 = 115;
DefaultPayload.Payload1 = 14;
status = nxdbSetProperty(FrameRef, 0x0A020005, 2, DefaultPayload);
PropertyIDのOR計算に気付かず、だいぶ迷走しました
問題はこのデータベースをどうやって送信に結びつけるかという点です
FrameOutSinglePoint、FrameOutQueued、FrameOutStreamの使い分けと使い方が
まだわかっていません
上記内容への指摘や情報を提供頂けますと幸いです
※nxCAN_Payloadは1Du8で、以下定義としました
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct nxCAN_Payload // size of structure is 8 bytes
{
[FieldOffset(0)]
public byte Payload0; //u8
[FieldOffset(1)]
public byte Payload1; //u8
[FieldOffset(2)]
public byte Payload2; //u8
[FieldOffset(3)]
public byte Payload3; //u8
[FieldOffset(4)]
public byte Payload4; //u8
[FieldOffset(5)]
public byte Payload5; //u8
[FieldOffset(6)]
public byte Payload6; //u8
[FieldOffset(7)]
public byte Payload7; //u8
}
06-18-2017 09:01 AM
メモリデータベースが一応できたので、送信を試みました
先ずはFrameOutSinglePointを使ってみました
呼び出し関数は次の2つで行けそうです
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxCreateSession(
string DatabaseName, //const char*
string ClusterName, //const char*
string List, //const char*
string Interface, //const char*
uint Mode, //u32
out uint SessionRef //nxSessionRef_t*(=u32*)
);
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxWriteFrame(
uint SessionRef, //nxSessionRef_t(=u32)
[MarshalAs(UnmanagedType.AsAny)]object Buffer, //void*
uint NumberOfBytesForFrames, //u32 (byte)
double Timeout //f64 (second)
);
この関数にメモリデータベースを代入しました
int status = 0;
string DBName = ":memory:";
string CluName = "CAN_Cluster";
string Array = "CAN_Frame";
string IFName = "CAN1";
//セッション作成
status = nxCreateSession(DBName, CluName, SignalArray, IFName, 11, out SessionRef);
//送信フレーム(Payload長2、拡張ID=357827584)作成
nxFrameCAN TestFrame = new nxFrameCAN();
TestFrame.Identifier = 357827584 + 0x20000000;
TestFrame.PayloadLength = 2;
TestFrame.Payload0 = 0xFF;
TestFrame.Payload1 = 0x0F;
//フレーム送信
status = nxWriteFrame(SessionRef, TestFrame, 24, 0.0);
セッション作成時にModeを11(FrameOutSinglePoint)としています
このModeではnxWriteFrameのTimeoutを0.0にするみたいです
これを実行してみると信号が出てきますが、データベースでTransmitTime = 0.1と
しているのにもかかわらず2ms周期で出力されてる感じです
現在CANバスに終端抵抗しか接続されていないのですが、これがまずいのでしょうか
CANの知識が乏しくここで止まっている状態です
ヒントとなる助言や文献を頂けると幸いです
※nxFrameCANは以下定義としました
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct nxFrameCAN // size of structure is 24 bytes(8,4,1,1,1,1,8)
{
[FieldOffset(0)]
public ulong Timestamp; //nxTimestamp_t(=u64)
[FieldOffset(8)]
public uint Identifier; //u32
[FieldOffset(12)]
public byte Type; //u8
[FieldOffset(13)]
public byte Flags; //u8
[FieldOffset(14)]
public byte Info; //u8
[FieldOffset(15)]
public byte PayloadLength; //u8
[FieldOffset(16)]
public byte Payload0; //u8
[FieldOffset(17)]
public byte Payload1; //u8
[FieldOffset(18)]
public byte Payload2; //u8
[FieldOffset(19)]
public byte Payload3; //u8
[FieldOffset(20)]
public byte Payload4; //u8
[FieldOffset(21)]
public byte Payload5; //u8
[FieldOffset(22)]
public byte Payload6; //u8
[FieldOffset(23)]
public byte Payload7; //u8
}
06-18-2017 11:37 AM
済みません、間違いがありました
プログラム冒頭に宣言が不足していました
static uint SessionRef;
セッションを作成する関数の引数に誤植がありました
status = nxCreateSession(DBName, CluName, Array, IFName, 11, out SessionRef);
あと、Transmit Timeについてですが、気になるプロパティを見つけたので後で試して
みたいと思います
Session:Interface:CAN:Single Shot Transmit? (0x02100024)
07-02-2017 08:04 AM
Session:Interface:CAN:Single Shot Transmit?(0x02100024)確認しました
説明書にもあるとおり、このプロパティがFalseだと送信失敗時に再送信を試みるという
ことでした(ISO 11898-1, 6.11 Automatic Retransmission)
Trueに設定することで予定通りのフレーム送信ができました
やっぱりCANを使うとCANデータベースが便利そうです
メモリデータベースをこつこつ構築するのもなかなか骨が折れます
次はCAN DBファイルの利用を研究しました
手元のCAN DBファイルはNI-XNETの*.ncdではなく、あっちの*.dbcですが、何の
支障もなく使用できました
呼び出し関数は次です
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxdbAddAlias(
string DatabaseAlias, //const char*
string DatabaseFilepath, //const char*
uint DefaultBaudRate //u32
);
使い方こんな感じで良さそうです
※Frame1、Frame2、Frame3はCAN DBファイルに記述されたフレーム名
※CAN DBファイル(CAN_SYSTEM.dbc)は実行ファイルと同じディレクトリにあるとします
static uint SessionRef;
int status = 0;
string IFName = "CAN1";
string DBAlias = "CAN_DB";
string DBPath = "CAN_SYSTEM.dbc";
uint BaudRate = 500000;
//エイリアス作成
status = nxdbAddAlias(DBAlias, DBPath, BaudRate);
//セッション作成(Frame Output Single-Point Mode)
status = nxCreateSession(DBAlias, "Cluster", "Frame1,Frame2,Frame3", IFName, 11, out SessionRef);
//送信フレーム作成 ※拡張ID
nxFrames TXFrame = new nxFrames();
TXFrame.F1_Identifier = 357826816 | 0x20000000;
TXFrame.F1_PayloadLength = 2;
TXFrame.F1_Payload0 = 0x01;
TXFrame.F1_Payload1 = 0xFF;
TXFrame.F2_Identifier = 357826848 | 0x20000000;
TXFrame.F2_PayloadLength = 3;
TXFrame.F2_Payload0 = 0x0A;
TXFrame.F2_Payload1 = 0x10;
TXFrame.F2_Payload2 = 0x00;
TXFrame.F3_Identifier = 357826880 | 0x20000000;
TXFrame.F3_PayloadLength = 1;
TXFrame.F3_Payload0 = 0xF0;
//フレーム送信
status = nxWriteFrame(SessionRef, TXFrame, 72, 0.0);
これでCAN DBファイルに記述されたフレームがバスに出てきました
3つのフレームが立て続けに出てくる訳ですが、各フレームのTransmit Timeが違う
場合やTiming Typeが異なる場合にどうなるのかはよくわかりません
セッションは同じ振る舞いのフレームやシグナルをまとめるものの様な気がしますが
詳細は不明です
上記内容への指摘や情報を提供頂けますと幸いです
※nxFramesの定義は以下としています
[StructLayout(LayoutKind.Explicit, Size = 72)]
public struct nxFrames
{
[FieldOffset(0)]
public ulong F1_Timestamp; //nxTimestamp_t(=u64)
[FieldOffset(8)]
public uint F1_Identifier; //u32
[FieldOffset(12)]
public byte F1_Type; //u8
[FieldOffset(13)]
public byte F1_Flags; //u8
[FieldOffset(14)]
public byte F1_Info; //u8
[FieldOffset(15)]
public byte F1_PayloadLength; //u8
[FieldOffset(16)]
public byte F1_Payload0; //u8
[FieldOffset(17)]
public byte F1_Payload1; //u8
[FieldOffset(18)]
public byte F1_Payload2; //u8
[FieldOffset(19)]
public byte F1_Payload3; //u8
[FieldOffset(20)]
public byte F1_Payload4; //u8
[FieldOffset(21)]
public byte F1_Payload5; //u8
[FieldOffset(22)]
public byte F1_Payload6; //u8
[FieldOffset(23)]
public byte F1_Payload7; //u8
[FieldOffset(24)]
public ulong F2_Timestamp; //nxTimestamp_t(=u64)
[FieldOffset(32)]
public uint F2_Identifier; //u32
[FieldOffset(36)]
public byte F2_Type; //u8
[FieldOffset(37)]
public byte F2_Flags; //u8
[FieldOffset(38)]
public byte F2_Info; //u8
[FieldOffset(39)]
public byte F2_PayloadLength; //u8
[FieldOffset(40)]
public byte F2_Payload0; //u8
[FieldOffset(41)]
public byte F2_Payload1; //u8
[FieldOffset(42)]
public byte F2_Payload2; //u8
[FieldOffset(43)]
public byte F2_Payload3; //u8
[FieldOffset(44)]
public byte F2_Payload4; //u8
[FieldOffset(45)]
public byte F2_Payload5; //u8
[FieldOffset(46)]
public byte F2_Payload6; //u8
[FieldOffset(47)]
public byte F2_Payload7; //u8
[FieldOffset(48)]
public ulong F3_Timestamp; //nxTimestamp_t(=u64)
[FieldOffset(56)]
public uint F3_Identifier; //u32
[FieldOffset(60)]
public byte F3_Type; //u8
[FieldOffset(61)]
public byte F3_Flags; //u8
[FieldOffset(62)]
public byte F3_Info; //u8
[FieldOffset(63)]
public byte F3_PayloadLength; //u8
[FieldOffset(64)]
public byte F3_Payload0; //u8
[FieldOffset(65)]
public byte F3_Payload1; //u8
[FieldOffset(66)]
public byte F3_Payload2; //u8
[FieldOffset(67)]
public byte F3_Payload3; //u8
[FieldOffset(68)]
public byte F3_Payload4; //u8
[FieldOffset(69)]
public byte F3_Payload5; //u8
[FieldOffset(70)]
public byte F3_Payload6; //u8
[FieldOffset(71)]
public byte F3_Payload7; //u8
}
07-22-2017 11:55 PM
CANフレーム送信について研究してきましたが、ここでCANフレーム受信を試みたいと思います
CANバスに流れたデータフレームの読み取りをします
呼び出し関数は次を使いました
[DllImport("Nixnet.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nxReadFrame(
uint SessionRef, //nxSessionRef_t
out nxFrameCAN Buffer, //void*
uint SizeOfBuffer, //u32
double Timeout, //f64
out uint NumberOfBytesReturned //u32*
);
以下の使い方でフレームの取得ができました
※RXFrameはCAN DBファイルに記述されたフレーム名
※CAN DBファイル(CAN_SYSTEM.dbc)は実行ファイルと同じディレクトリにあるとします
※nxFrameCANは1フレーム分の構造体
static uint SessionRef;
int status = 0;
uint Datasize = 0;
string IFName = "CAN1";
string DBAlias = "CAN_DB";
string DBPath = "CAN_SYSTEM.dbc";
uint BaudRate = 500000;
nxFrameCAN RXData = new nxFrameCAN();
//エイリアス作成
status = nxdbAddAlias(DBAlias, DBPath, BaudRate);
//セッション作成(Frame Input Single-Point Mode)
status = nxCreateSession(DBAlias, "Cluster", "RXFrame", IFName, 8, out SessionRef);
//フレーム受信
status = nxReadFrame(SessionRef, out RXData, 24, 0.0, out Datasize);
これでフレームがRXDataに入ります
あとはnxFrameCANの定義に基づいてペイロードや時間を取り出すことになります
Frame Input Single-Point Modeでは最新のフレーム情報を取得するためにTime Outは0にするみたいです
なお、上記だと1フレームの取得にしか使えません
複数フレームを取得する場合にはデータを受け取るvoid* Bufferに工夫が必要です
前回使った3フレーム用のnxFramesとかバイト配列などを活用することになる気がします
関数からはデータのバイト数が返ってくるので可変長データとかにも対応できると思われます
上記の実行結果では24バイト(=1フレーム)が返ってきました
上記内容への指摘や情報を提供頂けますと幸いです