--- a/etherlab/etherlab.py Fri Oct 19 16:37:54 2012 +0200
+++ b/etherlab/etherlab.py Thu Oct 25 19:55:02 2012 +0200
@@ -5,6 +5,7 @@
import wx
from xmlclass import *
+from POULibrary import POULibrary
from ConfigTreeNode import ConfigTreeNode
from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
from ConfigEditor import NodeEditor, CIA402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
@@ -56,6 +57,31 @@
"""
#--------------------------------------------------
+# Etherlab Specific Blocks Library
+#--------------------------------------------------
+
+def GetLocalPath(filename):
+ return os.path.join(os.path.split(__file__)[0], filename)
+
+class EtherlabLibrary(POULibrary):
+ def GetLibraryPath(self):
+ return GetLocalPath("pous.xml")
+
+ def Generate_C(self, buildpath, varlist, IECCFLAGS):
+ etherlab_ext_file = open(GetLocalPath("etherlab_ext.c"), 'r')
+ etherlab_ext_code = etherlab_ext_file.read()
+ etherlab_ext_file.close()
+
+ Gen_etherlabfile_path = os.path.join(buildpath, "etherlab_ext.c")
+ ethelabfile = open(Gen_etherlabfile_path,'w')
+ ethelabfile.write(etherlab_ext_code)
+ ethelabfile.close()
+
+ runtimefile_path = os.path.join(os.path.split(__file__)[0], "runtime_etherlab.py")
+ return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "",
+ ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py"))))
+
+#--------------------------------------------------
# Ethercat Node
#--------------------------------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/etherlab_ext.c Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,42 @@
+#include "iec_types_all.h"
+
+#define FREE 0
+#define ACQUIRED 1
+#define ANSWERED 2
+
+long SDOLock = FREE;
+extern long AtomicCompareExchange(long* atomicvar,long compared, long exchange);
+
+int AcquireSDOLock() {
+ return AtomicCompareExchange(&SDOLock, FREE, ACQUIRED) == FREE;
+}
+
+void SDOAnswered() {
+ AtomicCompareExchange(&SDOLock, ACQUIRED, ANSWERED);
+}
+
+int HasAnswer() {
+ return SDOLock == ANSWERED;
+}
+
+void ReleaseSDOLock() {
+ AtomicCompareExchange(&SDOLock, ANSWERED, FREE);
+}
+
+int __init_etherlab_ext()
+{
+ SDOLock = FREE;
+ return 0;
+}
+
+void __cleanup_etherlab_ext()
+{
+}
+
+void __retrieve_etherlab_ext()
+{
+}
+
+void __publish_etherlab_ext()
+{
+}
--- a/etherlab/extension.py Fri Oct 19 16:37:54 2012 +0200
+++ b/etherlab/extension.py Thu Oct 25 19:55:02 2012 +0200
@@ -1,5 +1,12 @@
import features
+def GetEtherLabLibClass():
+ from etherlab import EtherlabLibrary
+ return EtherlabLibrary
+
+features.libraries.append(
+ ('Etherlab', GetEtherLabLibClass))
+
def GetEtherLabClass():
from etherlab import RootClass
return RootClass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/pous.xml Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.plcopen.org/xml/tc6.xsd"
+ xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml">
+ <fileHeader companyName="EtherlabMaster"
+ productName="EtherlabMaster"
+ productVersion="1"
+ creationDateTime="2012-10-22T12:12:45"/>
+ <contentHeader name="EtherlabMaster SDO Blocks"
+ modificationDateTime="2012-10-25T19:53:33">
+ <coordinateInfo>
+ <fbd>
+ <scaling x="0" y="0"/>
+ </fbd>
+ <ld>
+ <scaling x="0" y="0"/>
+ </ld>
+ <sfc>
+ <scaling x="0" y="0"/>
+ </sfc>
+ </coordinateInfo>
+ </contentHeader>
+ <types>
+ <dataTypes/>
+ <pous>
+ <pou name="EtherLabSDOUpload" pouType="functionBlock">
+ <interface>
+ <inputVars>
+ <variable name="EXECUTE">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="POS">
+ <type>
+ <INT/>
+ </type>
+ </variable>
+ <variable name="INDEX">
+ <type>
+ <UINT/>
+ </type>
+ </variable>
+ <variable name="SUBINDEX">
+ <type>
+ <USINT/>
+ </type>
+ </variable>
+ <variable name="VARTYPE">
+ <type>
+ <string/>
+ </type>
+ </variable>
+ </inputVars>
+ <outputVars>
+ <variable name="ACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="VALID">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="VALUE">
+ <type>
+ <string/>
+ </type>
+ </variable>
+ </outputVars>
+ <localVars>
+ <variable name="PY0">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ <variable name="PY1">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ <variable name="EXECUTE0">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="STATE">
+ <type>
+ <INT/>
+ </type>
+ <initialValue>
+ <simpleValue value="0"/>
+ </initialValue>
+ </variable>
+ </localVars>
+ </interface>
+ <body>
+ <ST>
+<![CDATA[{extern int AcquireSDOLock();}
+{extern int HasAnswer();}
+{extern void ReleaseSDOLock();}
+CASE STATE OF
+ 0:
+ IF EXECUTE AND NOT EXECUTE0 THEN
+ STATE := 1;
+ ACK := 0;
+ VALID := 0;
+ VALUE := 'None';
+ END_IF;
+ 1:
+ {if (AcquireSDOLock()) __SET_VAR(data__->,STATE, 2)}
+ 2:
+ IF PY0.ACK THEN
+ STATE := 3;
+ END_IF;
+ 3:
+ {if (HasAnswer()) __SET_VAR(data__->,STATE, 4)}
+ 4:
+ IF PY1.ACK THEN
+ ACK := 1;
+ VALUE := PY1.RESULT;
+ VALID := NE(VALUE, 'None');
+ STATE := 0;
+ {ReleaseSDOLock();}
+ END_IF;
+ELSE
+ STATE := 0;
+END_CASE;
+
+EXECUTE0 := EXECUTE;
+PY0(TRIG := STATE = 2,
+ CODE := CONCAT('EthercatSDOUpload(',
+ INT_TO_STRING(POS),
+ ',',
+ UINT_TO_STRING(INDEX),
+ ',',
+ USINT_TO_STRING(SUBINDEX),
+ ',"',
+ VARTYPE,
+ '")'));
+PY1(TRIG := STATE = 4,
+ CODE := 'GetResult()');
+]]>
+ </ST>
+ </body>
+ </pou>
+ <pou name="EtherLabSDODownload" pouType="functionBlock">
+ <interface>
+ <inputVars>
+ <variable name="EXECUTE">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="POS">
+ <type>
+ <INT/>
+ </type>
+ </variable>
+ <variable name="INDEX">
+ <type>
+ <UINT/>
+ </type>
+ </variable>
+ <variable name="SUBINDEX">
+ <type>
+ <USINT/>
+ </type>
+ </variable>
+ <variable name="VARTYPE">
+ <type>
+ <string/>
+ </type>
+ </variable>
+ <variable name="VALUE">
+ <type>
+ <string/>
+ </type>
+ </variable>
+ </inputVars>
+ <outputVars>
+ <variable name="ACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="ERROR">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ </outputVars>
+ <localVars>
+ <variable name="PY0">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ <variable name="PY1">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ <variable name="EXECUTE0">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="STATE">
+ <type>
+ <INT/>
+ </type>
+ <initialValue>
+ <simpleValue value="0"/>
+ </initialValue>
+ </variable>
+ </localVars>
+ </interface>
+ <body>
+ <ST>
+<![CDATA[{extern int AcquireSDOLock();}
+{extern int HasAnswer();}
+{extern void ReleaseSDOLock();}
+CASE STATE OF
+ 0:
+ IF EXECUTE AND NOT EXECUTE0 THEN
+ STATE := 1;
+ ACK := 0;
+ ERROR := 0;
+ END_IF;
+ 1:
+ {if (AcquireSDOLock()) __SET_VAR(data__->,STATE, 2)}
+ 2:
+ IF PY0.ACK THEN
+ STATE := 3;
+ END_IF;
+ 3:
+ {if (HasAnswer()) __SET_VAR(data__->,STATE, 4)}
+ 4:
+ IF PY1.ACK THEN
+ ACK := 1;
+ VALUE := PY1.RESULT;
+ ERROR := EQ(PY1.RESULT, 'False');
+ STATE := 0;
+ {ReleaseSDOLock();}
+ END_IF;
+ELSE
+ STATE := 0;
+END_CASE;
+EXECUTE0 := EXECUTE;
+PY0(TRIG := STATE = 2,
+ CODE := CONCAT('EthercatSDODownload(',
+ INT_TO_STRING(POS),
+ ',',
+ UINT_TO_STRING(INDEX),
+ ',',
+ USINT_TO_STRING(SUBINDEX),
+ ',"',
+ VARTYPE,
+ '",',
+ VALUE,
+ ')'));
+PY1(TRIG := STATE = 4,
+ CODE := 'GetResult()');
+]]>
+ </ST>
+ </body>
+ </pou>
+ </pous>
+ </types>
+ <instances>
+ <configurations/>
+ </instances>
+</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/runtime_etherlab.py Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,50 @@
+import subprocess,sys,ctypes
+from threading import Thread
+
+SDOAnswered = PLCBinary.SDOAnswered
+SDOAnswered.restype = None
+SDOAnswered.argtypes = []
+
+SDOThread = None
+Result = None
+
+def SDOThreadProc(*params):
+ global Result
+ if params[0] == "upload":
+ command = "ethercat upload -p %d -t %s 0x%.4x 0x%.2x"
+ else:
+ command = "ethercat download -p %d -t %s 0x%.4x 0x%.2x %s"
+
+ proc = subprocess.Popen(command % params[1:], stdout=subprocess.PIPE, shell=True)
+ res = proc.wait()
+ output = proc.communicate()[0]
+
+ if params[0] == "upload":
+ Result = None
+ if res == 0:
+ if params[2] in ["float", "double"]:
+ Result = float(output)
+ elif params[2] in ["string", "octet_string", "unicode_string"]:
+ Result = output
+ else:
+ hex_value, dec_value = output.split()
+ if int(hex_value, 16) == int(dec_value):
+ Result = int(dec_value)
+ else:
+ Result = res == 0
+
+ SDOAnswered()
+
+def EthercatSDOUpload(pos, index, subindex, var_type):
+ global SDOThread
+ SDOThread = Thread(target=SDOThreadProc, args=["upload", pos, var_type, index, subindex])
+ SDOThread.start()
+
+def EthercatSDODownload(pos, index, subindex, var_type, value):
+ global SDOThread
+ SDOThread = Thread(target=SDOThreadProc, args=["download", pos, var_type, index, subindex, value])
+ SDOThread.start()
+
+def GetResult():
+ global Result
+ return Result