vvvv3701669
Hi all,
I am trying to add my FBD to editor library,
for example, I have a average fbd, how to add it to Library Arithmetic?

thanks!
Quote 0 0
thiagoralves
There is no "easy way" to add your custom block to the library without modifying the source code of the editor. All blocks are hard-coded in the source code of the editor. That being said, there is a "patch way" to add blocks to the library without modifying much of the code. The steps are the following:

1. Go to the directory where OpenPLC Editor is installed in your machine. That's usually C:\Users\[Your-User-Name]\OpenPLC\OpenPLC Editor\editor if you're on Windows.
2. Find the subfolder plcopen
3. With a source code editor (I recommend notepad++) open the file definitions.py and add your custom library file to it on line 50:
StdTC6Libs = [(_("Standard function blocks"),   join(sd, "Standard_Function_Blocks.xml")),
              (_("Additional function blocks"), join(sd, "Additional_Function_Blocks.xml")),
              (_("My Custom Library"), join(sd, "My_Custom_Library.xml"))]

4. Then on the same folder, create the "My_Custom_Library.xml" file with the information about your own function blocks. Since this is a library file, you can add multiple function blocks to the same file. On this example I'm adding just one. This is how your "My_Custom_Library.xml" file should look like:
<?xml version='1.0' encoding='utf-8'?>
<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
  <fileHeader companyName="OpenPLC" productName="My Custom Library" productVersion="1.0" creationDateTime="2020-01-21T09:44:11"/>
  <contentHeader name="My Custom Library" author="Thiago Alves" modificationDateTime="2020-01-21T09:44:11">
    <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="Test" pouType="functionBlock">
        <interface>
          <inputVars>
            <variable name="I0">
              <type>
                <INT/>
              </type>
        <documentation>
                <xhtml😋><![CDATA[Insert an integer here]]></xhtml😋>
              </documentation>
            </variable>
            <variable name="ACTIVE">
              <type>
                <BOOL/>
              </type>
        <documentation>
                <xhtml😋><![CDATA[0 - block does nothing, 1 - block sums 10 to integer in I0]]></xhtml😋>
              </documentation>
            </variable>
          </inputVars>
          <outputVars>
            <variable name="OUT">
              <type>
                <INT/>
              </type>
        <documentation>
                <xhtml😋><![CDATA[This is the output: I0 + 10]]></xhtml😋>
              </documentation>
            </variable>
          </outputVars>
        </interface>
        <body>
          <ST>
            <xhtml😋><![CDATA[IF ACTIVE = TRUE THEN
  OUT := I0 + 10;
  END_IF;]]></xhtml😋>
          </ST>
        </body>
        <documentation>
          <xhtml😋><![CDATA[This block outputs the sum of input I0 and 10.]]></xhtml😋>
        </documentation>
      </pou>
    </pous>
  </types>
  <instances>
    <configurations/>
  </instances>
</project>


Save everything and your new block will show up in the editor now. This is enough to have the block there, but your code won't compile just yet. You will have to add information about how to compile your new block in MatIEC. This is a bit tricky, but not very hard.

1. Go to folder \OpenPLC Editor\matiec\lib\
2. Create a file my_custom_library.txt with the full structured text code for all your custom blocks in your library. Following the example, your file should look like this:
(*
 * This is my custom blocks implementation
 *
 *
 * Test Block
 * -----------
 *)
(* This block should get an integer at I0, sum
   10 to it and then output the sum at OUT
*)
FUNCTION_BLOCK TEST
  VAR_INPUT
    I0 : INT;
    ACTIVE : BOOL;
  END_VAR
  VAR_OUTPUT
    OUT : INT;
  END_VAR
  IF ACTIVE = TRUE THEN
    OUT := I0 + 10;
  END_IF;
END_FUNCTION_BLOCK

3. Now open the file standard_FB.txt and include your new .txt file in it right below the sema.txt inclusion at the end of the file. The end of your file should look like this:
(* Not in the standard, but useful nonetheless. *)
{#include "sema.txt" }
{#include "my_custom_library.txt" }

{enable code generation}


This is the tricky part. You will also have to write the C code representation of your function block inside MatIEC. I'm trying to find a way so that users don't have to do this, but for now, the only way to have your block compiling is to manually write the C code for it. Here is how you do it:

1. Go to folder \OpenPLC Editor\matiec\lib\C\
2. Open the file iec_std_FB.h in notepad++ (or any other code editor of your preference) and go to line 555, right after the declaration of the function block SEMA.
3. Then insert the declaration of your custom block TEST (the only block defined in your custom library):
// FUNCTION_BLOCK TEST
// Data part
typedef struct {
  // FB Interface - IN, OUT, IN_OUT variables
  __DECLARE_VAR(BOOL,EN)
  __DECLARE_VAR(BOOL,ENO)
  __DECLARE_VAR(INT,I0)
  __DECLARE_VAR(BOOL,ACTIVE)
  __DECLARE_VAR(INT,OUT)
} TEST;

4. Now go to the end of the code (the very last line of code) before the #endif line
5. After the // SEMA_body__()  code declaration, add the code body for your custom block in C. This is basically your implementation of the function block, but now written in C:
static void TEST_init__(TEST *data__, BOOL retain) {
  __INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
  __INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
  __INIT_VAR(data__->I0,0,retain)
  __INIT_VAR(data__->ACTIVE,__BOOL_LITERAL(FALSE),retain)
  __INIT_VAR(data__->OUT,0,retain)
}
// Code part
static void TEST_body__(TEST *data__) {
  
  // Control execution
  if (!__GET_VAR(data__->EN)) {
    __SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
    return;
  }
  else {
    __SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
  }
  
  // Code
  if (__GET_VAR(data__->ACTIVE,)) {
    __SET_VAR(data__->,OUT,,__GET_VAR(data__->I0,)+10);
  }
  goto __end;
  __end:
    return;
} // TEST_body__() 


Now you have to do the same thing also for the file iec_std_FB_no_ENENO.h but this time excluding the execution control parameters. Open iec_std_FB_no_ENENO.h on notepad++ and on line 495 add the declaration of you custom block TEST without the EN and ENO pins:
// FUNCTION_BLOCK TEST
// Data part
typedef struct {
  // FB Interface - IN, OUT, IN_OUT variables
  __DECLARE_VAR(INT,I0)
  __DECLARE_VAR(BOOL,ACTIVE)
  __DECLARE_VAR(INT,OUT)
} TEST;


And finally at the end of the same file, add the implementation of your block in C right after the // SEMA_body__() :
static void TEST_init__(TEST *data__, BOOL retain) {
  __INIT_VAR(data__->I0,0,retain)
  __INIT_VAR(data__->ACTIVE,__BOOL_LITERAL(FALSE),retain)
  __INIT_VAR(data__->OUT,0,retain)
}
// Code part
static void TEST_body__(TEST *data__) {
  // Code
  if (__GET_VAR(data__->ACTIVE,)) {
    __SET_VAR(data__->,OUT,,__GET_VAR(data__->I0,)+10);
  }
  goto __end;
  __end:
    return;
} // TEST_body__() 


That's it! Now your custom block is added to the editor and also to MatIEC and should compile just fine.
Quote 1 0
thiagoralves
To make things easier, I'm attaching here all the modified files in a zip folder.
Quote 1 0
vvvv3701669
To make things easier, I'm attaching here all the modified files in a zip folder.

it's work.
thank you so much!
Quote 0 0