はじめに
仕事でCODESYSを使うことになったので気づいたことのメモです。
MELSEC等の従来からあるPLCなら簡単なのですが、IEC61131-3準拠のCODESYSとかだとビット操作などが結構めんどいです。
(まあラダーも絶望的に書きづらいのでSTで書けという戦略なのでしょうか…MELSECがラダーをポコポコ書きやすすぎるという気もしますが)
ちなみにIEC61131-3は呼びにくい名前ですが「イレブンサーティワン」という呼び方もあるそうです。最近知りました。CODESYSがなんぞや見たいな説明はしません。もっと良い解説ページがあると思うから。
(めんどくさがりの言い訳)
ちなみにこれはCODESYSとOMRONのNX-EIC202(EtherNet/IP)と通信してる動画です。
CODESYS(Orange Pi R1 Plus LTSで実行)でEthernetIP使い方調べてたら夜になった。 pic.twitter.com/SsbBw2f9MU
— よしのぶ (@fa_yoshinobu) September 5, 2023
Orange Pi R1 Plus LTSという5000円くらいのSingle Board Computerです。
OSはArmbianを使用しています。
共用体(UNION)
ビット操作をしたい、こういう場合に使うのは共用体(UNION)です。共用体についての詳しい説明については省きますが、
要するに同じメモリ領域を2重で定義してWORDでアクセスしたりBITでアクセスしたりというものです。
MELSECだと[SET M0]だとBITで指定、[MOV K1 K4M0]だと桁指定でWORDで簡単にアクセスできるから楽なんですがねぇ~ はぁ…
失敗例
まずは失敗例です。なにが駄目なのか考えようのコーナー!
TYPE union_BIT16:
UNION
nBit : ARRAY[0..15] OF BOOL;
nByte : ARRAY[0..1] OF BYTE;
nWord : ARRAY[0..0] OF WORD;
END_UNION
END_TYPE
TYPE union_BIT32:
UNION
nBit : ARRAY[0..31] OF BOOL;
nByte : ARRAY[0..3] OF BYTE;
nWord : ARRAY[0..1] OF WORD;
nDword : ARRAY[0..0] OF DWORD;
END_UNION
END_TYPE
data1はunion_BIT16として、data2はunion_BIT32としてグローバル変数として定義。
union_BIT32はこいういイメージですねDWORDの1つの箱をDWORD,WORD,BYTE,BITで好きなように配列としてアクセスしようとする計画です。では動かしてみましょう。
nBit[0] オレンジ を TRUEにすると、nByte[0]が1に、 nBit[1] 緑 を TRUEにすると、nByte[1]が1に…
おかしいですね…
BITとBOOLの違い。
BITとBOOLどちらもTRUE/FALSEしか状態が格納できません。
じゃあなんで2つもおなじ役目の物があるねんということですが以下が違いです。
・BITは配列が作れない、BOOLは配列が作れる。
・BITは1つでメモリを1BIT使用する、BOOLは1つで1BYTE使用する。
※これはCODESYSの場合であり他のPLCも同じとは限りません
という違いがあります。
じゃあBITの方がメモリ節約できるじゃんとなりますが、問題は読み書きに時間がかかります。
コンピュータから見るとアドレスの指定はBYTE単位の方が処理しやすいからです。
BOOLでないと配列にできないのはコンピュータが処理しやすいからですね。
ではデータのサイズを見てみましょう。
SIZEOFでは変数のサイズを見れます。バイトのサイズが出力される関数です。
data1はboolが16個あるから 1Byte * 16 = 16になります。
data2はboolが32個あるから 1Byte * 32 = 32になります。
正解例
TYPE struct_BIT16 :
STRUCT
b00:BIT;
b01:BIT;
b02:BIT;
b03:BIT;
b04:BIT;
b05:BIT;
b06:BIT;
b07:BIT;
b08:BIT;
b09:BIT;
b0A:BIT;
b0B:BIT;
b0C:BIT;
b0D:BIT;
b0E:BIT;
b0F:BIT;
END_STRUCT
END_TYPE
TYPE struct_BIT32 :
STRUCT
b00:BIT;
b01:BIT;
b02:BIT;
b03:BIT;
b04:BIT;
b05:BIT;
b06:BIT;
b07:BIT;
b08:BIT;
b09:BIT;
b0A:BIT;
b0B:BIT;
b0C:BIT;
b0D:BIT;
b0E:BIT;
b0F:BIT;
b10:BIT;
b11:BIT;
b12:BIT;
b13:BIT;
b14:BIT;
b15:BIT;
b16:BIT;
b17:BIT;
b18:BIT;
b19:BIT;
b1A:BIT;
b1B:BIT;
b1C:BIT;
b1D:BIT;
b1E:BIT;
b1F:BIT;
END_STRUCT
END_TYPE
TYPE union_BIT16:
UNION
nBit :struct_BIT16;
nByte : ARRAY[0..1] OF BYTE;
nWord : ARRAY[0..0] OF WORD;
END_UNION
END_TYPE
TYPE union_BIT32:
UNION
nBit :struct_BIT32;
nByte : ARRAY[0..3] OF BYTE;
nWord : ARRAY[0..1] OF WORD;
nDword : ARRAY[0..0] OF DWORD;
END_UNION
END_TYPE
nBitのところが配列から構造体のstruct_BIT16/32になって構造体の中身はBITを16個,32個並べています。
ではこれで試してみましょう。
下位2BITがONなので3,BYTE,WORD,DWORDに3が入りましたねめでたしめでたし。
CODESYSのデータ型については以下に説明があります
他のBIT指定方法。
CountはWORDで定義しています。ほしいビットを.1などをつけるだけで使えます。
MELSECとかと同じですね。WORDだと.0~.15が指定できます
CODESYSの説明ページ(Index access to bits integer variables)