PythonでKEYENCEの上位リンク通信(Ethernet)します
この上位リンク通信はメッセージサービス用の通信コマンドでPC-PLC間で使用してPLCのメモリの値を読み書きできます
ここではpythonを使ってEtherenetで上位リンク通信するクラスを作りました
kvHostLink
環境
PLC対象機種
KV-EP21V
KV-8000(A)
KV-7500
KV-5500
KV-NC1EP
クライアント側環境
python 3.9
対応コマンド
機能 | コマンド | メソッド |
---|---|---|
モード変更 | Mn | mode |
エラークリア | ER | errclr |
エラー番号確認 | ?E | er |
機種の問い合わせ | ?K | unittype |
時刻設定 | WRT | settime |
強制セット | ST | set |
強制リセット | RS | reset |
連続強制セット | STS | sts |
連続強制リセット | RSS | rss |
データ読み出し | RD | read |
連続データ読み出し | RDS | reads |
データ書き込み | WR | write |
連続データ書き込み | WRS | writes |
使い方
上位リンク通信のコマンドとレスポンスはすべて文字列です
レスポンスは文字列で最後にはCR+LFが付きます
オブジェクトの作成
kv = kvHostLink('192.168.0.31')
kvhostlinkクラスは通信相手のPLCのIPアドレスを指定してオブジェクトを作ります
モード変更
data = kv.mode('1')
引数には0か1を入れて動作状態を切り替えます
0: PROGRAMモード
1: RUNモード
エラークリア
data = kv.errclr()
エラー番号確認
data = kv.er()
エラー番号が返ってきます
機種の問い合わせ
data = kv.unittype()
レスポンスは以下の番号が各機種に割り当たっています
KV-8000 :57
KV-8000A :58
KV-7300 :54
KV-7500 :55
KV-3000 :51
KV-5000 :52
KV-5500 :53
KV-NC32T :128
KV-N60□□ :132
KV-N40□□ :133
KV-N24□□ :134
時刻設定
data = kv.settime()
PLCの時刻を送信元の時刻に合わせます
強制セット
data = kv.set('MR0')
引数にはデバイス種別と番号を入力します
デバイス名 | 種別 | 番号 |
---|---|---|
リレー | R | 0-199915 |
リンクリレー | B | 0-7FFF |
内部補助リレー | MR | 0-399915 |
ラッチリレー | LR | 0-99915 |
コントロールリレー | CR | 0-7915 |
タイマ | T | 0-3999 |
カウンタ | C | 0-3999 |
高速カウンタコンパレータ | CTC | 0-3 |
ワークリレー | VB | 0-F9FF |
※ 番号は機種によってサイズが変わります
強制リセット
data = kv.reset('MR0')
引数にはデバイス種別と番号を入力します
連続強制セット
data = kv.sts('MR10', 5)
引数1はデバイス種別と番号を入力します
引数2はセットする個数を入力します
連続強制リセット
data = kv.rts('MR10', 5)
引数1はデバイス種別と番号を入力します
引数2はリセットする個数を入力します
データ読み出し
data = kv.read('MR0.U')
引数1はデバイス種別と番号とデータ形式を入力します
データ形式は以下で指定します
サフィックス | データ形式 |
---|---|
.U | 10進数16ビット符号なし |
.S | 10進数16ビット符号あり |
.D | 10進数32ビット符号なし |
.L | 10進数16ビット符号あり |
.H | 16進数16ビット |
デバイス種別と番号
デバイス名 | 種別 | 番号 |
---|---|---|
リレー | R | 0-199915 |
リンクリレー | B | 0-7FFF |
内部補助リレー | MR | 0-399915 |
ラッチリレー | LR | 0-99915 |
コントロールリレー | CR | 0-7915 |
ワークリレー | VB | 0-F9FF |
データメモリ | DM | 0-65534 |
拡張データメモリ | EM | 0-65534 |
ファイルレジスタ | FM | 0-32767 |
ファイルレジスタ | ZF | 0-524287 |
リンクレジスタ | W | 0-7FFF |
テンポラリデータメモリ | TM | 0-511 |
インデックスレジスタ | Z | 1-12 |
タイマ | T | 0-3999 |
タイマ(現在値) | TC | 0-3999 |
タイマ(設定値) | TS | 0-3999 |
カウンタ | C | 0-3999 |
カウンタ(現在値) | CC | 0-3999 |
カウンタ(設定値) | CS | 0-3999 |
デジタルトリマ | AT | 0-7 |
コントロールメモリ | CM | 0-5999 |
ワークメモリ | VM | 0-50999 |
※ 番号は機種によってサイズが変わります
連続データ読み出し
data = kv.reads('MR0.S',4)
引数1はデバイス種別と番号とデータ形式を入力します
引数2は読み出す個数を入力します
データ書き込み
data = kv.write('DM0.U', '2')
引数1はデバイス種別と番号とデータ形式を入力します
引数2は書き込む値を入力します
連続データ書き込み
data = kv.writs('DM1.S', 4, '1 2 3 4')
引数1はデバイス種別と番号とデータ形式を入力します
引数2は書き込む個数を入力します
引数3にスペースで区切って書き込む値を入力します
コード
import time
from socket import *
import struct
import datetime
BUFSIZE = 4096
class kvHostLink:
addr = ()
destfins = []
srcfins = []
port = 8501
def __init__(self, host):
self.addr = host, self.port
def sendrecive(self, command):
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', self.port))
s.settimeout(2)
starttime = time.time()
s.sendto(command, self.addr)
#print("send:%r" % (command))
rcvdata = s.recv(BUFSIZE)
elapsedtime = time.time() - starttime
#print ('receive: %r\t Length=%r\telapsedtime = %sms' % (rcvdata, len(rcvdata), str(elapsedtime * 1000)))
#print()
return rcvdata
def mode(self, mode):
senddata = 'M' + mode
rcv = self.sendrecive((senddata + '\r').encode())
return rcv
def unittype(self):
rcv = self.sendrecive("?k\r".encode())
return rcv
def errclr(self):
senddata = 'ER'
rcv = self.sendrecive((senddata + '\r').encode())
return rcv
def er(self):
senddata = '?E'
rcv = self.sendrecive((senddata + '\r').encode())
return rcv
def settime(self):
dt_now = datetime.datetime.now()
senddata = 'WRT ' + str(dt_now.year)[2:]
senddata = senddata + ' ' + str(dt_now.month)
senddata = senddata + ' ' + str(dt_now.day)
senddata = senddata + ' ' + str(dt_now.hour)
senddata = senddata + ' ' + str(dt_now.minute)
senddata = senddata + ' ' + str(dt_now.second)
senddata = senddata + ' ' + dt_now.strftime('%w')
rcv = self.sendrecive((senddata + '\r').encode())
return rcv
def set(self, address):
rcv = self.sendrecive(('ST ' + address + '\r').encode())
return rcv
def reset(self, address):
rcv = self.sendrecive(('RS ' + address + '\r').encode())
return rcv
def sts(self, address, num):
rcv = self.sendrecive(('STS ' + address + ' ' + str(num) + '\r').encode())
return rcv
def rss(self, address, num):
rcv = self.sendrecive(('RSS ' + address + ' ' + str(num) + '\r').encode())
return rcv
def read(self, addresssuffix):
rcv = self.sendrecive(('RD ' + addresssuffix + '\r').encode())
return rcv
def reads(self, addresssuffix, num):
rcv = self.sendrecive(('RDS ' + addresssuffix + ' ' + str(num) + '\r').encode())
return rcv
def write(self, addresssuffix, data):
rcv = self.sendrecive(('WR ' + addresssuffix + ' ' + data + '\r').encode())
return rcv
def writs(self, addresssuffix, num, data):
rcv = self.sendrecive(('WRS ' + addresssuffix + ' ' + str(num) + ' ' + data + '\r').encode())
return rcv
kv = kvHostLink('192.168.0.31')
data = kv.mode('1')
print(data)
data = kv.er()
print(data)
data = kv.errclr()
print(data)
data = kv.unittype()
print(data)
data = kv.settime()
print(data)
data = kv.set('MR0')
print(data)
data = kv.reset('MR1')
print(data)
data = kv.sts('MR10', 5)
print(data)
data = kv.rss('MR10', 4)
print(data)
data = kv.read('DM0.U')
print(data)
data = kv.reads('DM0.S', 4)
print(data)
data = kv.write('DM0.U', '2')
print(data)
data = kv.writs('DM1.S', 4, '1 2 3 4')
print(data)