はじめに
ソケット通信を行うときは、データをByte配列によるバッファに変換してサーバに送信します。そして、受信したデータもByte配列を文字列や実数等に変換して、クライアント側で処理します。
「データをByte配列にする」ということはいったい何?という疑問もささやかれると思いますが、簡単に言えば、データを16進数にまとめているといえばわかりやすいかと思います。
パソコンとPLCの間で上位リンク通信を行う上では、その中身を知ることが非常に重要だったりしますので、PLCと各言語でどのように変換されるのか確認したいと思います。
結論から言えば、PLCでもプログラミング言語でも結果は同じとなりますが、その変換のコードも書き方も本投稿で学習のきっかけとなれば幸いです。
PLCの場合
試しに-35,256,852
という数字をPLCであらわしてみましょう。
CR2002とMOV.Lコマンドでこの数字をDM0に転送します。
その結果を登録モニタで32bit16進数で確認すると下図のようになると思います。
これは単純にこの数字が16進数として表記された結果ですが、DM0にどのようにデータが格納されたかを細かく分析するとこのようになります。
つまり、"05"と"EC"が下位レジスタであるDM0、"FD"と"E6"が上位レジスタであるDM1に格納されているということになります。
つまり、32bit符号付き整数が4つのByte配列になって、PLC内のレジスタに格納されているということになります。1つのByteで8bitですから、4バイトで32bitということになります。
Pythonの場合
Pythonで同じ数字を変数に代入して、Byte配列にしたらどうなるか、見てみましょう。コードは下記のとおりです。
valueという変数に整数を格納し、to_bytesメソッドでByte配列に変換します。その引数は配列数が4で、変換はリトルエンディアン、符号付きという意味になります。
※リトルエンディアンについては割愛いたします。
結果は0xfd
という風に出てきますが、PLCとの比較で分かりやすくするために0x
の表記を削除し、upper()
メソッドで大文字に変換します。
value = -35256852
buf = [hex(x).replace('0x','').upper()
for x in value.to_bytes(4, 'little', signed=True)]
str = buf[3]+', '
str += buf[2]+', '
str += buf[1]+', '
str += buf[0]
print('変換結果: ' + str)
結果としてはPLCで出力された結果と一致しています。
当然といえば当然のことですが、データがByte配列にどのようにPLCまたはパソコンンのメモリに格納されているかを知ることで、この先のPLC上位リンク通信でさまざま役に立つ場面が出てくると思います。
C#の場合
C#の場合もコードと結果を記載しておきます。
ToString("X")
で数字を16進数の大文字表記にしております。
internal class Program
{
private static void Main(string[] args)
{
int value = -35256852;
var buf = BitConverter.GetBytes(value)
.Select(x => x.ToString("X")).ToArray();
Console.WriteLine($"実行結果: {buf[3]}, {buf[2]}, {buf[1]}, {buf[0]}");
}
}
実行結果