plcopen/structures.py
changeset 1313 85c167bfff93
parent 1310 3d7fa2257b24
child 1320 bb04c41cbee9
equal deleted inserted replaced
1312:250c3ae0787c 1313:85c167bfff93
    21 #You should have received a copy of the GNU General Public
    21 #You should have received a copy of the GNU General Public
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import string, os, sys, re
    25 import string, os, sys, re
       
    26 from plcopen import LoadProject
    26 
    27 
    27 LANGUAGES = ["IL","ST","FBD","LD","SFC"]
    28 LANGUAGES = ["IL","ST","FBD","LD","SFC"]
    28 
    29 
    29 LOCATIONDATATYPES = {"X" : ["BOOL"],
    30 LOCATIONDATATYPES = {"X" : ["BOOL"],
    30                      "B" : ["SINT", "USINT", "BYTE", "STRING"],
    31                      "B" : ["SINT", "USINT", "BYTE", "STRING"],
    36 
    37 
    37 #-------------------------------------------------------------------------------
    38 #-------------------------------------------------------------------------------
    38 #                        Function Block Types definitions
    39 #                        Function Block Types definitions
    39 #-------------------------------------------------------------------------------
    40 #-------------------------------------------------------------------------------
    40 
    41 
       
    42 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
       
    43 
       
    44 StdBlockLibrary = LoadProject(os.path.join(ScriptDirectory, "Standard_Function_Blocks.xml"))
       
    45 AddnlBlockLibrary = LoadProject(os.path.join(ScriptDirectory, "Additional_Function_Blocks.xml"))
       
    46 
       
    47 StdBlockComments = {
       
    48     "SR": _("SR bistable\nThe SR bistable is a latch where the Set dominates."),
       
    49     "RS": _("RS bistable\nThe RS bistable is a latch where the Reset dominates."),
       
    50     "SEMA": _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."),
       
    51     "R_TRIG": _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected."),
       
    52     "F_TRIG": _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected."),
       
    53     "CTU": _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."),
       
    54     "CTD": _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."),
       
    55     "CTUD": _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other."),
       
    56     "TP": _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."),
       
    57     "TON": _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true."),
       
    58     "TOF": _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."),
       
    59     "RTC": _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on."),
       
    60     "INTEGRAL": _("Integral\nThe integral function block integrates the value of input XIN over time."),
       
    61     "DERIVATIVE": _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."),
       
    62     "PID": _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."),
       
    63     "RAMP": _("Ramp\nThe RAMP function block is modelled on example given in the standard."),
       
    64     "HYSTERESIS": _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."),
       
    65 }
       
    66 
       
    67 for block_type in ["CTU", "CTD", "CTUD"]:
       
    68     for return_type in ["DINT", "LINT", "UDINT", "ULINT"]:
       
    69         StdBlockComments["%s_%s" % (block_type, return_type)] = StdBlockComments[block_type]
       
    70 
       
    71 def GetBlockInfos(pou):
       
    72     infos = pou.getblockInfos()
       
    73     infos["comment"] = StdBlockComments[infos["name"]]
       
    74     infos["inputs"] = [
       
    75         (var_name, var_type, "rising")
       
    76         if var_name in ["CU", "CD"]
       
    77         else (var_name, var_type, var_modifier)
       
    78         for var_name, var_type, var_modifier in infos["inputs"]]
       
    79     return infos
    41 
    80 
    42 """
    81 """
    43 Ordored list of common Function Blocks defined in the IEC 61131-3
    82 Ordored list of common Function Blocks defined in the IEC 61131-3
    44 Each block have this attributes:
    83 Each block have this attributes:
    45     - "name" : The block name
    84     - "name" : The block name
    54     - The data type
    93     - The data type
    55     - The default modifier which can be "none", "negated", "rising" or "falling"
    94     - The default modifier which can be "none", "negated", "rising" or "falling"
    56 """
    95 """
    57 
    96 
    58 StdBlckLst = [{"name" : _("Standard function blocks"), "list":
    97 StdBlckLst = [{"name" : _("Standard function blocks"), "list":
    59                [{"name" : "SR", "type" : "functionBlock", "extensible" : False, 
    98                [GetBlockInfos(pou) for pou in StdBlockLibrary.getpous()]},
    60                     "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], 
       
    61                     "outputs" : [("Q1","BOOL","none")],
       
    62                     "comment" : _("SR bistable\nThe SR bistable is a latch where the Set dominates.")},
       
    63                 {"name" : "RS", "type" : "functionBlock", "extensible" : False, 
       
    64                     "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], 
       
    65                     "outputs" : [("Q1","BOOL","none")],
       
    66                     "comment" : _("RS bistable\nThe RS bistable is a latch where the Reset dominates.")},
       
    67                 {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, 
       
    68                     "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], 
       
    69                     "outputs" : [("BUSY","BOOL","none")],
       
    70                     "comment" : _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources.")},
       
    71                 {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, 
       
    72                     "inputs" : [("CLK","BOOL","none")], 
       
    73                     "outputs" : [("Q","BOOL","none")],
       
    74                     "comment" : _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected.")},
       
    75                 {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, 
       
    76                     "inputs" : [("CLK","BOOL","none")], 
       
    77                     "outputs" : [("Q","BOOL","none")],
       
    78                     "comment" : _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected.")},
       
    79                 {"name" : "CTU", "type" : "functionBlock", "extensible" : False, 
       
    80                     "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], 
       
    81                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
       
    82                     "comment" : _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value.")},
       
    83                 {"name" : "CTD", "type" : "functionBlock", "extensible" : False, 
       
    84                     "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], 
       
    85                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
       
    86                     "comment" : _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value.")},
       
    87                 {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, 
       
    88                     "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], 
       
    89                     "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")],
       
    90                     "comment" : _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other.")},
       
    91                 {"name" : "TP", "type" : "functionBlock", "extensible" : False, 
       
    92                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
       
    93                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
       
    94                     "comment" : _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration.")},
       
    95                 {"name" : "TON", "type" : "functionBlock", "extensible" : False, 
       
    96                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
       
    97                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
       
    98                     "comment" : _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true.")},
       
    99                 {"name" : "TOF", "type" : "functionBlock", "extensible" : False, 
       
   100                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
       
   101                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
       
   102                     "comment" : _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false.")},
       
   103                 ]},
       
   104               {"name" : _("Additional function blocks"), "list":
    99               {"name" : _("Additional function blocks"), "list":
   105                [{"name" : "RTC", "type" : "functionBlock", "extensible" : False, 
   100                [GetBlockInfos(pou) for pou in AddnlBlockLibrary.getpous()]},
   106                     "inputs" : [("IN","BOOL","none"),("PDT","DATE_AND_TIME","none")], 
       
   107                     "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")],
       
   108                     "comment" : _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on.")},
       
   109                 {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, 
       
   110                     "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], 
       
   111                     "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")],
       
   112                     "comment" : _("Integral\nThe integral function block integrates the value of input XIN over time.")},
       
   113                 {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, 
       
   114                     "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], 
       
   115                     "outputs" : [("XOUT","REAL","none")],
       
   116                     "comment" : _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN.")},
       
   117                 {"name" : "PID", "type" : "functionBlock", "extensible" : False, 
       
   118                     "inputs" : [("AUTO","BOOL","none"),("PV","REAL","none"),("SP","REAL","none"),("X0","REAL","none"),("KP","REAL","none"),("TR","REAL","none"),("TD","REAL","none"),("CYCLE","TIME","none")], 
       
   119                     "outputs" : [("XOUT","REAL","none")],
       
   120                     "comment" : _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control.")},
       
   121                 {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, 
       
   122                     "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none")], 
       
   123                     "outputs" : [("BUSY","BOOL","none"),("XOUT","REAL","none")],
       
   124                     "comment" : _("Ramp\nThe RAMP function block is modelled on example given in the standard.")},
       
   125                 {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, 
       
   126                     "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], 
       
   127                     "outputs" : [("Q","BOOL","none")],
       
   128                     "comment" : _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2.")},
       
   129 ##                {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, 
       
   130 ##                    "inputs" : [("PV1","REAL","none"),("PV2","REAL","none"),("RATIO","REAL","none"),("TIMON","TIME","none"),("TIMOFF","TIME","none"),("TOLERANCE","BOOL","none"),("RESET","BOOL","none"),("CYCLE","TIME","none")], 
       
   131 ##                    "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")],
       
   132 ##                    "comment" : _("Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2.")}
       
   133                 ]},
       
   134              ]
   101              ]
   135 
   102 
   136 
   103 
   137 #-------------------------------------------------------------------------------
   104 #-------------------------------------------------------------------------------
   138 #                           Data Types definitions
   105 #                           Data Types definitions
   444             else:
   411             else:
   445                 raise "First function must be in a category"
   412                 raise "First function must be in a category"
   446     
   413     
   447     return Standard_Functions_Decl
   414     return Standard_Functions_Decl
   448 
   415 
   449 std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(os.path.split(__file__)[0],"iec_std.csv"))))#, True)
   416 std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(ScriptDirectory,"iec_std.csv"))))#, True)
   450 
   417 
   451 StdBlckLst.extend(std_decl)
   418 StdBlckLst.extend(std_decl)
   452 
   419 
   453 # Dictionary to speedup block type fetching by name
   420 # Dictionary to speedup block type fetching by name
   454 StdBlckDct = {}
   421 StdBlckDct = {}
   456 for section in StdBlckLst:
   423 for section in StdBlckLst:
   457     for desc in section["list"]:
   424     for desc in section["list"]:
   458         words = desc["comment"].split('"')
   425         words = desc["comment"].split('"')
   459         if len(words) > 1:
   426         if len(words) > 1:
   460             desc["comment"] = words[1]
   427             desc["comment"] = words[1]
   461         desc["usage"] = (
   428         desc["usage"] = ("\n (%s) => (%s)" % 
   462             "\n (" +
   429             (", ".join(["%s:%s" % (input[1], input[0]) 
   463             str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["inputs"]]).strip("[]").replace("'",'') +
   430                         for input in desc["inputs"]]),
   464             " ) => (" +
   431              ", ".join(["%s:%s" % (output[1], output[0]) 
   465             str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["outputs"]]).strip("[]").replace("'",'') +
   432                         for output in desc["outputs"]])))
   466             " )")
       
   467         BlkLst = StdBlckDct.setdefault(desc["name"],[])
   433         BlkLst = StdBlckDct.setdefault(desc["name"],[])
   468         BlkLst.append((section["name"], desc))
   434         BlkLst.append((section["name"], desc))
   469 
   435 
   470 #-------------------------------------------------------------------------------
   436 #-------------------------------------------------------------------------------
   471 #                            Languages Keywords
   437 #                            Languages Keywords