CIP通信
概略
Ethernetで接続されているPLCの変数をCIP通信を使って読み書きします
フォームにはNJCompoletをnjCompolet1というインスタンス名で貼って置きます
以下サンプルコードはC#で書いてあります
フォームの作成(ボタンの配置など)は省略しているので適宜ボタンなどは配置してください
njCompolet1をアクティブにする
通信をするには通信相手のPLCのIPアドレスと、ActiveプロパティをTrueにします
サンプルではフォームロード時にセットします
private void Form1_Load(object sender, EventArgs e)
{
njCompolet1.PeerAddress = "192.168.250.1"; //PLCのIPアドレス
njCompolet1.Active = true;
}
3-4行目
njCompolet1.PeerAddress = "192.168.250.1"; //PLCのIPアドレス
njCompolet1.Active = true;
送信先のPLCのIPアドレスをPeerAddressに設定してActiveをTrueにします
ActiveをTrueにすることでPeerAddressのPLCとコネクションを開設します
変数の読出し
button1をクリックするとReadVariableメソッドを実行して変数の値を読み出します
private void button1_Click(object sender, EventArgs e)
{
try
{
// 数値型 実数型
Int32 vInt = (Int32)njCompolet1.ReadVariable("variableInt");
float vReal = (float)njCompolet1.ReadVariable("variableReal");
// 日付時刻
DateTime vDate = (DateTime)njCompolet1.ReadVariable("variableDate");
TimeSpan vTime = (TimeSpan)njCompolet1.ReadVariable("variableTime");
DateTime vDateTime = (DateTime)njCompolet1.ReadVariable("variableDateAndTime");
// 文字列
string vStr = (string)njCompolet1.ReadVariable("variableString");
// 配列
int[] vAryInt = (int[])njCompolet1.ReadVariable("variableAryInt");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
6行目
Int32 vInt = (Int32)njCompolet1.ReadVariable("variableInt");
ReadVariableメソッドを使ってPLCにあるvariableIntという変数を読み出してvIntという変数に格納します
ReadVariableメソッドの戻り値はObject型なのでInt型にキャストしています
PLCのvariableIntはグローバル変数でネットワーク公開を「公開のみ」、「入力」、「出力」のどれかに設定しておきます
7-18行目
float vReal = (float)njCompolet1.ReadVariable("variableReal");
// 日付時刻
DateTime vDate = (DateTime)njCompolet1.ReadVariable("variableDate");
TimeSpan vTime = (TimeSpan)njCompolet1.ReadVariable("variableTime");
DateTime vDateTime = (DateTime)njCompolet1.ReadVariable("variableDateAndTime");
// 文字列
string vStr = (string)njCompolet1.ReadVariable("variableString");
// 配列
int[] vAryInt = (int[])njCompolet1.ReadVariable("variableAryInt");
同様にReal型、Date型、Time型、DateTime型、String型を読み出します
配列も同様に配列にキャストして読み出すことができます
変数の書込み
button2をクリックするとWriteVariableメソッドを実行して変数に書込みます
private void button2_Click(object sender, EventArgs e)
{
try
{
// 数値型 実数型
njCompolet1.WriteVariable("variableInt", 1);
njCompolet1.WriteVariable("variableReal", 1.23);
// 日付時刻
njCompolet1.WriteVariable("variableDate", DateTime.Now);
njCompolet1.WriteVariable("variableTime", new TimeSpan(1, 0, 0));
njCompolet1.WriteVariable("variableDateAndTime", DateTime.Now);
// 文字列
njCompolet1.WriteVariable("variableString", "ABC");
// 配列
int[] intValue = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
njCompolet1.WriteVariable("variableAryInt", intValue);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
6行目
njCompolet1.WriteVariable("variableInt", 1);
WriteVariableメソッドを使ってPLCにあるvariableIntという変数に数値1を書込みします
7-19行目
njCompolet1.WriteVariable("variableReal", 1.23);
// 日付時刻
njCompolet1.WriteVariable("variableDate", DateTime.Now);
njCompolet1.WriteVariable("variableTime", new TimeSpan(1, 0, 0));
njCompolet1.WriteVariable("variableDateAndTime", DateTime.Now);
// 文字列
njCompolet1.WriteVariable("variableString", "ABC");
// 配列
int[] intValue = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
njCompolet1.WriteVariable("variableAryInt", intValue);
同様にReal型、Date型、Time型、DateTime型、String型を書き込みます
配列も同様に書き込むことができます
構造体の読み書き
読み出す構造体のメンバのデータ型(サイズ)が違う場合にはアライメントに注意してください
以下の構造体の場合
下図のようなアライメントになります
読み出したバイト配列を先頭から順番にBitConverterを使ってそれぞれのデータ型に変換します
String型の場合はnull文字を検索して文字数分をバイト配列からString型の変数に変換します
private void button3_Click(object sender, EventArgs e)
{
Encoding enc = Encoding.GetEncoding("utf-8");
byte[] byteArray = new byte[256];
int pos = 0;
try
{
byte[] bytesTestStruct = (byte[])njCompolet1.ReadVariable("TestStruct");
UInt16 variableBool = BitConverter.ToUInt16(bytesTestStruct, 0);
Int16 variableInt = BitConverter.ToInt16(bytesTestStruct, 2);
UInt16 variableUInt = BitConverter.ToUInt16(bytesTestStruct, 4);
Int32 variableDint = BitConverter.ToInt32(bytesTestStruct, 8);
Array.Copy(bytesTestStruct, 12, byteArray, 0, 256);
pos = Array.IndexOf(byteArray, (byte)0); //nullを検索して、バイト数にする
if (pos == -1) pos = 256; //nullが見つからなければ最大値
string variableStr = enc.GetString(byteArray, 0, pos);
Console.WriteLine(variableStr);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
3行目
Encoding enc = Encoding.GetEncoding("utf-8");
PLCの文字列コードはUTF-8なのでエンコードをUTF-8で用意しておきます
4行目
byte[] byteArray = new byte[256];
文字列を格納するバイト配列を用意しておきます
9行目
byte[] bytesTestStruct = (byte[])njCompolet1.ReadVariable("TestStruct");
ReadVariableで構造体を読み出してbytesTestStructのバイト配列に格納します
11-14行目
UInt16 variableBool = BitConverter.ToUInt16(bytesTestStruct, 0);
Int16 variableInt = BitConverter.ToInt16(bytesTestStruct, 2);
UInt16 variableUInt = BitConverter.ToUInt16(bytesTestStruct, 4);
Int32 variableDint = BitConverter.ToInt32(bytesTestStruct, 8);
BitConverterを使ってbyte配列の指定位置の値を数値に変換します
まず、先頭はBOOL型10個が2byteに入っているので一旦UInt16型で読み出します(BitConverterはBOOL型は対応していないため)
次の12行目はINT型、13行目はUINT型、14行目はDINT型をそれぞれ2,4,8byte目から読出します
16-19行目
Array.Copy(bytesTestStruct, 12, byteArray, 0, 256);
pos = Array.IndexOf(byteArray, (byte)0); //nullを検索して、バイト数にする
if (pos == -1) pos = 256; //nullが見つからなければ最大値
string variableStr = enc.GetString(byteArray, 0, pos);
16行目から19行目まではバイト配列の12byte目から入っている文字列を読み出します
16行目で12byte目から256byteをbyteArrayに取り出します
17行目で文字列の終端のNullを探すためにIndexOfを使って(byte)0を探します
18行目はNullが見つからないときは256byte全てが文字として扱います
19行目でバイト配列を文字列にエンコードしてvariableStringに格納します
読み出す時と同様にアライメントに注意して書き込みます
private void button4_Click(object sender, EventArgs e)
{
Encoding enc = Encoding.GetEncoding("utf-8");
byte[] bytedata = new byte[1000];
byte[] writedata = new byte[268]; //構造体のバイト数
UInt16 variableBool = 0x10;
Int16 variableInt = -10;
UInt16 variableUInt = 20;
Int32 variableDint = 100000;
try
{
Array.Copy(BitConverter.GetBytes(variableBool), 0, bytedata, 0, 2);
Array.Copy(BitConverter.GetBytes(variableInt), 0, bytedata, 2, 2);
Array.Copy(BitConverter.GetBytes(variableUInt), 0, bytedata, 4, 2);
Array.Copy(BitConverter.GetBytes(variableDint), 0, bytedata, 8, 4);
byte[] byteArray = enc.GetBytes("ABC");
Array.Copy(byteArray, 0, bytedata, 12, 3);
Array.Copy(bytedata, writedata, 16);
njCompolet1.WriteVariable("TestStruct", writedata);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
3行目
Encoding enc = Encoding.GetEncoding("utf-8");
PLCの文字列コードはUTF-8なのでエンコードをUTF-8で用意しておきます
4-5行目
byte[] bytedata = new byte[1000];
byte[] writedata = new byte[268]; //構造体のバイト数
4行目のbytedataは作業用のバイト配列で1000byte用意しました
5行目のwritedataは構造体に書き込むためのバイト配列で構造体のバイト数の268byteを用意します
7-10行目
UInt16 variableBool = 0x10;
Int16 variableInt = -10;
UInt16 variableUInt = 20;
Int32 variableDint = 100000;
各変数に書き込むデータを用意します
14-19行目
Array.Copy(BitConverter.GetBytes(variableBool), 0, bytedata, 0, 2);
Array.Copy(BitConverter.GetBytes(variableInt), 0, bytedata, 2, 2);
Array.Copy(BitConverter.GetBytes(variableUInt), 0, bytedata, 4, 2);
Array.Copy(BitConverter.GetBytes(variableDint), 0, bytedata, 8, 4);
byte[] byteArray = enc.GetBytes("ABC");
Array.Copy(byteArray, 0, bytedata, 12, 3);
BitConverter.GetBytesを使って数値をバイト配列に変換してbytedataへ格納していきます
18行目は文字列のためGetBytesで文字列をバイト配列にエンコードしてから19行目でbytedataにコピーして格納します
21-22行目
Array.Copy(bytedata, writedata, 16);
njCompolet1.WriteVariable("TestStruct", writedata);
21行目で作業用のbytedataから書込み用のwritedataにコピーします
22行目でWriteVariableを使ってPLCのTestStruct構造体にwritedataの値を書き込みます
Windowsの時刻は0001/01/01 00:00:00.000を起点に100nsでカウントしています
構造体のメンバに日付時刻がある場合はバイト配列で上記の経過時間(カウント)が入っているため読み出した値を1970-01-01からの経過時間でWindowの日付時刻に変換してください
double msec =(double)(BitConverter.ToUInt64(bytesTestStruct, 0)) / 1000000.0;
DateTime variableDateTime = new DateTime(1970, 1, 1).AddMilliseconds(msec);
時刻書込み
button5をクリックするとPCの時刻をPLCに書き込みます
private void button5_Click(object sender, EventArgs e)
{
try
{
njCompolet1.Clock = DateTime.Now;
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
5行目
njCompolet1.Clock = DateTime.Now;
PCの時刻をそのままClockプロパティに書き込むことでPLCの時刻を変更できます
その他よく使いそうなメンバ
名前 | 説明 | |
---|---|---|
プロパティ | ReceiveTimeLimit | Compoletの受信待ちがタイムアウトするまでの時間を取得または設定します |
IsConnected | ノードに接続しているかどうかを取得します | |
TypeName | PLCの形式情報を取得します | |
RunStatus | PLCの運転状態を表します | |
メソッド | ReadVariableMultiple | PLCの複数のタグの値を読み出します |
GetEventLogs | PLCのイベントログを取得します |
全てのメンバはヘルプファイルを参照してください
ヘルプファイルは [スタート] - [OMRON] - [CX-Compolet]にあります