各位大大好, 小弟目前需要使用python讀取/控制 Omron PLC,
在讀取的時候,都正常能夠取到值,
但在寫入的時候出現以下狀況:
修改點位(D0001)為100,數值確實有變動,但是點位(D0002、D0003)同時被更改為0
補充: 我目前在python利用ctype轉換型態,再利用pythonnet呼叫C#的開源庫,將數值傳送至C#的函式。
// C#的實現方法如下
// omronConn的部份為開源庫提供函式
// 已知以下的代碼能夠正常寫入
// ...
double double_value = short.Parse(value);
omronConn.Write(recipe, double_value);
# Python的實現方法如下
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Python 3.7
# pip install pythonnet
# DLL 為 C#
import ctypes
import re
import sys
import clr
try:
HSL = clr.AddReference(
r"src\modules\OmronSDK\omron\lib\net451\HslCommunication"
)
hsl_location = HSL.Location
SYSTEM = clr.AddReference(
"System"
)
system_location = SYSTEM.Location
print("\n")
print("Load library %s" % hsl_location)
print("Load library %s" % system_location)
print("\n")
except Exception:
raise
class OmronSDK:
from HslCommunication.Profinet.Omron import OmronFinsNet
from System import Convert, Int32
def __init__(self, local_ip: str, plc_ip: str, plc_port: int = 9600) -> None:
self.local_ip = local_ip
self.plc_ip = plc_ip
self.plc_port = plc_port
self.conn = None
@classmethod
def Valid_IPv4_Address(self, ip) -> bool:
"""Valid_IPv4_Address IP驗證
Args:
ip (_type_): IP Address
Returns:
bool: True or False
"""
m = re.match(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ip)
return bool(m) and all(map(lambda n: 0 <= int(n) <= 255, m.groups()))
def Connect(self) -> tuple:
"""Connect
Raises:
ValueError: IP 輸入錯誤
Returns:
tuple: 返回結果
"""
self.suffix_local_ip = ""
self.suffix_plc_ip = ""
try:
if self.Valid_IPv4_Address(self.local_ip) and \
self.Valid_IPv4_Address(self.plc_ip):
self.suffix_local_ip = self.local_ip.split(".")[-1]
self.suffix_plc_ip = self.plc_ip.split(".")[-1]
else:
raise ValueError("Input IP type error !!!")
except Exception:
raise
try:
if self.conn is None:
omron = OmronSDK.OmronFinsNet(
self.plc_ip,
OmronSDK.Int32(self.plc_port)
)
# Server IP 後綴尾碼
omron.SA1 = OmronSDK.Convert.ToByte(self.suffix_local_ip)
# PLC IP 後綴尾碼
omron.DA1 = OmronSDK.Convert.ToByte(self.suffix_plc_ip)
# 固定為0
omron.DA2 = 0x00
result = omron.ConnectServer()
if result is None:
return (result, "Omron connection faild.")
elif not result.IsSuccess:
return (None, result.Message)
elif result.IsSuccess:
self.conn = omron
return (result.Message, "CNC connection successfully.")
except Exception as err_msg:
raise
def Disconnect(self) -> object:
"""Disconnect
Returns:
object: 返回結果
"""
return self.conn.ConnectClose()
def Reader(self, typer: str, recipe: str) -> tuple:
try:
typer = typer.upper()
value = ""
if typer == "BOOL":
value = self.conn.ReadBool(recipe).Content
elif typer == "SHORT":
value = self.conn.ReadInt16(recipe).Content
elif typer == "USHORT":
value = self.conn.ReadUInt16(recipe).Content
elif typer == "INT":
value = self.conn.ReadInt32(recipe).Content
elif typer == "UINT":
value = self.conn.ReadUInt32(recipe).Content
elif typer == "FLOAT":
value = self.conn.ReadFloat(recipe).Content
elif typer == "LONG":
value = self.conn.ReadInt64(recipe).Content
elif typer == "ULONG":
value = self.conn.ReadUInt64(recipe).Content
elif typer == "DOUBLE":
value = self.conn.ReadDouble(recipe).Content
elif typer == "STRING":
# ASCII
value = self.conn.ReadString(recipe, 5).Content
return (typer, value)
except Exception:
raise
def Writer(self, typer: str, recipe: str, value):
# 此部分能夠正常更改數值,但會有多個點位被同時更改的問題,且都為0
try:
typer = typer.upper()
if typer == "BYTES":
self.conn.Write(recipe, str.encode(value))
elif typer == "SHORT":
self.conn.Write(recipe, (ctypes.c_ushort(int(value))).value)
elif typer == "FLOAT":
self.conn.Write(recipe, ctypes.c_float(float(value)))
elif typer == "LONG":
self.conn.Write(recipe, ctypes.c_long(int(value)))
elif typer == "ULONG":
self.conn.Write(recipe, ctypes.c_ulong(int(value)))
elif typer == "DOUBLE":
self.conn.Write(recipe, ctypes.c_double(float(value)).value)
elif typer == "STRING":
# ASCII
self.conn.Write(recipe, str(value))
except Exception as err_msg:
pass
def Testing():
import datetime
import logging
import os
import platform
from ctypes import byref, windll, wintypes
while True:
try:
print("----- Press [quit(q)]/[Ctrl-c] to exit -----")
print("\n")
plc_ip = '10.30.99.199'
plc_port = '9600'
local_ip = '10.30.99.21'
if not OmronSDK.Valid_IPv4_Address(plc_ip) and \
not OmronSDK.Valid_IPv4_Address(local_ip):
continue
if plc_ip == "q" or plc_ip == "quit":
sys.exit(0)
omron = OmronSDK(
local_ip=local_ip,
plc_ip=plc_ip,
plc_port=plc_port
)
conn = omron.Connect()
use_function = input("Select function w or r: ")
if use_function == 'w':
while True and conn[0] == '成功':
try:
print("\n")
typer = input(
"Input recipe type [BYTES SHORT USHORT UINT FLOAT LONG ULONG DOUBLE STRING]: ")
recipe = input("Input recipe code: ")
recipe_value = input("Input recipe value: ")
if typer == "q" or recipe == "quit":
sys.exit(0)
writer = omron.Writer(
typer=typer,
recipe=recipe,
value=recipe_value
)
logger.info(writer)
except KeyboardInterrupt:
break
except Exception:
raise
if use_function == 'r':
while True and conn[0] == '成功':
try:
print("\n")
typer = input(
"Input recipe type [BOOL SHORT USHORT INT UINT FLOAT LONG ULONG DOUBLE STRING]: ")
recipe = input("Input recipe code: ")
if typer == "q" or recipe == "quit":
sys.exit(0)
reader = omron.Reader(
typer=typer,
recipe=recipe
)
logger.info(reader)
except KeyboardInterrupt:
break
except Exception:
raise
except KeyboardInterrupt:
omron.Disconnect()
sys.exit(0)
except Exception:
raise
if __name__ == "__main__":
Testing()
小弟目前在懷疑是否是轉換時型態有誤...
試了很久,網上也不太有資料...
請各位大大指點一些道路,小弟感激不盡。