iT邦幫忙

0

python 操控 omron PLC [已解決]

  • 分享至 

  • xImage

各位大大好, 小弟目前需要使用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()

小弟目前在懷疑是否是轉換時型態有誤...
試了很久,網上也不太有資料...
請各位大大指點一些道路,小弟感激不盡。

franx0722 iT邦新手 2 級 ‧ 2022-07-25 16:56:19 檢舉
沒代碼, 問神比較快.
回@franx0722大大,已補上,再請您協助,謝謝。
已解決,謝謝
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友回答

立即登入回答