【GX Works3】MOV命令の使い方|MOVP・DMOV・FMOV/BMOVの使い分けまで総まとめ

概要:転送命令はこの4つで足りる

「タッチパネルの設定値をタイマにセットしたい」「エラーコードをクリアしたい」——GX Works3でラダーを組み始めると、真っ先に使うことになるのがMOV命令です。指定したデバイスの数値を別のデバイスへコピーするだけのシンプルな命令ですが、初期化・設定値転送・データ受け渡しなど、あらゆる場面で顔を出すため、PLCプログラムの中で最も出現回数が多い命令と言っても過言ではありません。

そしてMOVには「32bit版のDMOV」「同じ値を敷き詰めるFMOV」「ブロックごとコピーするBMOV」という兄弟がいて、現場のデータ転送はほぼこの4つで完結します。この記事では、実務で必ずぶつかる「MOVとMOVPの上書き問題」を中心に、4命令の使い分けまで現場目線で総まとめします。

やりたいこと使う命令
数値を1点、デバイスに入れるMOV(P)
±32767を超える値・32bitで扱う値を転送するDMOV(P)
同じ値をn点の連続デバイスに敷き詰める(一括初期化)FMOV(P)
連続n点のかたまりをそのまま別エリアへコピーするBMOV(P)

MOV/MOVP(16bit転送の基本)

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 / ops/refs/instructions/08_data-transfer.md より転記。

命令記号実行条件主なオペランド/データ型動作
MOV常時実行(s) 転送元 / (d) 転送先(符号付きBIN16/ANY16)BIN16ビットデータを指定デバイスへ転送
MOVP立上り(s) 転送元 / (d) 転送先(符号付きBIN16/ANY16)立上り1スキャンのみ転送(毎スキャン上書きを防ぐ)

範囲 -32768〜32767。常時実行のMOVは毎スキャン上書きされる点に注意。

動作

X0 → MOVP K100 D0 のラダー図(定数100をD0へ転送)
図1:X0がONした瞬間だけMOVPが実行され、定数100がD0へ一度だけ転送されます。
MOV(常時実行・毎スキャン上書き)と MOVP(立上り1回のみ)を並べた比較ラダー図。コメントで動作の違いを明記
図2:同じ転送でもMOVは常時実行、MOVPは立上りのみ実行という違いが、D0への書き込み頻度の差になって表れます。

MOVは「(s)で指定したBIN16ビットデータを(d)へ転送する」というだけの命令です。ただし実行条件の違いによって、現場での挙動はまったく変わります。MOVは常時実行なので、実行条件がONの間は毎スキャン(d)へ書き込みが行われ続けます。一方MOVPは立上り実行のため、実行条件がOFF→ONに変わった瞬間の1スキャンだけ転送が行われ、そのあとは何もしません。図1のように「ボタンを押した瞬間に設定値をセットしたい」という用途では、MOVPを使うのが基本形です。

もう一つ押さえておきたいのが、(s)に桁指定したビットデバイス(K1X0やK2M0など)を指定した場合の挙動です。マニュアルによると、桁指定で指定した範囲のビットだけが転送対象になり、それ以外のビットは「0が指定されているものとして」転送されます。つまりK1X0(4ビット分)を(s)にしてD0へ転送すると、D0の上位12ビットは元の値に関係なく強制的に0でクリアされる、ということです。ここを知らずに「一部のビットだけ書き換えたい」という使い方をすると、意図せず他のビットまで0になって事故ります。なお、MOV/MOVPともに演算エラーは発生しません。

サンプルコード

① タッチパネルの設定値をタイマにセットする

[X10  MOVP  D500  D0 ]

タッチパネル側でD500に書き込んだ設定値(例:ワーク投入待ち時間)を、X10(設定確定ボタン)が押された瞬間だけD0へ転送します。D0をそのままタイマの設定値デバイスとして使えば、プログラムを止めずにタイマ時間を変更できます。常時実行のMOVにしてしまうと、オペレーターがタッチパネルを操作している途中の中途半端な値まで毎スキャンD0に反映されてしまうため、確定操作を挟むならMOVPを使うのが定石です。

② 入力16点をまとめてワードデバイスへ取り込む

[SM400  MOV  K4X0  D10 ]

SM400(常時ON)を実行条件にして、X0〜XF(16点。iQ-RのX/Yデバイスは16進数採番)をK4X0という桁指定でまとめて指定し、D10へ転送します。1点ずつM0〜M15にコピーするより回路がすっきりし、D10を16進数表示にすればオンオフパターンを1つの値として監視・比較できるようになります。診断表示やロギング用にまとめてデータを整形したいときによく使う型です。

③ エラーコードのゼロクリア

[X20  MOVP  K0  D100 ]

D100をエラーコード格納用デバイスとして使っている場合、X20(エラーリセットボタン)が押された瞬間に定数0を書き込んでクリアします。RSTでも同様にクリアできますが(ワードデバイスに対するRSTはMOV K0と同一動作)、0以外の任意の初期値を書き込みたい場面ではMOV(P) K◯◯の形しか使えません。あわせて覚えておくと応用が利きます。

よくある誤解

①「MOVで一度転送したら値は保持される」という誤解

MOVは"転送"であって"記憶"ではありません。実行条件がONの間、MOVは毎スキャン(d)へ上書きを続けます。よくあるハマりどころが、常時ON条件でMOVを入れっぱなしにした結果、その下流で別の回路がD0を書き換えても毎スキャン元の値に戻されてしまい、「なぜか自分の書き込みが反映されない」と延々と悩むケースです。ワンショットで値を入れたいだけならMOVPを使う、これがMOV/MOVPで最も間違えやすいポイントです。

②範囲外の値をそのままMOVに突っ込む

MOVが扱えるのは-32768〜32767の範囲の符号付きBIN16ビットデータだけです。この範囲を超える値(大きな積算値やカウント値など)を扱いたい場合は、32ビット版のDMOV(次のセクションで解説)を使う必要があります。「Dデバイス2個分を使いたいのにMOVで済ませようとして値が壊れる」というのも初心者が詰まりやすいポイントの一つです。

③桁指定ビットデバイスからの転送で上位ビットが0埋めされる

K1X0やK2M10のように(s)へ桁指定したビットデバイスを指定すると、指定した桁数分しか転送されず、残りのビットは0として扱われます。「一部のビットだけ更新したくて桁指定を使ったのに、転送先の上位ビットまで0にリセットされてしまった」という事故につながりやすいポイントです。転送先の全ビットが上書きされる前提で桁数を設計しましょう。

DMOV/DMOVP(32bit転送)

「位置決めユニットへ送る目標パルス数」「生産数の積算カウンタ」——MOVを使い続けていると、±32767の範囲をあっさり超える値に必ず突き当たります。そこで使うのがDMOVです。動作イメージは「MOVの32ビット幅版」ですが、内部でワードデバイスを2つ使う構造になっているため、そこだけは意識して使う必要があります。

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 / ops/refs/instructions/08_data-transfer.md より転記。

命令記号実行条件主なオペランド/データ型動作
DMOV / DMOVP常時実行/立上り(s) 転送元 / (d) 転送先(符号付きBIN32/ANY32)BIN32ビットデータを転送(デバイス2点使用)

範囲 -2147483648〜2147483647。D0指定でD0(下位16bit)+D1(上位16bit)を使用。奇数番号始まりは避ける。

動作

X0 → DMOVP K100000 D0 のラダー図(32bit定数をD0,D1へ転送)
図3:X0がONした瞬間だけDMOVPが実行され、32ビット定数100000がD0・D1の2ワードへ一括転送されます。
D0(下位16bit) + D1(上位16bit) で32bitを構成する図。デバイスモニタ画面キャプチャでも可
図4:D0を32bit転送の先頭に指定すると、下位16ビットはD0、上位16ビットはD1に格納され、2つのワードで1つの32bit値を構成します。

DMOVは「(s)で指定されたBIN32ビットデータを、(d)で指定されたデバイスへ転送する」命令です。ここで現場が必ず押さえておきたいのが、(d)にD0を指定した場合の実際の消費デバイス数です。書式のオペランド欄では(d)は1つのデバイスとして書かれていますが、32ビットデータを格納するには16ビットのワードデバイス2つ分の領域が必要になるため、D0を指定すると実際にはD0(下位16ビット)とD1(上位16ビット)の2ワードが使われます。デバイス一覧やコメント一覧でD0だけを見て「1ワードしか使っていない」と判断すると、隣のD1が別の用途で使われていた場合に値が衝突する事故につながります。

また(s)にK1X0のような桁指定したビットデバイスを指定した場合、指定した桁数分のビットだけが転送対象になり、それ以外のビットは0が指定されているものとして扱われます。MOVと同じ考え方ですが、対象が32ビット分に広がるぶん、意図せず広い範囲が0クリアされるリスクも大きくなります。なお、DMOV/DMOVPともに演算エラーは発生しません。

サンプルコード

① 位置決めユニットへ目標パルス数をセットする

[X0  DMOVP  K100000  D0 ]

位置決め軸の目標位置を100000パルスにセットする例です。X0(位置決め開始条件)が立ち上がった瞬間だけD0・D1へ32ビット定数を転送します。MOVでは32767までしか扱えないため、パルス数が大きくなる位置決め用途ではDMOVが標準になります。

② 32ビット積算値を別デバイスへ退避コピーする

[X1  DMOVP  D200  D300 ]

D200・D201に格納されている32ビット積算値(生産数カウンタなど)を、X1が立ち上がった瞬間にD300・D301へコピーします。リセット前に現在値を退避しておきたい、といった場面でよく使う型です。

③ 2ワードを一括でゼロクリアする

[SM400  DMOV  K0  D100 ]

D100・D101をまとめてゼロクリアする例です。RSTやMOV K0を2回に分けて書く代わりに、DMOV K0で1命令・2ワード分を一括初期化できます。SM400(常時ON)を条件にしているので、電源投入直後の初期化処理などに組み込む形です。

よくある誤解

①「D0だけ使ってるつもり」で隣のデバイスを潰す

DMOVの(d)をD0だけの1個のデバイスとして扱ってしまうと事故ります。実際にはD0(下位16ビット)とD1(上位16ビット)の2ワードを消費するため、D1を別の用途(例えば別のタイマ設定値など)に割り付けていると、DMOVを実行した瞬間にその値が上書きされてしまいます。デバイス一覧表ではDMOVの(d)に指定したデバイスの「次の番号」まで予約済みとして扱うのが安全です。DMOV/DMOVP絡みのトラブルで最も多いのが、実はこの1点です。

②MOVで32ビット値を扱おうとして値が壊れる/逆に小さい値でもDMOVで統一する

32767を超える値をMOVで転送しようとすると正しく転送できません。逆に、値そのものは小さくてもデバイスコメントや用途上32ビットとして扱うと決めているデータ(積算値・パルス数など)は、あえて全部DMOVで統一しておくと、あとから桁数が大きくなったときに命令を書き換える手間を防げます。

③デバイス割付を1個ずつ進めて重複させてしまう

DMOVで32ビットデバイスを使うと決めたら、次のDMOVで使うデバイスはD0,D2,D4…のように2個飛ばしで割り付ける必要があります。D0,D1,D2…と1個ずつ順番に割り付けてしまうと、2本目のDMOVの下位ワードが1本目の上位ワードと重なってしまい、片方の値が壊れます。デバイス割付表を作るときは、32ビットデバイスは最初から「2個1組」で予約しておきましょう。

FMOV/BMOV(一括転送・ブロック転送)

FMOVとBMOVは似ているようで役割がまったく違います。FMOVは1つの値を指定した範囲すべてに敷き詰める命令で、複数のデバイスを同じ値でまとめて初期化したいときに使います。対してBMOVは、連続したエリアの中身をそのまま別のエリアへコピーする命令で、値がバラバラのブロックをそっくり移動させたいときに使います。データテーブルの一括クリア、レシピデータの切替、測定値の履歴退避など、現場で「まとめて」扱いたい場面ではまずこの2つが候補に挙がります。

書式

出典: MELSEC iQ-R プログラミングマニュアル(CPUユニット用命令/汎用FUN/汎用FB編)SH-081226 / ops/refs/instructions/08_data-transfer.md より転記。

命令記号実行条件主なオペランド/データ型動作
FMOV / FMOVP常時実行/立上り(s) 転送データ / (d) 先頭 / (n) 点数 0〜65535同一データをn点の連続デバイスへ一括転送
BMOV / BMOVP常時実行/立上り(s) 先頭 / (d) 先頭 / (n) 点数 0〜65535連続n点のブロックを別エリアへ一括転送

FMOV=同一値の敷き詰め(初期化に便利)、BMOV=ブロックコピー。

動作

FMOVP K100 D0 K5 のラダー図(D0〜D4の5点に全て100を転送)
図5:FMOVP K100 D0 K5 により、実行条件が成立した瞬間にD0を先頭とする5点(D0〜D4)へ定数100が一括で書き込まれます。
BMOVP D0 D10 K5 のラダー図(D0〜D4の内容をD10〜D14へブロックコピー)
図6:BMOVP D0 D10 K5 により、D0〜D4の5点分の内容がそのままD10〜D14へブロックごとコピーされます。

FMOVの機能はシンプルで、(s)で指定した1点のBIN16ビットデータと同じ値を、(d)を先頭にn点分すべてに書き込みます。図5のようにK100を(s)にすれば、D0からD4までの5点全部が100で埋まります。値は1つ、書き込み先だけがn点に広がるイメージです。

一方BMOVは、(s)を先頭にn点分のデータをそのまま(d)を先頭にn点分へコピーします。図6のようにD0〜D4の5点それぞれの値が、そのままD10〜D14へ移されます。転送元と転送先が重なっていても転送は可能で、マニュアルの規定では、デバイス番号の小さい方へ転送する場合は(s)から順に、大きい方へ転送する場合は(s)+(n)-1から順に処理されるため、上書きによるデータ破壊を避けられる設計になっています。

またFMOV・BMOVともに、(s)や(d)にビットデバイスを桁指定(K1X0など)で組み合わせた場合は、その桁指定分のビット数だけが転送対象になります。演算エラーは発生しません。

サンプルコード

①ロギングエリアをまとめてゼロクリアする

[X10  FMOVP  K0  D100  K20 ]

D100を先頭とする20点(D100〜D119)を測定値のロギングエリアとして使っている場合、X10(クリアボタン)が押された瞬間に全点へ定数0を書き込みます。1点ずつRSTやMOVで消していくと回路が長くなりますが、FMOVPなら1行でエリア全体を初期化できます。運転開始前のイニシャライズ処理でもよく使う形です。

②レシピデータを実行エリアへ展開する

[X20  BMOVP  D200  D300  K10 ]

D200を先頭とする10ワード(D200〜D209)に品種ごとのレシピ(温度・速度・時間などの設定値セット)を格納しておき、X20(品種切替ボタン)が押された瞬間にD300以降の実際に使う実行エリア(D300〜D309)へ丸ごとコピーします。切り替えたいレシピの先頭番地を(s)に指定するだけで展開できるため、多品種切替の定番パターンです。

③測定値の履歴を1つ後ろへシフトして退避する

[X30  BMOVP  D0  D1  K9 ]

D0〜D9の10点を「今回値+直近9回分の履歴」として使っている場合、X30(サンプリングタイミング)が立ち上がるたびに、D0を先頭とする9点(D0〜D8)をD1を先頭とする9点(D1〜D9)へ転送すると、既存の履歴が1つずつ後ろへシフトします。常時ON条件のBMOVにすると毎スキャンずれてしまうため、必ずトリガ条件+BMOVPで組みます。転送元(D0〜D8)と転送先(D1〜D9)が重なっていますが、BMOVはデバイス番号の大きい方への転送なので(s)+(n)-1すなわちD8から順に処理され、データが上書きで潰れることなく正しくシフトされます。このあとD0へ新しい測定値をMOVで書き込めば、履歴バッファの完成です。

よくある誤解

①FMOVとBMOVを混同する

名前が似ているFMOVとBMOVですが、動作は正反対です。FMOVは(s)で指定した1つの値をn点全部に敷き詰める命令、BMOVは(s)から始まるn点分のデータをそのままn点分コピーする命令です。「同じ値で埋めたいのか、違う値のまとまりをそのまま移したいのか」を先に決めてから命令を選ばないと、初期化のつもりでBMOVを使ってしまい元データがそのまま流用されて意図しない値が入る、といったミスにつながります。

②「転送元と転送先が重なるとBMOVは使えない」という誤解

「転送元と転送先のデバイス範囲が重なっていると、正しく転送できないのでは」と心配する人もいますが、マニュアルには「転送元と転送先のデバイスが重複している場合も転送を行うことができます」と明記されています。デバイス番号の小さい方へ転送する場合は(s)から順に、大きい方へ転送する場合は(s)+(n)-1から順に処理する、という方向の規定があるため、重なっていても正しい結果が得られる設計になっています。先ほどの履歴シフトの例のように、あえて範囲を重ねて使うテクニックもあるので、「重なる=NG」と決めつけないようにしましょう。

③(s)(d)が両方ビットデバイスの場合は桁数をそろえる

(s)、(d)の両方にビットデバイスを指定する場合、マニュアルには「(s),(d)が両方ともビットデバイスの場合は,必ず(s),(d)の桁数を同一にしてください」という注意書きがあります。たとえばK2X0(8ビット分)を(s)にしたのに(d)をK4Y0(16ビット分)にする、といった桁数の食い違いは避ける必要があります。片方がワードデバイスであれば桁指定側のビット数が転送対象になりますが、両方ビットデバイスのときだけはこのルールに従って桁数をそろえてください。

SWAP/XCHはどうする?

転送系にはほかに、ワード内の上位/下位バイトを入れ替えるSWAPと、2つのデバイスの値を交換するXCHがあります。通信データのバイトオーダー変換など用途がニッチなので、この記事では深掘りしません。書式は命令語 早見表のデータ転送セクションで確認できます。

関連記事