# HG changeset patch
# User Laurent Bessard
# Date 1378847458 -7200
# Node ID 85c167bfff935f7b1077550f51a7eb8e1e3cc136
# Parent 250c3ae0787c16b208c19429a44262c5a7db93c2
Replaced standard function blocks library definition from dictionary to plcopen xml files
diff -r 250c3ae0787c -r 85c167bfff93 PLCControler.py
--- a/PLCControler.py Tue Sep 10 10:37:42 2013 +0200
+++ b/PLCControler.py Tue Sep 10 23:10:58 2013 +0200
@@ -30,7 +30,7 @@
import datetime
from time import localtime
-from plcopen import*
+from plcopen import *
from graphics.GraphicCommons import *
from PLCGenerator import *
@@ -1297,14 +1297,16 @@
return variables
# Add a global var to configuration to configuration
- def AddConfigurationGlobalVar(self, config_name, type, var_name,
+ def AddConfigurationGlobalVar(self, config_name, var_type, var_name,
location="", description=""):
if self.Project is not None:
# Found the configuration corresponding to name
configuration = self.Project.getconfiguration(config_name)
if configuration is not None:
# Set configuration global vars
- configuration.addglobalVar(type, var_name, location, description)
+ configuration.addglobalVar(
+ self.GetVarTypeObject(var_type),
+ var_name, location, description)
# Replace the configuration globalvars by those given
def SetConfigurationGlobalVars(self, name, vars):
@@ -1635,6 +1637,10 @@
result = project.getpou(typename)
if result is not None:
return result
+ for standardlibrary in [StdBlockLibrary, AddnlBlockLibrary]:
+ result = standardlibrary.getpou(typename)
+ if result is not None:
+ return result
for confnodetype in self.ConfNodeTypes:
result = confnodetype["types"].getpou(typename)
if result is not None:
@@ -2410,21 +2416,36 @@
connection.setconnectionParameter(idx, None)
idx += 1
- def AddEditedElementPouVar(self, tagname, type, name, location="", description=""):
+ def GetVarTypeObject(self, var_type):
+ var_type_obj = PLCOpenParser.CreateElement("type", "variable")
+ if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
+ var_type_obj.setcontent(PLCOpenParser.CreateElement(
+ var_type.lower() if var_type in ["STRING", "WSTRING"]
+ else var_type, "dataType"))
+ else:
+ derived_type = PLCOpenParser.CreateElement("derived", "dataType")
+ derived_type.setname(var_type)
+ var_type_obj.setcontent(derived_type)
+ return var_type_obj
+
+ def AddEditedElementPouVar(self, tagname, var_type, name, location="", description=""):
if self.Project is not None:
words = tagname.split("::")
if words[0] in ['P', 'T', 'A']:
pou = self.Project.getpou(words[1])
if pou is not None:
- pou.addpouLocalVar(type, name, location, description)
-
- def AddEditedElementPouExternalVar(self, tagname, type, name):
+ pou.addpouLocalVar(
+ self.GetVarTypeObject(var_type),
+ name, location, description)
+
+ def AddEditedElementPouExternalVar(self, tagname, var_type, name):
if self.Project is not None:
words = tagname.split("::")
if words[0] in ['P', 'T', 'A']:
pou = self.Project.getpou(words[1])
if pou is not None:
- pou.addpouExternalVar(type, name)
+ pou.addpouExternalVar(
+ self.GetVarTypeObject(var_type), name)
def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name):
if self.Project is not None:
diff -r 250c3ae0787c -r 85c167bfff93 plcopen/Additional_Function_Blocks.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/Additional_Function_Blocks.xml Tue Sep 10 23:10:58 2013 +0200
@@ -0,0 +1,522 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,CURRENT_TIME,__CURRENT_TIME)}
+
+ IF IN
+ THEN
+ IF NOT PREV_IN
+ THEN
+ OFFSET := PDT - CURRENT_TIME;
+ END_IF;
+
+ (* PDT + time since PDT was loaded *)
+ CDT := CURRENT_TIME + OFFSET;
+ ELSE
+ CDT := CURRENT_TIME;
+ END_IF;
+
+ Q := IN;
+ PREV_IN := IN;
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = TR THEN
+ BUSY := 0;
+ XOUT := X1;
+ ELSE XOUT := XI + (X1-XI) * TIME_TO_REAL(T)
+ / TIME_TO_REAL(TR);
+ T := T + CYCLE;
+ END_IF;
+ELSE
+ XOUT := X0;
+ XI := X0;
+ T := T#0s;
+END_IF;]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (XIN2 + EPS) THEN
+ Q := 1;
+END_IF;]]>
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 250c3ae0787c -r 85c167bfff93 plcopen/Standard_Function_Blocks.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/Standard_Function_Blocks.xml Tue Sep 10 23:10:58 2013 +0200
@@ -0,0 +1,1469 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = PV);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = PV);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = PV);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = PV);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = PV);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+END_IF;
+Q := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+END_IF;
+Q := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+END_IF;
+Q := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+END_IF;
+Q := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+END_IF;
+Q := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+ END_IF;
+ END_IF;
+END_IF;
+QU := (CV >= PV);
+QD := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+ END_IF;
+ END_IF;
+END_IF;
+QU := (CV >= PV);
+QD := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+ END_IF;
+ END_IF;
+END_IF;
+QU := (CV >= PV);
+QD := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+ END_IF;
+ END_IF;
+END_IF;
+QU := (CV >= PV);
+QD := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0)
+ THEN CV := CV-1;
+ END_IF;
+ END_IF;
+END_IF;
+QU := (CV >= PV);
+QD := (CV <= 0);]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,CURRENT_TIME,__CURRENT_TIME)}
+
+IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *)
+THEN
+ (* start timer... *)
+ STATE := 1;
+ Q := TRUE;
+ START_TIME := CURRENT_TIME;
+
+ELSIF (STATE = 1)
+THEN
+ IF ((START_TIME + PT) <= CURRENT_TIME)
+ THEN
+ STATE := 2;
+ Q := FALSE;
+ ET := PT;
+ ELSE
+ ET := CURRENT_TIME - START_TIME;
+ END_IF;
+END_IF;
+
+IF ((STATE = 2) AND NOT(IN))
+THEN
+ ET := T#0s;
+ STATE := 0;
+END_IF;
+
+PREV_IN := IN;
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,CURRENT_TIME,__CURRENT_TIME)}
+
+IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *)
+THEN
+ (* start timer... *)
+ STATE := 1;
+ Q := FALSE;
+ START_TIME := CURRENT_TIME;
+
+ELSE
+ (* STATE is 1 or 2 !! *)
+ IF (NOT(IN))
+ THEN
+ ET := T#0s;
+ Q := FALSE;
+ STATE := 0;
+
+ ELSIF (STATE = 1)
+ THEN
+ IF ((START_TIME + PT) <= CURRENT_TIME)
+ THEN
+ STATE := 2;
+ Q := TRUE;
+ ET := PT;
+ ELSE
+ ET := CURRENT_TIME - START_TIME;
+ END_IF;
+ END_IF;
+
+END_IF;
+
+PREV_IN := IN;
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,CURRENT_TIME,__CURRENT_TIME)}
+
+IF ((STATE = 0) AND PREV_IN AND NOT(IN)) (* found falling edge on IN *)
+THEN
+ (* start timer... *)
+ STATE := 1;
+ START_TIME := CURRENT_TIME;
+
+ELSE
+ (* STATE is 1 or 2 !! *)
+ IF (IN)
+ THEN
+ ET := T#0s;
+ STATE := 0;
+
+ ELSIF (STATE = 1)
+ THEN
+ IF ((START_TIME + PT) <= CURRENT_TIME)
+ THEN
+ STATE := 2;
+ ET := PT;
+ ELSE
+ ET := CURRENT_TIME - START_TIME;
+ END_IF;
+ END_IF;
+
+END_IF;
+
+Q := IN OR (STATE = 1);
+PREV_IN := IN;
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 250c3ae0787c -r 85c167bfff93 plcopen/plcopen.py
--- a/plcopen/plcopen.py Tue Sep 10 10:37:42 2013 +0200
+++ b/plcopen/plcopen.py Tue Sep 10 23:10:58 2013 +0200
@@ -23,7 +23,6 @@
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from xmlclass import *
-from structures import *
from types import *
import os, re
from lxml import etree
@@ -296,16 +295,13 @@
def setcontentHeader(self, contentheader):
contentheader_obj = self.contentHeader
for attr, value in contentheader.iteritems():
- if attr == "projectName":
- contentheader_obj.setname(value)
- elif attr == "projectVersion":
- contentheader_obj.setversion(value)
- elif attr == "authorName":
- contentheader_obj.setauthor(value)
- elif attr == "pageSize":
- contentheader_obj.setpageSize(*contentheader["pageSize"])
- elif attr == "scaling":
- contentheader_obj.setscaling(contentheader["scaling"])
+ func = {"projectName": contentheader_obj.setname,
+ "projectVersion": contentheader_obj.setversion,
+ "authorName": contentheader_obj.setauthor,
+ "pageSize": lambda v: contentheader_obj.setpageSize(*v),
+ "scaling": contentheader_obj.setscaling}.get(attr)
+ if func is not None:
+ func(value)
elif attr in ["modificationDateTime", "organization", "language"]:
setattr(contentheader_obj, attr, value)
setattr(cls, "setcontentHeader", setcontentHeader)
@@ -607,16 +603,7 @@
globalvars.append(PLCOpenParser.CreateElement("varList"))
var = PLCOpenParser.CreateElement("variable", "varListPlain")
var.setname(name)
- var_type_obj = PLCOpenParser.CreateElement("dataType")
- if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
- var_type_obj.setcontent(PLCOpenParser.CreateElement(
- var_type.lower() if var_type in ["STRING", "WSTRING"]
- else vartype, "dataType"))
- else:
- derived_type = PLCOpenParser.CreateElement("derived", "dataType")
- derived_type.setname(var_type)
- var_type_obj.setcontent(derived_type)
- var.settype(var_type_obj)
+ var.settype(var_type)
if location != "":
var.setaddress(location)
if description != "":
@@ -1164,16 +1151,7 @@
content[-1].addnext(varlist)
var = PLCOpenParser.CreateElement("variable", "varListPlain")
var.setname(name)
- var_type_obj = PLCOpenParser.CreateElement("type", "variable")
- if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
- var_type_obj.setcontent(PLCOpenParser.CreateElement(
- var_type.lower() if var_type in ["STRING", "WSTRING"]
- else var_type, "dataType"))
- else:
- derived_type = PLCOpenParser.CreateElement("derived", "dataType")
- derived_type.setname(var_type)
- var_type_obj.setcontent(derived_type)
- var.settype(var_type_obj)
+ var.settype(var_type)
if location != "":
var.setaddress(location)
if description != "":
diff -r 250c3ae0787c -r 85c167bfff93 plcopen/structures.py
--- a/plcopen/structures.py Tue Sep 10 10:37:42 2013 +0200
+++ b/plcopen/structures.py Tue Sep 10 23:10:58 2013 +0200
@@ -23,6 +23,7 @@
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import string, os, sys, re
+from plcopen import LoadProject
LANGUAGES = ["IL","ST","FBD","LD","SFC"]
@@ -38,6 +39,44 @@
# Function Block Types definitions
#-------------------------------------------------------------------------------
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
+
+StdBlockLibrary = LoadProject(os.path.join(ScriptDirectory, "Standard_Function_Blocks.xml"))
+AddnlBlockLibrary = LoadProject(os.path.join(ScriptDirectory, "Additional_Function_Blocks.xml"))
+
+StdBlockComments = {
+ "SR": _("SR bistable\nThe SR bistable is a latch where the Set dominates."),
+ "RS": _("RS bistable\nThe RS bistable is a latch where the Reset dominates."),
+ "SEMA": _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."),
+ "R_TRIG": _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected."),
+ "F_TRIG": _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected."),
+ "CTU": _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."),
+ "CTD": _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."),
+ "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."),
+ "TP": _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."),
+ "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."),
+ "TOF": _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."),
+ "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."),
+ "INTEGRAL": _("Integral\nThe integral function block integrates the value of input XIN over time."),
+ "DERIVATIVE": _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."),
+ "PID": _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."),
+ "RAMP": _("Ramp\nThe RAMP function block is modelled on example given in the standard."),
+ "HYSTERESIS": _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."),
+}
+
+for block_type in ["CTU", "CTD", "CTUD"]:
+ for return_type in ["DINT", "LINT", "UDINT", "ULINT"]:
+ StdBlockComments["%s_%s" % (block_type, return_type)] = StdBlockComments[block_type]
+
+def GetBlockInfos(pou):
+ infos = pou.getblockInfos()
+ infos["comment"] = StdBlockComments[infos["name"]]
+ infos["inputs"] = [
+ (var_name, var_type, "rising")
+ if var_name in ["CU", "CD"]
+ else (var_name, var_type, var_modifier)
+ for var_name, var_type, var_modifier in infos["inputs"]]
+ return infos
"""
Ordored list of common Function Blocks defined in the IEC 61131-3
@@ -56,81 +95,9 @@
"""
StdBlckLst = [{"name" : _("Standard function blocks"), "list":
- [{"name" : "SR", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("S1","BOOL","none"),("R","BOOL","none")],
- "outputs" : [("Q1","BOOL","none")],
- "comment" : _("SR bistable\nThe SR bistable is a latch where the Set dominates.")},
- {"name" : "RS", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("S","BOOL","none"),("R1","BOOL","none")],
- "outputs" : [("Q1","BOOL","none")],
- "comment" : _("RS bistable\nThe RS bistable is a latch where the Reset dominates.")},
- {"name" : "SEMA", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")],
- "outputs" : [("BUSY","BOOL","none")],
- "comment" : _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources.")},
- {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CLK","BOOL","none")],
- "outputs" : [("Q","BOOL","none")],
- "comment" : _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected.")},
- {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CLK","BOOL","none")],
- "outputs" : [("Q","BOOL","none")],
- "comment" : _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected.")},
- {"name" : "CTU", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")],
- "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
- "comment" : _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value.")},
- {"name" : "CTD", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")],
- "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
- "comment" : _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value.")},
- {"name" : "CTUD", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")],
- "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")],
- "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.")},
- {"name" : "TP", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("IN","BOOL","none"),("PT","TIME","none")],
- "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
- "comment" : _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration.")},
- {"name" : "TON", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("IN","BOOL","none"),("PT","TIME","none")],
- "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
- "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.")},
- {"name" : "TOF", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("IN","BOOL","none"),("PT","TIME","none")],
- "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
- "comment" : _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false.")},
- ]},
+ [GetBlockInfos(pou) for pou in StdBlockLibrary.getpous()]},
{"name" : _("Additional function blocks"), "list":
- [{"name" : "RTC", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("IN","BOOL","none"),("PDT","DATE_AND_TIME","none")],
- "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")],
- "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.")},
- {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")],
- "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")],
- "comment" : _("Integral\nThe integral function block integrates the value of input XIN over time.")},
- {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")],
- "outputs" : [("XOUT","REAL","none")],
- "comment" : _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN.")},
- {"name" : "PID", "type" : "functionBlock", "extensible" : False,
- "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")],
- "outputs" : [("XOUT","REAL","none")],
- "comment" : _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control.")},
- {"name" : "RAMP", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none")],
- "outputs" : [("BUSY","BOOL","none"),("XOUT","REAL","none")],
- "comment" : _("Ramp\nThe RAMP function block is modelled on example given in the standard.")},
- {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False,
- "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")],
- "outputs" : [("Q","BOOL","none")],
- "comment" : _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2.")},
-## {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False,
-## "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")],
-## "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")],
-## "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.")}
- ]},
+ [GetBlockInfos(pou) for pou in AddnlBlockLibrary.getpous()]},
]
@@ -446,7 +413,7 @@
return Standard_Functions_Decl
-std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(os.path.split(__file__)[0],"iec_std.csv"))))#, True)
+std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(ScriptDirectory,"iec_std.csv"))))#, True)
StdBlckLst.extend(std_decl)
@@ -458,12 +425,11 @@
words = desc["comment"].split('"')
if len(words) > 1:
desc["comment"] = words[1]
- desc["usage"] = (
- "\n (" +
- str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["inputs"]]).strip("[]").replace("'",'') +
- " ) => (" +
- str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["outputs"]]).strip("[]").replace("'",'') +
- " )")
+ desc["usage"] = ("\n (%s) => (%s)" %
+ (", ".join(["%s:%s" % (input[1], input[0])
+ for input in desc["inputs"]]),
+ ", ".join(["%s:%s" % (output[1], output[0])
+ for output in desc["outputs"]])))
BlkLst = StdBlckDct.setdefault(desc["name"],[])
BlkLst.append((section["name"], desc))