Home » Eclipse Projects » 4DIAC - Framework for Distributed Industrial Automation and Control » How to create IEC 61131-3 callable function in 4diac?
How to create IEC 61131-3 callable function in 4diac? [message #1863567] |
Sat, 10 February 2024 17:28 |
Ketut Kumajaya Messages: 26 Registered: January 2024 |
Junior Member |
|
|
IEC 61131-3 SECANTF function:
FUNCTION SECANTF : REAL
VAR_INPUT
X : REAL;
Y : REAL;
P : UINT;
END_VAR
(* Ketut Kumajaya, 20/08/2018 *)
(* Reference: https://lar.bnl.gov/properties/basic.html *)
(* Reference: http://edge.rit.edu/edge/P07106/public/Nox.pdf *)
IF (P = 3) THEN SECANTF := -Y + 4.863 * EXP((-5.9409785*(1.0 - X) + 1.3553888*EXPT(1.0 - X,1.5) - 0.46497607*EXPT(1.0 - X,2) - 1.5399043*EXPT(1.0 - X,4.5))/X);
ELSE IF (P = 5) THEN SECANTF := -Y + 7251.0 * EXP((-6.71893 * (1.0 - X) + 1.35966 * EXPT((1.0 - X),1.5) - 1.3779 * EXPT((1.0 - X),2.5) - 4.051 * EXPT((1.0 - X),5))/X);
ELSE SECANTF := 0.0;
END_IF;
END_IF;
END_FUNCTION
IEC 61131-3 SECANT function than call SECANTF function:
FUNCTION SECANT : REAL
VAR_INPUT
X1 : REAL;
X2 : REAL;
E1 : REAL;
Y1 : REAL;
P1 : UINT;
END_VAR
VAR
XM1 : REAL;
X0 : REAL;
C1 : REAL;
END_VAR
(* Ketut Kumajaya, 20/08/2018 *)
(* Adapted from: https://www.geeksforgeeks.org/program-to-find-root-of-an-equations-using-secant-method/ *)
XM1 := E1 + 0.1; (* make sure to initially enter the loop *)
IF (SECANTF(X1,Y1,P1) * SECANTF(X2,Y1,P1) < 0.0) THEN
(* repeat the loop until the convergence *)
WHILE (ABS(XM1 - X0) >= E1) DO
(* calculate the intermediate value *)
X0 := (X1 * SECANTF(X2,Y1,P1) - X2 * SECANTF(X1,Y1,P1)) / (SECANTF(X2,Y1,P1) - SECANTF(X1,Y1,P1));
(* check if x0 is root of equation or not *)
C1 := SECANTF(X1,Y1,P1) * SECANTF(X0,Y1,P1);
(* update the value of interval *)
X1 := X2;
X2 := X0;
(* if x0 is the root of equation then break the loop *)
IF (C1 = 0.0) THEN
EXIT;
END_IF;
XM1 := (X1 * SECANTF(X2,Y1,P1) - X2 * SECANTF(X1,Y1,P1)) / (SECANTF(X2,Y1,P1) - SECANTF(X1,Y1,P1));
END_WHILE;
SECANT := X0;
ELSE
SECANT := 0.0;
END_IF;
END_FUNCTION
IEC 61499 SECANTF FB:
ALGORITHM calculate
(* Ketut Kumajaya, 20/08/2018 *)
(* Reference: https://lar.bnl.gov/properties/basic.html *)
(* Reference: http://edge.rit.edu/edge/P07106/public/Nox.pdf *)
IF (QI = 3) THEN (* argon function *)
OUT := -Y + 4.863 * EXP((-5.9409785 * (1.0 - X) + 1.3553888 * EXPT(1.0 - X, 1.5) - 0.46497607 * EXPT(1.0 - X, 2) - 1.5399043 * EXPT(1.0 - X, 4.5)) / X);
ELSE
IF (QI = 5) THEN (* nitrous oxide function *)
OUT := -Y + 7251.0 * EXP((-6.71893 * (1.0 - X) + 1.35966 * EXPT((1.0 - X), 1.5) - 1.3779 * EXPT((1.0 - X), 2.5) - 4.051 * EXPT((1.0 - X), 5)) / X);
ELSE
OUT := 0.0;
END_IF;
END_IF;
END_ALGORITHM
IEC 61499 SECANT FB that call SECANTF FB. SECANTF1 is a SECANTF function block type registered inside SECANT FB:
ALGORITHM calculate
(* Ketut Kumajaya, 20/08/2018 *)
(* Adapted from: https://www.geeksforgeeks.org/program-to-find-root-of-an-equations-using-secant-method/ *)
XM1 := E1 + 0.1; (* make sure to initially enter the loop *)
(* IF (SECANTF(QI, X1, Y1) * SECANTF(QI, X2, Y1) < 0.0) THEN *)
SECANTF1(QI := QI, X := X1, Y := Y1);
Z1 := SECANTF1.OUT;
SECANTF1(QI := QI, X := X2, Y := Y1);
Z1 := Z1 * SECANTF1.OUT;
IF (Z1 < 0.0) THEN
(* repeat the loop until the convergence *)
WHILE (ABS(XM1 - X0) >= E1) DO
(* calculate the intermediate value *)
(* X0 := (X1 * SECANTF(QI, X2, Y1) - X2 * SECANTF(QI, X1, Y1)) / (SECANTF(QI, X2, Y1) - SECANTF(QI, X1, Y1)); *)
SECANTF1(QI := QI, X := X2, Y := Y1);
Z1 := X1 * SECANTF1.OUT;
SECANTF1(QI := QI, X := X1, Y := Y1);
Z1 := Z1 - X2 * SECANTF1.OUT;
SECANTF1(QI := QI, X := X2, Y := Y1);
X0 := SECANTF1.OUT;
SECANTF1(QI := QI, X := X1, Y := Y1);
X0 := X0 - SECANTF1.OUT;
X0 := Z1 / X0;
(* check if x0 is root of equation or not *)
(* C1 := SECANTF(QI, X1, Y1) * SECANTF(QI, X0, Y1) *)
SECANTF1(QI := QI, X := X1, Y := Y1);
C1 := SECANTF1.OUT;
SECANTF1(QI := QI, X := X0, Y := Y1);
C1 := C1 * SECANTF1.OUT;
(* update the value of interval *)
X1 := X2;
X2 := X0;
(* if x0 is the root of equation then break the loop *)
IF (C1 = 0.0) THEN
EXIT;
END_IF;
(* XM1 := (X1 * SECANTF(QI, X2, Y1) - X2 * SECANTF(QI, X1, Y1)) / (SECANTF(QI, X2, Y1) - SECANTF(QI, X1, Y1)); *)
SECANTF1(QI := QI, X := X2, Y := Y1);
Z1 := X1 * SECANTF1.OUT;
SECANTF1(QI := QI, X := X1, Y := Y1);
Z1 := Z1 - X2 * SECANTF1.OUT;
SECANTF1(QI := QI, X := X2, Y := Y1);
XM1 := SECANTF1.OUT;
SECANTF1(QI := QI, X := X1, Y := Y1);
XM1 := XM1 - SECANTF1.OUT;
XM1 := Z1 / XM1;
END_WHILE;
OUT := X0;
ELSE
OUT := 0.0;
END_IF;
END_ALGORITHM
Is my implementation above correct or is there any a simpler way? It looks complicated but works.
EDIT:
I can make a C function call inside exported FB easily but I just want to write my FB completely in ST language.
[Updated on: Sun, 11 February 2024 01:29] Report message to a moderator
|
|
|
Re: How to create IEC 61131-3 callable function in 4diac? [message #1863571 is a reply to message #1863567] |
Sun, 11 February 2024 11:27 |
|
I think having the code in ST is definitely the better solution then in C. Especially from a maintainability and portability perspective.
As there is lot of math involved I have a hard time to say if it is correct. But I would have some general observations that may help you making your code more readable:
- Functions and Function blocks may not have the same name
- if your function is only used by one function block you can define the function as method inside of the function block.
- It loooks like your SECANTF Function is rather expensive. From what I see you always invoke it with two different parameter sets. Doing this once before all your ifs and storing the results in two variables leads to better performance but also to better readable code.
- why is SECANTF an FB and not a method of SECANT FB? A method can access inputs and outputs of the FB. In your case this means you could avoid the QI parameter which again results in a bit better readability of your code.
I hope this helps.
|
|
|
Re: How to create IEC 61131-3 callable function in 4diac? [message #1863572 is a reply to message #1863571] |
Sun, 11 February 2024 17:59 |
Ketut Kumajaya Messages: 26 Registered: January 2024 |
Junior Member |
|
|
METHOD SECANT_FUNC : REAL
VAR_INPUT
SECANT_FUNC_X : REAL;
END_VAR
(* Ketut Kumajaya, 20/08/2018 *)
(* Reference: https://lar.bnl.gov/properties/basic.html *)
(* Reference: http://edge.rit.edu/edge/P07106/public/Nox.pdf *)
IF (SECANT_F = 3) THEN (* argon function *)
SECANT_FUNC := -SECANT_Y + 4.863 * EXP((-5.9409785 * (1.0 - SECANT_FUNC_X) + 1.3553888 * EXPT(1.0 - SECANT_FUNC_X,
1.5) - 0.46497607 * EXPT(1.0 - SECANT_FUNC_X, 2.0) - 1.5399043 * EXPT(1.0 - SECANT_FUNC_X, 4.5)) / SECANT_FUNC_X);
ELSE
IF (SECANT_F = 5) THEN (* nitrous oxide function *)
SECANT_FUNC := -SECANT_Y + 7251.0 * EXP((-6.71893 * (1.0 - SECANT_FUNC_X) + 1.35966 * EXPT((1.0 - SECANT_FUNC_X)
, 1.5) - 1.3779 * EXPT((1.0 - SECANT_FUNC_X), 2.5) - 4.051 * EXPT((1.0 - SECANT_FUNC_X), 5)) / SECANT_FUNC_X);
ELSE
SECANT_FUNC := 0.0; (* for future function *)
END_IF;
END_IF;
END_METHOD
METHOD SECANT : REAL
VAR_INPUT
SECANT_X1 : REAL;
SECANT_X2 : REAL;
SECANT_E : REAL;
END_VAR
VAR_TEMP
SECANT_XM : REAL;
SECANT_X0 : REAL;
SECANT_C : REAL;
SECANT_X11 : REAL;
SECANT_X21 : REAL;
END_VAR
(* Ketut Kumajaya, 20/08/2018 *)
(* Adapted from: https://www.geeksforgeeks.org/program-to-find-root-of-an-equations-using-secant-method/ *)
SECANT_X11 := SECANT_X1; (* to avoid writing to input variable *)
SECANT_X21 := SECANT_X2; (* to avoid writing to input variable *)
SECANT_XM := SECANT_E + 0.1; (* make sure to initially enter the loop *)
IF (SECANT_FUNC(SECANT_X11) * SECANT_FUNC(SECANT_X21) < 0.0) THEN
(* repeat the loop until the convergence *)
WHILE (ABS(SECANT_XM - SECANT_X0) >= SECANT_E) DO
(* calculate the intermediate value *)
SECANT_X0 := (SECANT_X11 * SECANT_FUNC(SECANT_X21) - SECANT_X21 * SECANT_FUNC(SECANT_X11)) / (SECANT_FUNC(
SECANT_X21)
- SECANT_FUNC(SECANT_X11));
(* check if SECANT_X0 is root of equation or not *)
SECANT_C := SECANT_FUNC(SECANT_X11) * SECANT_FUNC(SECANT_X0);
(* update the value of interval *)
SECANT_X11 := SECANT_X21;
SECANT_X21 := SECANT_X0;
(* if SECANT_X0 is the root of equation then break the loop *)
IF (SECANT_C = 0.0) THEN
EXIT;
END_IF;
SECANT_XM := (SECANT_X11 * SECANT_FUNC(SECANT_X21) - SECANT_X21 * SECANT_FUNC(SECANT_X11)) / (SECANT_FUNC(
SECANT_X21)
- SECANT_FUNC(SECANT_X11));
END_WHILE;
SECANT := SECANT_X0;
ELSE
SECANT := 0.0;
END_IF;
END_METHOD
ALGORITHM calculate
...
Y1 := Y1 + 1.01325; (* absolute pressure *)
SECANT_Y := Y1 / 10.0;
SECANT_F := 3;
Y1 := -273.15 + SECANT(0.55615813, 1.0, 0.000001) * 150.687;
...
END_ALGORITHM
My function block implementation much better now. I set SECANT_F and SECANT_Y variable first and then call SECANT method per as your recommendation. Thank you very much.
[Updated on: Mon, 12 February 2024 01:31] Report message to a moderator
|
|
| | | | |
Re: How to create IEC 61131-3 callable function in 4diac? [message #1872395 is a reply to message #1872383] |
Wed, 30 October 2024 10:05 |
|
Yes the develop branch is the branch where we do all the developments. There it can happen that stuff break or are not working.
The release branch is the current release.
The freeze branch is a branch which we use to test and stabilize features for our prerelease branch. This is the 3.0.x which holds the rather stable version for the next release.
The 4diac FORTE branches with the same name should be compatible to the 4diac IDE branches.
We are heavily working on the upcoming 3.0.0 release. The reason why it is not yet a public release is that there are a few breaking changes upcoming for 4diac FORTE and the 3.0.0 release should have a stable 4diac FORTE API that will be fixed for many years.
I hope this clarifies the situation.
|
|
|
Re: How to create IEC 61131-3 callable function in 4diac? [message #1872407 is a reply to message #1872395] |
Wed, 30 October 2024 11:30 |
Guido Piasenza Messages: 17 Registered: October 2024 |
Junior Member |
|
|
Ok, thanks !
When trying to build the release branch I see a strange problem, the build process freezes after a few seconds:
[INFO] Scanning for projects...
[WARNING] The POM for org.apache.commons:commons-lang3:jar:3.8.1 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for org.apache.commons:commons-lang3:3.8.1
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/47/commons-parent-47.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/47/commons-parent-47.pom, line 1, column 42
[WARNING] The POM for commons-io:commons-io:jar:2.5 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for commons-io:commons-io:2.5
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/39/commons-parent-39.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/39/commons-parent-39.pom, line 1, column 42
[WARNING] The POM for commons-io:commons-io:jar:2.6 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for commons-io:commons-io:2.6
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/42/commons-parent-42.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/42/commons-parent-42.pom, line 1, column 42
[WARNING] The POM for org.apache.commons:commons-compress:jar:1.20 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for org.apache.commons:commons-compress:1.20
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/48/commons-parent-48.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/48/commons-parent-48.pom, line 1, column 42
[WARNING] The POM for org.apache.commons:commons-exec:jar:1.3 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for org.apache.commons:commons-exec:1.3
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/35/commons-parent-35.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/35/commons-parent-35.pom, line 1, column 42
[WARNING] The POM for org.apache.commons:commons-compress:jar:sources:1.20 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for org.apache.commons:commons-compress:1.20
[FATAL] Non-parseable POM /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/48/commons-parent-48.pom: UTF-8 BOM plus xml decl of ISO-8859-1 is incompatible (position: START_DOCUMENT seen <?xml version="1.0" encoding="ISO-8859-1"... @1:42) @ /home/gpiasenza/.m2/repository/org/apache/commons/commons-parent/48/commons-parent-48.pom, line 1, column 42
[INFO] Computing target platform for MavenProject: org.eclipse.fordiac:org.eclipse.fordiac.ide.product:2.0.1-SNAPSHOT @ /home/gpiasenza/WinShare/Download/Automazione/Source/4diac-ide/plugins/org.eclipse.fordiac.ide.product/pom.xml
[WARNING] No system packages found in profile nor toolchain for JRE-1.1, using current JRE system packages.
This can cause faulty dependency resolution, consider adding a definition for a 'jdk' with id=JRE-1.1 in your toolchains.xml
[WARNING] No system packages found in profile nor toolchain for JavaSE-11, using current JRE system packages.
This can cause faulty dependency resolution, consider adding a definition for a 'jdk' with id=JavaSE-11 in your toolchains.xml
[WARNING] No system packages found in profile nor toolchain for JavaSE-15, using current JRE system packages.
This can cause faulty dependency resolution, consider adding a definition for a 'jdk' with id=JavaSE-15 in your toolchains.xml
[WARNING] No system packages found in profile nor toolchain for JavaSE-16, using current JRE system packages.
This can cause faulty dependency resolution, consider adding a definition for a 'jdk' with id=JavaSE-16 in your toolchains.xml
[WARNING] No system packages found in profile nor toolchain for JavaSE-17, using current JRE system packages.
This can cause faulty dependency resolution, consider adding a definition for a 'jdk' with id=JavaSE-17 in your toolchains.xml
This does not happen with other branches.
|
|
|
Re: How to create IEC 61131-3 callable function in 4diac? [message #1872431 is a reply to message #1872407] |
Wed, 30 October 2024 20:27 |
|
I fear that the release branch is currently not building anymore. Fixing that would be more work then we currently think it is worth spending on it. Especially as the upcoming version will be so much better. So we would like to spend our effort in getting the remaining bits and pieces fixed. Therefore we would appreciate especially people testing and evaluating the 3.0.x branch and providing feedback there.
|
|
| |
Re: How to create IEC 61131-3 callable function in 4diac? [message #1872482 is a reply to message #1872437] |
Fri, 01 November 2024 08:20 |
|
As not so much 4diac FORTE development is happening you can either use develop or freeze. As an major change is coming to 4diac FORTE in he next days you maybe better of with freeze. But as you are also working on the code develop should also be fine. But maybe you then want to switch also your IDE to develop so that you get the according code generator changes as well.
|
|
|
Goto Forum:
Current Time: Mon Jan 13 08:20:06 GMT 2025
Powered by FUDForum. Page generated in 0.04739 seconds
|