ナマケモノ成長日誌

怠惰を求めて勤勉に行き着く。

PLCラダー自動作成_3-3_軸のラダーを自動生成する

シリンダ関係と同じ感じです。

前回の記事

軸デバイスコメントの生成と、KV STUDIOへのインポートを行いました。
あとは、軸回路のニーモニック生成を自動で行います。

軸回路のラダーをマクロで組む

面倒臭い物はどんどんと自動化してしまおう。

軸回路のラダーの面倒くささ

軸回路って、繰り返し単位が大きいせいで、[複数貼り付け]で作りづらいですよね。
[複数貼り付け]でオフセット量を全て指定して…といった作り方ができないわけでは無いのですが、
一つの軸に対する一連のラダーがそれなりのボリュームになるので、オフセットの設定が非常に手間。
結果として、単純なコピペをした後に手修正してバグ連発、なんてことがよくある(反省)ので、効率化&バグ削減のためにマクロを使ってニーモニックを書いてしまおうという訳です。
今回は試しに、原点復帰回路を例に説明します。

手順

  1. Excelにラダー作成に必要な条件を設定する
  2. 軸回路のラダーの形を定義する
  3. ニーモニック生成用のシートを用意する
  4. マクロを書く
  5. マクロでニーモニックを作り、KV STUDIOに入力する。

1.Excelにラダー作成に必要な条件を設定する

前回記事終了時点だと不足する点があるので、もう少しExcelを作り込みます。

  • 位置決めユニットの構成設定欄を設ける

[軸デバイス設定]シートに、位置決めユニットの構成として、各ユニットでどの軸を制御するか、等を記載しておきます。

位置決めユニットの構成を設定する。

一応各項目について説明します。

  • ユニット種別

KV-XH04ML、KV-XH16MLのどちらを使用するかを記載します。
ラダーを書く上では、位置決めユニットの型式によって、ユニットに割当てられるリレー(R)の範囲が変わるので、ここの設定を参照してリレーの記述を切替えます。
プルダウンで選択できるようにしておくと楽。
なお今回提示のラダーでは、ユニット型式の軸数のチェックまでは行っていません。必要であれば実装してみてください。

ユニット種別の選択
  • 先頭軸,末尾軸

当該ユニットから制御する軸の範囲を指定します。
これも、[軸デバイス設定]シートに記載した軸をプルダウンで選択できるようにしておくと楽です。
なおユニット間での被りとか、順序の逆転のチェックなどは今回は実装していません。

先頭軸,末尾軸の選択
  • ユニット番号

ユニットエディタ上での位置決めユニットの位置を数値で指定します。
バッファメモリを扱う際にユニット番号を記述する場合、ここを参照します。

  • 先頭アドレス,末尾アドレス

ユニットに割付ける先頭リレー(R)を記述します。
末尾アドレスは割付けの補助として欄を設けていますが、ラダーを書く際には参照していません。
割付けられるリレーの数はユニットの型式により変わるので、下記のような数式を使って計算・表示しています。

末尾アドレスの計算

原点復帰回路に使うデバイスのコメントをフォーマットに記載して、デバイスコメントの生成・KV STUDIOへのインポートを行っておきます。

原点復帰回路に使うデバイスのコメント
フォーマットに従いデバイスコメントが生成される。

2.軸回路のラダーの形を定義する

[ツールを使って、こんな形のラダーを書くぞ]と定義しましょう。
例えばこんな風です。

原点復帰回路のラダーフォーマット

これをニーモニックにするとこんな感じです。

原点復帰回路のニーモニックフォーマット

3.ニーモニック生成用のシートを用意する

軸回路用のシートを別で用意しておいて、[軸ーモニック]など名前をつけます。
またニーモニックを生成する列を決めておきましょう。

4.マクロを書く

2.で決めたフォーマットに従いニーモニックを書くマクロを作成します。
こんな感じです。

Sub Axis_SV2_mnemonic()
    ' 機能:軸デバイス設定をもとに、各位置決めユニット・各軸ごとの原点復帰処理の命令セット(ニーモニック)を生成し、
    '       OUTarray に格納して、B列に一括出力する。

    Dim i As Long              ' ユニットごとのループカウンタ(最大8ユニット)
    Dim j As Long              ' 各ユニット内の軸ごとのループカウンタ
    Dim row As Long            ' OUTarray の出力行数カウンタ
    Dim OUTarray(0 To 65535) As String  ' 出力ニーモニックを格納する配列(最大65536行)

    Dim UNIT_1st_axis As Byte         ' 各ユニットにおける先頭軸番号(0~49)
    Dim UNIT_end_axis As Byte         ' 各ユニットにおける末尾軸番号(0~49)
    Dim UNIT_1st_axis_OUT As Long     ' 出力リレー(R)のベースアドレス
    Dim UNIT_1st_axis_IN As Long      ' 入力リレー(R)のベースアドレス

    ' === 各ユニット(最大8台分)をループ処理 ===
    For i = 0 To 7
        ' R6 から右方向に3列ずつ(R,S,T)を見てユニット名が入っている場合に処理
        If Worksheets("軸デバイス設定").Range("R6").Offset(0, i * 3).Value <> "" Then

            ' --------------------------
            ' ユニットの先頭軸 / 末尾軸の列位置取得(B2:AY2 から一致セルを探す)
            ' --------------------------
            With Worksheets("軸デバイス設定")
                ' 先頭軸名の列番号を取得(B列=列2 として基準)
                For Each cell In .Range("B2:AY2")
                    If cell.Value = .Range("S6").Offset(0, i * 3).Value Then
                        UNIT_1st_axis = cell.Column - 2
                        Exit For
                    End If
                Next cell

                ' 末尾軸名の列番号を取得(同上)
                For Each cell In .Range("B2:AY2")
                    If cell.Value = .Range("T6").Offset(0, i * 3).Value Then
                        UNIT_end_axis = cell.Column - 2
                        Exit For
                    End If
                Next cell
            End With

            ' --------------------------
            ' R出力 / R入力のベースアドレス設定
            ' --------------------------
            With Worksheets("軸デバイス設定")
                ' 出力(OUT)のベースアドレス:S9 + 200(これは固定加算)
                UNIT_1st_axis_OUT = .Range("S9").Offset(0, i * 3).Value + 200

                ' 入力(IN)のベースアドレスはユニット形式により分岐
                Select Case .Range("R6").Offset(0, i * 3).Value
                    Case "KV-XH04ML"
                        UNIT_1st_axis_IN = .Range("S9").Offset(0, i * 3).Value + 2000
                    Case "KV-XH16ML"
                        UNIT_1st_axis_IN = .Range("S9").Offset(0, i * 3).Value + 6800
                End Select
            End With

            ' --------------------------
            ' ユニット名ブックマークをOUTarrayに出力
            ' --------------------------
            With Worksheets("軸デバイス設定")
                OUTarray(row) = ";<h1/>■" & .Range("R6").Offset(0, i * 3).Value & "[" & .Range("R9").Offset(0, i * 3).Value & "]"
                row = row + 1
            End With

            ' --------------------------
            ' 各軸に対する命令セット(原点復帰処理)を生成
            ' --------------------------
            For j = 0 To UNIT_end_axis - UNIT_1st_axis
                ' --- ブックマーク:軸名 ---
                OUTarray(row) = ";<h1/> -" & Worksheets("軸デバイス設定").Range("B2").Offset(0, j + UNIT_1st_axis)
                row = row + 1

                ' --- 原点復帰中処理 ---
                OUTarray(row) = ";--原点復帰--": row = row + 1

                ' LDP:原点復帰開始スイッチ(軸操作デバイス)
                OUTarray(row) = "LDP " & Worksheets("軸操作デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 4): row = row + 1
                ' OR:原点復帰ビット
                OUTarray(row) = "OR " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' AND:動力ON(共通フラグ)
                OUTarray(row) = "AND 動力ON": row = row + 1
                ' ANB:アラームリセット状態チェック1(Rビット)
                OUTarray(row) = "ANB R" & UNIT_1st_axis_OUT + 102 + j * 400: row = row + 1
                ' ANB:アラームリセット状態チェック2(制御デバイスの別ビット)
                OUTarray(row) = "ANB " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' OUT:原点復帰実行(制御デバイス)
                OUTarray(row) = "OUT " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' OUT:原点復帰実行(Rビット)
                OUTarray(row) = "OUT R" & UNIT_1st_axis_OUT + 110 + j * 400: row = row + 1

                ' --- 原点復帰完了処理 ---
                OUTarray(row) = "LD R" & UNIT_1st_axis_IN + 110 + j * 400: row = row + 1
                OUTarray(row) = "OR " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                OUTarray(row) = "AND " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                OUTarray(row) = "OUT " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
            Next j
        Else
            Exit For
        End If
    Next i

    ' ===============================
    ' 出力配列をB列に一括書き出し
    ' ===============================
    Range("B1").Resize(row, 1).Value = Application.Transpose(OUTarray)

    MsgBox "完了しました。"
End Sub

実行すると、ニーモニックが生成されます。

生成された原点復帰回路のニーモニック

生成したニーモニックを全てコピーし、KV STUDIOの[リスト編集]で貼付けて挿入すると、原点復帰回路が生成されます。

生成された原点復帰回路

そんなに大したものではないのですが、マクロ動作について説明していきます。

変数定義
    Dim i As Long              ' ユニットごとのループカウンタ(最大8ユニット)
    Dim j As Long              ' 各ユニット内の軸ごとのループカウンタ
    Dim row As Long            ' OUTarray の出力行数カウンタ
    Dim OUTarray(0 To 65535) As String  ' 出力ニーモニックを格納する配列(最大65536行)

    Dim UNIT_1st_axis As Byte         ' 各ユニットにおける先頭軸番号(0~49)
    Dim UNIT_end_axis As Byte         ' 各ユニットにおける末尾軸番号(0~49)
    Dim UNIT_1st_axis_OUT As Long     ' 出力リレー(R)のベースアドレス
    Dim UNIT_1st_axis_IN As Long      ' 入力リレー(R)のベースアドレス

01. i:Integer(整数型)
02. j:Integer(整数型)
03 row:Integer(整数型)
04 OUTarray(0 to 65535):String(文字列型)
シリンダニーモニックと同様です。

06. UNIT_1st_axis:Byte(1バイト整数型)
07. UNIT_end_axis:Byte(1バイト整数型)
位置決めユニットの先頭軸番号と末尾軸番号を0~49の範囲で格納します。

08. UNIT_1st_axis_OUT:Long(長整数型)
09. UNIT_1st_axis_IN:Long(長整数型)
位置決めユニットの先頭軸に割付けられた出力アドレスと入力アドレスを格納します。

位置決めユニット情報の取得
    For i = 0 To 7
        ' R6 から右方向に3列ずつ(R,S,T)を見てユニット名が入っている場合に処理
        If Worksheets("軸デバイス設定").Range("R6").Offset(0, i * 3).Value <> "" Then

            ' --------------------------
            ' ユニットの先頭軸 / 末尾軸の列位置取得(B2:AY2 から一致セルを探す)
            ' --------------------------
            With Worksheets("軸デバイス設定")
                ' 先頭軸名の列番号を取得(B列=列2 として基準)
                For Each cell In .Range("B2:AY2")
                    If cell.Value = .Range("S6").Offset(0, i * 3).Value Then
                        UNIT_1st_axis = cell.Column - 2
                        Exit For
                    End If
                Next cell

                ' 末尾軸名の列番号を取得(同上)
                For Each cell In .Range("B2:AY2")
                    If cell.Value = .Range("T6").Offset(0, i * 3).Value Then
                        UNIT_end_axis = cell.Column - 2
                        Exit For
                    End If
                Next cell
            End With

            ' --------------------------
            ' R出力 / R入力のベースアドレス設定
            ' --------------------------
            With Worksheets("軸デバイス設定")
                ' 出力(OUT)のベースアドレス:S9 + 200(これは固定加算)
                UNIT_1st_axis_OUT = .Range("S9").Offset(0, i * 3).Value + 200

                ' 入力(IN)のベースアドレスはユニット形式により分岐
                Select Case .Range("R6").Offset(0, i * 3).Value
                    Case "KV-XH04ML"
                        UNIT_1st_axis_IN = .Range("S9").Offset(0, i * 3).Value + 2000
                    Case "KV-XH16ML"
                        UNIT_1st_axis_IN = .Range("S9").Offset(0, i * 3).Value + 6800
                End Select
            End With

            ' --------------------------
            ' ユニット名ブックマーク
            ' --------------------------
            With Worksheets("軸デバイス設定")
                OUTarray(row) = ";<h1/>■" & .Range("R6").Offset(0, i * 3).Value & "[" & .Range("R9").Offset(0, i * 3).Value & "]"
                row = row + 1
            End With

1~3行目:位置決めユニットの型式が入力されていればニーモニック生成
[軸デバイス設定]シートにてユニット型式が選択されていればニーモニックを生成します。
ニーモニックを生成する前にチェックすべき項目は他にもあるのですが、
一旦は全て正しい入力がなされているという前提で進めます。

8~24行目:先頭軸、末尾軸の番号を取得
現在の位置決めユニットの先頭軸、末尾軸の番号を取得します。
For Each cell In .Range("B2:AY2")でB2~AY2セルの全てを確認し、
現在の位置決めユニットの軸名称と一致しているセルが見つかったら、
そのセルの列数 - 2 した値をUNIT_1st_axis、UNIT_end_axisに格納します。(0~49の値)

29~40行目:先頭軸の出力/入力アドレスを取得する
現在の位置決めユニットの先頭軸に割当てられる入出力リレー(R)の先頭アドレスを取得します。
出力アドレスは、位置決めユニットの先頭アドレス+2チャネル
入力アドレスは、ユニットの型式に応じて先頭アドレス+20チャネル(XH04MLの場合)、又は68チャネル(XH16MLの場合)です。
軸ごとの入出力リレーオフセット量は同一なので、ここから先は特段ユニット型式の違いを意識する必要が無くなります。

45~48行目:位置決めユニットのブックマークを記述する
ブックマークを入れておきます。

軸ごとの原点復帰回路ニーモニックを記述する。
            For j = 0 To UNIT_end_axis - UNIT_1st_axis
                ' --- ブックマーク:軸名 ---
                OUTarray(row) = ";<h1/> -" & Worksheets("軸デバイス設定").Range("B2").Offset(0, j + UNIT_1st_axis)
                row = row + 1

                ' --- 原点復帰中処理 ---
                OUTarray(row) = ";--原点復帰--": row = row + 1

                ' LDP:原点復帰開始スイッチ(軸操作デバイス)
                OUTarray(row) = "LDP " & Worksheets("軸操作デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 4): row = row + 1
                ' OR:原点復帰ビット
                OUTarray(row) = "OR " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' AND:動力ON(共通フラグ)
                OUTarray(row) = "AND 動力ON": row = row + 1
                ' ANB:アラームリセット状態チェック1(Rビット)
                OUTarray(row) = "ANB R" & UNIT_1st_axis_OUT + 102 + j * 400: row = row + 1
                ' ANB:アラームリセット状態チェック2(制御デバイスの別ビット)
                OUTarray(row) = "ANB " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' OUT:原点復帰実行(制御デバイス)
                OUTarray(row) = "OUT " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                ' OUT:原点復帰実行(Rビット)
                OUTarray(row) = "OUT R" & UNIT_1st_axis_OUT + 110 + j * 400: row = row + 1

                ' --- 原点復帰完了処理 ---
                OUTarray(row) = "LD R" & UNIT_1st_axis_IN + 110 + j * 400: row = row + 1
                OUTarray(row) = "OR " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                OUTarray(row) = "AND " & Worksheets("軸制御デバイス").Range("A6").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
                OUTarray(row) = "OUT " & Worksheets("軸制御デバイス").Range("A7").Offset(0, (UNIT_1st_axis + j) * 2): row = row + 1
            Next j
        Else
            Exit For
        End If
    Next i

    ' ===============================
    ' 出力配列をB列に一括書き出し
    ' ===============================
    Range("B1").Resize(row, 1).Value = Application.Transpose(OUTarray)

    MsgBox "完了しました。"
End Sub

1~4行目:位置決めユニットに割付けられた軸数分繰り返す
UNIT_end_axisとUNIT_1st_axisに先頭軸、末尾軸の番号が格納されているので、For文で繰り返します。
また、軸ごとにブックマークを入れておきます。

6~28行目:原点復帰回路のニーモニックを作る
予め決めておいたフォーマットに従いニーモニックを記述していきます。
事前に作ったデバイスマップから現在の軸のデバイスを拾ってきて、ニーモニックに反映させるイメージです。
デバイスマップには、各軸のデバイスが一定の間隔で並んでいますから、offsetプロパティを用いて参照するデバイスをスライドさせていくことで、For文で繰り返す中で対象の軸を切替えていけるという訳です。

まとめ

軸回路もマクロで書けちゃう。
今回は原点復帰のみ作りましたが、変数[j]を使ったFor文中に、手動操作、起動、JOGなどの、一つの軸に関する他のニーモニック生成マクロを追加していけば、軸回路を効率的にミスなく生成することが可能です。