変数

変数とは

PLCでラダーを作っていると物理アドレス(DM100とか)でメモリを指定しますが変数では'aaa'などの文字で指定します
PLCの中では'aaa'=0番地、'bbb'=1番地のようなテーブルが作られていて、これはビルドするときに自動的に割り振られるため何番のアドレスに'aaa'の変数が割り当てられているとかを気にする必要はありません

データ型の種類

種類の詳細はマニュアルを見てもらうとして、ここではザックリとどういう使い分けをするかなどを書きます

ブール型
ブール型はON/OFFを表す型で値はTRUE/FALSEと表現します
I/Oの接点やラダー内でフラグとして使用することが多いでしょう

ビット列型
BYTE,WORD,DWORD,LWORDです
ビット演算(AND XORなど)や命令語によって必要が出てきたときに使うぐらいの意識で、積極的に使わないようにします
ただし、BYTE配列は通信系のラダーでは使いやすいのでおすすめです

数値型
基本はこの数値型を使います
サイズの違いでSINT,INT,DINT,LINTがあり、それぞれにU付きのUSINT,UINT,UDINT,ULINTが加わります
U付きは符号なし(unsigned)という意味でマイナスがありません

実数型
REAL,LREALです
このデータ型は小数点が扱えますが、誤差が出ることに注意が必要です
(演算の時には丸めなどの処理をして回避します)
REAL型で6桁程度、LREAL型で14桁程度の精度があります
非常に便利なのですが、小数点3桁程度の精度でよければ数値型で×1000倍して計算したほうがいい場合もあります
数値型に比べて演算速度は遅くなりがちなので、スキャンタイムが伸びそうなら数値型にすると縮まることも・・・

日付時刻関係
TIME,DATE,TIME_OF_DAY,DATE_AND_TIMEです
タイマーの値はT#500msとか分かりやすく書けます
今日から7日後とかのカレンダー処理が必要なときには、月をまたぐか?、2月ならうるう年か?、年をまたぐのか?とか気にせずプラスT#7dすれば結果がもらえます
内部的には1970/01/01を起点に経過時間をns単位で累積した値を年月日時分秒に直しています
気にすることはないのですが、DATE_AND_TIME型をクリアした時に1970/01/01 00:00:00となることは覚えておいたほうがいいでしょう

文字列型
文字列の最後にNULL(0x00)を付けて文字列として扱います
文字コードはUTF-8です
最大文字数は1986byte(NULL含む)で、日本語を使うと減ります(全て日本語で661文字程度)
文字コードの変換はSJISToUTF8とUTF8ToSJISが用意されています

派生データ型

構造体型 (STRUCT)
複数の変数をまとめてデータ型を作れます
【例】3次元の座標をsPositionという名前で構造体を作ると下のようになります
構造体名 メンバ データ型
sPositon Struct
X LREAL
Y LREAL
Z LREAL

さらに、座標に有効フラグのEnableと座標名称のNameという変数を追加すると下のように異なった変数をひとつにまとめることができます
構造体名 メンバ データ型
sPositon Struct
X LREAL
Y LREAL
Z LREAL
Enable BOOL
Name STRING[20]

共用体型 (UNION)
同一のデータに対して異なるデータ型でアクセスできるようになります
ただし共用体のメンバに指定できるのはBOOL型とビット列型のみです

【例】BOOL型とWORD型とDWORD型の共用体を作ると下のようになります
共用体名 メンバ データ型
uTemp Union
B BOOL[32]
W WORD[2]
DW DWORD

この共用体のDWに16進で12345678という値を入れると下のようにメモリに入ります
H L
BOOL[32] 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0
WORD[2] 1234 5678
DW 12345678

変数名.b[0]はFALSE、変数名.b[3]はTRUE、変数名.W[0]は5678になります

列挙型 (ENUM)
値を意味のある文字に置き換えることができます

【例】モータの方向を指定するときに以下のように列挙型を作成します
名称 列挙値
正方向 0
近回り 1
負方向 2
現在方向 3
指定なし 4

配列

配列を使う場面は、レシピなど同じデータの塊を複数用意する場合や通信処理でバイト配列はよく使います

【例】上記の構造体のsPositionを使って位置データを20セット作ると下のような配列になります
データ型にsPosition[20]と入力すると勝手に下図のように変換してくれます

使うときは下記のように使います(ST内で使うとき)
Position[0].X:=100.0
Position[0].Y:=200.0
Position[0].Z:=10.0
Position[1].X:=120.0
Position[1].Y:=220.0
Position[1].Z:=12.0

ローカル変数とグローバル変数

基本的にグローバル変数を使わないようにプログラムを考えます
構造化プログラミングを意識すると自然とグローバル変数は少なくなると思います
たとえば、よく使うブロック(ローダー部分とか)を基本形の1つのPOUで作っておいて、ほかの設備でも使いまわせるようにグローバル変数はできるだけ少なくするなど

スコープ
ローカル変数はPOU内だけ見ることができる変数で、グローバル変数はどこからでも見れる変数です

グローバル変数Global01はPOU1からでもPOU2からでも見れます
POU1のローカル変数aaaとPOU2のローカル変数aaaは同じ名前ですが違うメモリに割り当てられます
POU1のローカル変数aaaはPOU2からは見ることができず、同様にPOU2のローカル変数aaaはPOU1からは見ることができません
これらのことを、POU1のローカル変数aaaはPOU1から見て「スコープ内にある」と言い、POU2から見ると「スコープの外にある」と言います

属性

初期値
PLC起動時に初期値が変数に入ります
保持にチェックが入っていると初期値は無視されます
割付先
I/Oマップに登録された変数は何らかの値が入ります
CJユニット用メモリにアクセスするときには下表のように設定します
CJメモリ 割付け方
CIO_0 %0
CIO_0.00 %0.0
WR0 %W0
HR0 %H0
DM0 %D0
EM0_0 EM0_0
EM4_0 EM4_0

【例】


保持
PLC電源断時に値を保持する

コンスタント
ラダー等から値の変更不可

ネットワーク公開
PCなどから変数にアクセスするときには必ず公開、入力、出力のどれか(非公開以外)を選択
タグデータリンクするときは入力もしくは出力を選択