<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Beckhoff Archives | DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/tag/beckhoff/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Fri, 04 Sep 2026 15:35:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>Beckhoff Archives | DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Getting Started with Database Server in Beckhoff TwinCAT 3</title>
		<link>https://static.dmcinfo.com/blog/16328/getting-started-with-database-server-in-beckhoff-twincat-3/</link>
		
		<dc:creator><![CDATA[Carter Silvey]]></dc:creator>
		<pubDate>Fri, 03 May 2024 09:41:19 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[TwinCAT3]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16328/getting-started-with-database-server-in-beckhoff-twincat-3/</guid>

					<description><![CDATA[<p>Table of contents Being able to store long term data is one of the most crucial parts of a manufacturing or testing environment. Having access to this data can allow a team to track long term trends of their systems. For instance, one team&#160;could track the uptimes of the various production lines to find where [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16328/getting-started-with-database-server-in-beckhoff-twincat-3/">Getting Started with Database Server in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-table-of-contents" class="wp-block-heading">Table of contents</h2>



<ol class="wp-block-list">
<li><a href="#download">Download and Installation</a></li>



<li><a href="#database">Adding the Database Project to a TwinCAT 3 Solutions</a></li>



<li><a href="#code">Writing Code to Write to the Database Server</a></li>



<li><a href="#testing">Testing the Database Connection</a></li>
</ol>



<p class="wp-block-paragraph">Being able to store long term data is one of the most crucial parts of a manufacturing or testing environment. Having access to this data can allow a team to track long term trends of their systems. For instance, one team&nbsp;could track the uptimes of the various production lines to find where the bottlenecks in the process flow are. Another team could use their motor&#8217;s&nbsp;speed data to track when it needs maintenance.</p>



<p class="wp-block-paragraph">Beckhoff TwinCAT 3 offers the ability to run a database server directly on the IPC using their TF6420 module. This module allows you to send data up to most types of databases, though this blog will provide specific examples by using a <a href="https://www.postgresql.org/" target="_blank">PostgreSQL</a> database since it is free to use,&nbsp;open source, and uses structured query language (SQL).</p>



<h2 id="download" class="wp-block-heading">1. Download and Installation</h2>



<h3 id="h-1-1-download" class="wp-block-heading">1.1. Download</h3>



<p class="wp-block-paragraph">First,&nbsp;<a href="https://www.beckhoff.com/en-us/products/automation/twincat/tfxxxx-twincat-3-functions/tf6xxx-connectivity/tf6420.html?" target="_blank" rel="noreferrer noopener">Download TF6420 from the Beckhoff website</a>. The installer is located in Documentation and Downloads&nbsp;&gt; Software and Tools.</p>



<figure class="wp-block-image aligncenter size-full"><img fetchpriority="high" decoding="async" width="866" height="619" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-download.png" alt="" class="wp-image-34727" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-download.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-download-300x214.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-download-768x549.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<h3 id="h-1-2-installation" class="wp-block-heading">1.2. Installation</h3>



<p class="wp-block-paragraph">Once downloaded you will need to run the .EXE on both the engineering computer and on the PLC. To download onto the PLC, the simplest way is to move the .EXE onto a USB and plug this into the PLC. Once the USB is plugged in, you can either remote into the PLC (Remote Desktop Connection) or connect a monitor and mouse using any of the outputs on the PLC. Once connected, run the .EXE on the PLC and install the software.</p>



<h3 id="h-1-3-open-twincat-xae" class="wp-block-heading">1.3. Open TwinCAT XAE</h3>



<p class="wp-block-paragraph">Once the installer is complete, open the TwinCAT XAE solution in which the database connection should be installed. If you haven&#8217;t already installed TwinCAT XAE or configured your Beckhoff IPC yet, <a href="https://static.dmcinfo.com/blog/19695/getting-started-with-a-beckhoff-plc-part-one-setup/">check out our setup blog on how to get started </a>and then come back to step 2.</p>



<h2 id="database" class="wp-block-heading">2. Adding the Database Project to a TwinCAT 3 Solution</h2>



<h3 id="h-2-1-add-new-database-server-nbsp-project" class="wp-block-heading">2.1. Add New Database Server&nbsp;Project</h3>



<p class="wp-block-paragraph">Within the project, right-click on the project solution -&gt; Add -&gt; New Project</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="438" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-project.png" alt="" class="wp-image-34731" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-project.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-project-300x152.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-project-768x388.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">In the window that opens, select TwinCAT Connectivity and then choose &#8220;Empty TwinCAT Database Server Project&#8221;</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="602" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-empty-twincat-database-server-project.png" alt="" class="wp-image-34733" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-empty-twincat-database-server-project.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-empty-twincat-database-server-project-300x209.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-empty-twincat-database-server-project-768x534.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<h3 class="wp-block-heading">2.2. Add and Configure the Database</h3>



<p class="wp-block-paragraph">Once the new project is added, there should be a default TcDbServer already added under the project. There is currently no database in the project, but this can be done by right-clicking TcDbServer -&gt; Add New Database</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="433" height="576" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-database.png" alt="" class="wp-image-34734" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-database.png 433w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-new-database-226x300.png 226w" sizes="(max-width: 433px) 100vw, 433px" /></figure>



<p class="wp-block-paragraph">You will then see a new DB server appear under TcDbServer. The server can be configured by double-clicking the DB. This will bring up the configuration window. Currently the window is empty, but this can be fixed by selecting the database type pictured below. For this example, a PostgreSQL database will be used.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="436" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-postgresql.png" alt="" class="wp-image-34735" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-postgresql.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-postgresql-300x151.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-postgresql-768x387.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">Once the database type is selected, the settings will appear and can be configured there. For PostgreSQL, the first few settings are Host, Database, and Port. The next option is Authentication which contains a drop down with different kinds of authentication. The example below is going to use Username/Password.</p>



<p class="wp-block-paragraph"><em>Note:&nbsp;The password used here is encrypted and is not stored in plain text anywhere on the PLC</em></p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="442" height="269" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-username-password.png" alt="" class="wp-image-34736" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-username-password.png 442w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-username-password-300x183.png 300w" sizes="(max-width: 442px) 100vw, 442px" /></figure>



<h3 id="h-2-3-set-target-ams-net-id" class="wp-block-heading">2.3. Set Target AMS Net ID</h3>



<p class="wp-block-paragraph">Once all the information is added, the connection is not quite ready to be tested. The AMS Net ID must be set up first. To do this, go back to TcDbServer and double click the tab. Once the server settings window is open, there is a dropdown menu in the top left where all the options for Ams Net Ids appear.</p>



<p class="wp-block-paragraph">For testing on a local machine select &lt;Local&gt;.</p>



<p class="wp-block-paragraph">If this is running on a PLC and you are connected to the PLC, the name of the PLC will be on this menu and you can choose that instead.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="451" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-ams-net-selection.png" alt="" class="wp-image-34739" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-ams-net-selection.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-ams-net-selection-300x156.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-ams-net-selection-768x400.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<h3 id="h-2-4-tf6420-license" class="wp-block-heading">2.4. TF6420 License</h3>



<p class="wp-block-paragraph">Before checking the connection to the server, the TF6420 license must be activated. For now, a trial license can be generated. First start by going to the Manage License tab at the top of the window that has opened. Next scroll all the way down to TF6420 TC3 Database Server and check the box next to it that says cpu license.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="296" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-license.png" alt="" class="wp-image-34741" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-license.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-license-300x103.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-license-768x263.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">After this box is checked, go back to the main license screen and into the Order Information (Runtime) tab. Once here go down to the 7 Days Trial License and click on that. A small screen will then appear in which you will type a short captcha. Once this is typed, hit Ok and the license will be generated.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="432" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-7-day-trial-license.png" alt="" class="wp-image-34742" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-7-day-trial-license.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-7-day-trial-license-300x150.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-7-day-trial-license-768x383.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<h3 id="h-2-5-activate-database-configuration" class="wp-block-heading">2.5. Activate Database Configuration</h3>



<p class="wp-block-paragraph">Next, activate the configuration of the database connection by right-clicking the DB and selecting Activate Configuration.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="433" height="555" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-activate-configuration.png" alt="" class="wp-image-34744" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-activate-configuration.png 433w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-activate-configuration-234x300.png 234w" sizes="(max-width: 433px) 100vw, 433px" /></figure>



<p class="wp-block-paragraph">(Optional) The database server toolbar&nbsp;is optional, but will be beneficial moving forward. At the top of the screen on the task bar, right-click and select TwinCAT Database Server. This will add a new set of tools at the top that can be used with the databases (one of them being activate configuration).</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="320" height="789" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-database-toolbar.png" alt="" class="wp-image-34745" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-database-toolbar.png 320w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-database-toolbar-122x300.png 122w" sizes="(max-width: 320px) 100vw, 320px" /></figure>



<p class="wp-block-paragraph">Here is what the toolbar will look like when added:</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="320" height="28" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-database-toolbar.png" alt="" class="wp-image-34746" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-database-toolbar.png 320w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-database-toolbar-300x26.png 300w" sizes="(max-width: 320px) 100vw, 320px" /></figure>



<h3 id="h-2-6-check-database-connection" class="wp-block-heading">2.6. Check Database Connection</h3>



<p class="wp-block-paragraph">After activating configuration, check this connection by going back to the DB page. At the bottom, there will be 2 options, CREATE and CHECK. Select CHECK.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="687" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-check-database.png" alt="" class="wp-image-34747" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-check-database.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-check-database-300x238.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-check-database-768x609.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">If everything went well, you should see a pop up that says the check succeeded. If not, verify all database information is correct and go back to step 8.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="314" height="196" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configuration-check-succeeded.png" alt="" class="wp-image-34748" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configuration-check-succeeded.png 314w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configuration-check-succeeded-300x187.png 300w" sizes="(max-width: 314px) 100vw, 314px" /></figure>



<h3 id="h-2-7-add-database-to-configuration-pool" class="wp-block-heading">2.7. Add Database to Configuration Pool</h3>



<p class="wp-block-paragraph">Once the database is configured, it needs to be added to the DB configuration pool. This can be done by right-clicking on the DB and hitting the Add to DB Configuration Pool tab.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="433" height="482" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-to-configuration-pool.png" alt="" class="wp-image-34749" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-to-configuration-pool.png 433w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-to-configuration-pool-270x300.png 270w" sizes="(max-width: 433px) 100vw, 433px" /></figure>



<h2 id="code" class="wp-block-heading">3. Writing Code to Write to the Database Server</h2>



<h3 id="h-3-1-installing-reference-libraries" class="wp-block-heading">3.1. Installing Reference Libraries</h3>



<p class="wp-block-paragraph">Once added to the DB Configuration Pool, there are a few basic functions to test the connection and write a few queries. In order to use these, we will need to install 2 additional libraries. To do this, go to the PLC project that the database will be called in. Then go to the references tab in the project tree pictured below. Right-click this and then select Add library.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="433" height="428" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-library.png" alt="" class="wp-image-34750" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-library.png 433w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-add-library-300x297.png 300w" sizes="(max-width: 433px) 100vw, 433px" /></figure>



<p class="wp-block-paragraph">This will open a library window where the 2 libraries needed for database are located. Tc3_Database and Tc3_EventLogger.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="771" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-tc3-database-and-tc3-eventlogger.png" alt="" class="wp-image-34751" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-tc3-database-and-tc3-eventlogger.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-tc3-database-and-tc3-eventlogger-300x267.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-tc3-database-and-tc3-eventlogger-768x684.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<h3 id="h-3-2-example-code" class="wp-block-heading">3.2. Example Code</h3>



<p class="wp-block-paragraph">We can now use the built-in TwinCAT functions to send a basic SQL command. Again, for this example we&#8217;re using PostgreSQL functions and syntax. Under POUs, open MAIN and put the following code in the variable declaration section:</p>


<pre class="”brush:pascal”"><br /><br />
</pre>


<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Pascal</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR 
    nStep, nNextStep : INT; 
    sQuery : STRING; 
    fbDatabase : FB_SQLDatabaseEvt(sNetID := '', tTimeout := T#5S); 
    fbSqlCommand : FB_SQLCommandEvt(sNetID := '', tTimeout := T#5S); 
    tcMessage : I_TcMessage;  
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">VAR</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    nStep, nNextStep : INT; </span></span>
<span class="line"><span style="color: #D4D4D4">    sQuery : </span><span style="color: #569CD6">STRING</span><span style="color: #D4D4D4">; </span></span>
<span class="line"><span style="color: #D4D4D4">    fbDatabase : FB_SQLDatabaseEvt(sNetID := </span><span style="color: #CE9178">&apos;&apos;</span><span style="color: #D4D4D4">, tTimeout := T</span><span style="color: #CE9178">#5</span><span style="color: #D4D4D4">S); </span></span>
<span class="line"><span style="color: #D4D4D4">    fbSqlCommand : FB_SQLCommandEvt(sNetID := </span><span style="color: #CE9178">&apos;&apos;</span><span style="color: #D4D4D4">, tTimeout := T</span><span style="color: #CE9178">#5</span><span style="color: #D4D4D4">S); </span></span>
<span class="line"><span style="color: #D4D4D4">    tcMessage : I_TcMessage;  </span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">Here is a&nbsp;brief explanation of each variable:</p>



<ul class="wp-block-list">
<li>nStep and nNextStep are used to drive a state machine.</li>



<li>sQuery is the raw string for the query we want to send to the database</li>



<li>FB_SQLDatabaseEvt is responsible for connecting, disconnecting and overall communication with the database.</li>



<li>FB_SQLCommandEvt is responsible for generating a SQL command to be sent via the FB_SQLDatabaseEvt. Note: A standard STRING will not work if being sent through FB_SQLDatabaseEvt, even if the syntax is correct.</li>



<li>I_TcMessage will store any messages sent back from the database server. This will be helpful for identifying errors if there are any.</li>
</ul>



<p class="wp-block-paragraph">In the code execution section of MAIN, add the following basic state machine:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Pascal</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>//Generate the query string.
//Change TableName to your table's name.
//Change column1 and column2 to the column names (include any other columns your table has, separated by ,).
//Change $'value1$' and $'value2$' to the values you wish to send.
//Note: $ is an escape character for a single quote. Single quotes indicate a string.

sQuery := 'INSERT INTO TableName (column1, column2) values ($'value1$', $'value2$')';

CASE nStep OF
    0:
        //Connect to the database at database ID 1
        IF fbDatabase.Connect(1) THEN
            nNextStep := 10;
        END_IF
    10:
        //Move the database message result to tcMessage
        tcMessage := fbDatabase.ipTcResult;
        //Go to disconnect step if there's an error
        IF fbDatabase.bError THEN
            nNextStep := 99;
        END_IF
        //Create a SQL command
        IF fbDatabase.CreateCmd(ADR(fbSqlCommand)) THEN
            nNextStep := 20;
        END_IF
    20:
        //Execute the SQL command of sQuery
        IF fbSQLCommand.Execute(ADR(sQuery), SIZEOF(sQuery)) >= 0 THEN
            tcMessage := fbSQLCommand.ipTcResult;
            nNextStep := 99;
        END_IF
    99:
        //Disconnect from the database
        IF fbDatabase.Disconnect() THEN
            nNextStep := 0;
        END_IF
END_CASE
 
//Advance the state machine step
nStep := nNextStep;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">//Generate the query string.</span></span>
<span class="line"><span style="color: #6A9955">//Change TableName to your table&apos;s name.</span></span>
<span class="line"><span style="color: #6A9955">//Change column1 and column2 to the column names (include any other columns your table has, separated by ,).</span></span>
<span class="line"><span style="color: #6A9955">//Change $&apos;value1$&apos; and $&apos;value2$&apos; to the values you wish to send.</span></span>
<span class="line"><span style="color: #6A9955">//Note: $ is an escape character for a single quote. Single quotes indicate a string.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">sQuery := </span><span style="color: #CE9178">&apos;INSERT INTO TableName (column1, column2) values ($&apos;</span><span style="color: #D4D4D4">value1$</span><span style="color: #CE9178">&apos;, $&apos;</span><span style="color: #D4D4D4">value2$</span><span style="color: #CE9178">&apos;)&apos;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CASE</span><span style="color: #D4D4D4"> nStep </span><span style="color: #569CD6">OF</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Connect to the database at database ID 1</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> fbDatabase.Connect(</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            nNextStep := </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        END_IF</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Move the database message result to tcMessage</span></span>
<span class="line"><span style="color: #D4D4D4">        tcMessage := fbDatabase.ipTcResult;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Go to disconnect step if there&apos;s an error</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> fbDatabase.bError </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            nNextStep := </span><span style="color: #B5CEA8">99</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        END_IF</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Create a SQL command</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> fbDatabase.CreateCmd(ADR(fbSqlCommand)) </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            nNextStep := </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        END_IF</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Execute the SQL command of sQuery</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> fbSQLCommand.Execute(ADR(sQuery), SIZEOF(sQuery)) &gt;= </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            tcMessage := fbSQLCommand.ipTcResult;</span></span>
<span class="line"><span style="color: #D4D4D4">            nNextStep := </span><span style="color: #B5CEA8">99</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        END_IF</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #B5CEA8">99</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Disconnect from the database</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> fbDatabase.Disconnect() </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            nNextStep := </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        END_IF</span></span>
<span class="line"><span style="color: #D4D4D4">END_CASE</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #6A9955">//Advance the state machine step</span></span>
<span class="line"><span style="color: #D4D4D4">nStep := nNextStep;</span></span></code></pre></div>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The state machine will do the following:</p>



<ul class="wp-block-list">
<li>Connect to the database with database ID 1. If you have multiple databases, you can change the database ID input to point to a specific database. You can find this ID by going back to the database configuration page (where you typed in the IP address, port number, etc.) and checking what the DBID is in the top left corner.</li>



<li>Create the SQL command.</li>



<li>Execute the SQL command according to sQuery</li>



<li>Disconnect from the database</li>
</ul>



<p class="wp-block-paragraph">You can activate the configuration for the PLC project to start sending queries to the database!</p>



<h2 id="testing" class="wp-block-heading">4. Testing the Database Connection</h2>



<h3 id="h-4-1-open-tf6420-configurator" class="wp-block-heading">4.1. Open TF6420 Configurator</h3>



<p class="wp-block-paragraph">After activating the configuration, the state machine should be looping through and inserting data into our table. We can check this by opening up the TF6420 Configurator application.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="707" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configurator.png" alt="" class="wp-image-34752" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configurator.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configurator-300x245.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-configurator-768x627.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">The database server and configuration should already be added from our steps to install the database server. If not, refer to the&nbsp;Adding the Database Project to a TwinCAT 3 Solution section.</p>



<h3 id="h-4-2-execute-a-sql-select-query" class="wp-block-heading">4.2. Execute a SQL Select Query</h3>



<p class="wp-block-paragraph">Open the SQL Query Editor.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="316" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-query-editor.png" alt="" class="wp-image-34753" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-query-editor.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-query-editor-300x109.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-query-editor-768x280.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">You should see a list of the SQL databases available from the DB configuration pool. You can click the refresh button if there are no databases currently connected. If that doesn&#8217;t work, make sure you&#8217;ve gone through the above steps and the configuration is activated.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="369" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-databases.png" alt="" class="wp-image-34754" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-databases.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-databases-300x128.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-sql-databases-768x327.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">Drop down the database to see all the available tables. You can right click on the table you&#8217;re writing to and click Select.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="406" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-select-table.png" alt="" class="wp-image-34755" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-select-table.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-select-table-300x141.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-select-table-768x360.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">You can see that TF6420 has auto-generated a select statement for you. If you press the FB_SQLCommandEvt.ExecuteDataReturn button, you should see datasets populate in the results field to the right.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="866" height="383" src="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-execute-sql-statement.png" alt="" class="wp-image-34756" srcset="https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-execute-sql-statement.png 866w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-execute-sql-statement-300x133.png 300w, https://static.dmcinfo.com/wp-content/uploads/2024/05/tf6420-execute-sql-statement-768x340.png 768w" sizes="(max-width: 866px) 100vw, 866px" /></figure>



<p class="wp-block-paragraph">If these are the values you&#8217;re sending to the database then the database server is communicating properly!</p>



<p class="wp-block-paragraph">For more information on some of the topics covered in this blog, please see the following:</p>



<ul class="wp-block-list">
<li><a href="https://infosys.beckhoff.com/content/1033/tf6420_tc3_database_server/index.html?id=3802295219214861788" target="_blank" rel="noreferrer noopener">TF6420 Database Server Infosys Page</a></li>



<li><a href="https://infosys.beckhoff.com/content/1033/tf6420_tc3_database_server/2674353931.html?id=997028420171989533" target="_blank" rel="noreferrer noopener">SQL Expert Mode Function Block Infosys Page</a></li>



<li><a href="https://www.postgresql.org/docs/" target="_blank">PostgreSQL Documentation</a></li>



<li><a href="https://static.dmcinfo.com/blog/19695/getting-started-with-a-beckhoff-plc-part-one-setup/">Getting Started with a Beckhoff PLC</a></li>
</ul>



<p class="wp-block-paragraph">For information that was not discussed directly in this blog&nbsp;but could be good next steps, please see the following:</p>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/blog/26400/ms-sql-stored-procedures-directly-from-beckhoff-twincat-plc/">MS SQL Stored Procedures Directly from Beckhoff TwinCAT PLC</a></li>



<li><a href="https://static.dmcinfo.com/blog/17976/getting-started-with-opc-ua-in-beckhoff-twincat-3/">Getting Started with OPC UA in Beckhoff TwinCAT 3</a></li>



<li><a href="https://static.dmcinfo.com/blog/16708/sql-server-performance-troubleshooting/">SQL Server Performance Troubleshooting</a></li>



<li><a href="https://infosys.beckhoff.com/content/1033/tf6420_tc3_database_server/5875128203.html?id=7303488825076816628" target="_blank" rel="noreferrer noopener">NoSQL Expert mode Function Block Infosys Page</a></li>
</ul>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Connect TwinCAT 3 Directly to Your Database</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Explore our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/" data-type="page" data-id="420">Automation</a> expertise in <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming/" data-type="page" data-id="457">Beckhoff TwinCAT 3</a>, TF6420 Database Server, PostgreSQL, and PLC-based SQL integration.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16328/getting-started-with-database-server-in-beckhoff-twincat-3/">Getting Started with Database Server in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Beckhoff OOP: Part One &#8211; Methods and Properties</title>
		<link>https://static.dmcinfo.com/blog/17364/beckhoff-oop-part-one-methods-and-properties/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 21:36:25 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[Methods]]></category>
		<category><![CDATA[Object-Oriented]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Properties]]></category>
		<category><![CDATA[TwinCAT]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17364/beckhoff-oop-part-one-methods-and-properties/</guid>

					<description><![CDATA[<p>Welcome to the first blog in this&#160;series on Beckhoff Object-Oriented Programming (OOP). OOP&#160;enables code to be divided into self-contained, reusable objects, resulting in code that is easier to understand, maintain, and update. Throughout this series, the reasons behind this advantage will hopefully become evident and clear. Beckhoff has a set of&#160;examples that will occasionally be [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17364/beckhoff-oop-part-one-methods-and-properties/">Beckhoff OOP: Part One &#8211; Methods and Properties</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Welcome to the first blog in this&nbsp;series on Beckhoff Object-Oriented Programming (OOP).</p>



<p class="wp-block-paragraph">OOP&nbsp;enables code to be divided into self-contained, reusable objects, resulting in code that is easier to understand, maintain, and update. Throughout this series, the reasons behind this advantage will hopefully become evident and clear.</p>



<p class="wp-block-paragraph">Beckhoff has a set of&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/7623882635.html?id=4094185901331026706" target="_blank" rel="noreferrer noopener">examples</a> that will occasionally be referenced throughout this series.</p>



<p class="wp-block-paragraph">Object oriented programming exists of 4 pillars:</p>



<ol class="wp-block-list">
<li><strong>Encapsulation</strong>: Encapsulation refers to the grouping of data (variables, properties) and functions (methods, function blocks) into a single unit called an object. The single object allows for the internal code to be hidden from the application code.</li>



<li><strong>Inheritance</strong>: Inheritance allows objects to inherit properties and functions from other objects. This allows for code to be reused even if the logic is not exactly the same.</li>



<li><strong>Polymorphism</strong>: Polymorphism means the ability of objects to take on different forms or exhibit different behaviors based on the context. This is useful for devices that have very similar functions, but the processes for how they are completed are very different. </li>



<li><strong>Abstraction</strong>: Abstraction involves simplifying complex systems by breaking them down into more manageable and understandable parts. It focuses on only the essential properties and behaviors of an object while hiding the unnecessary details. </li>
</ol>



<p class="wp-block-paragraph">Beckhoff provides several different tools that can be used to achieve these four pillars. Throughout this series, it will be pointed out how each tool correlates to the four pillars.</p>



<p class="wp-block-paragraph">This first blog will touch on two basic principles of OOP, methods and properties.</p>



<h2 class="wp-block-heading" id="h-methods">Methods</h2>



<p class="wp-block-paragraph"><a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/2530307467.html?id=770088965081884469" target="_blank">Methods</a>&nbsp;are&nbsp;actions that an object can perform, while <em>encapsulating </em>the details of how an object performs its tasks. Methods specify the behavior or actions that objects can perform, <em>abstracting </em>the implementation details and providing a clean interface for interacting with objects.</p>



<p class="wp-block-paragraph">Methods can perform operations, manipulate data, and they may or may not return a value depending on their implementation. As for what a method should return, this depends largely on whether the method will be completed in one scan or not. For example, commanding a conveyor to move 10 feet will take more than one scan. However, determining the value of a sensor only takes one scan.</p>



<p class="wp-block-paragraph">In addition, there are different access modifiers for methods, with the two main ones being <strong><code>PUBLIC</code></strong> and <strong><code>PRIVATE</code></strong>. Public versus private determines whether the method can be called outside of the program or function block.&nbsp;There are two additional modifiers:&nbsp;<strong><code>PROTECTED</code></strong>, which allows any function block that inherits the function block&nbsp;to access the method&nbsp;(more on that in future blogs) and <strong><code>INTERNAL</code></strong>, which restricts access to objects in the library.</p>



<p class="wp-block-paragraph">In the example of commanding a conveyor to move 10 feet, the method may return a standard response that can be used in&nbsp;an application. This should be public because function blocks outside of the conveyor will need to call this.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
TYPE ST_Response 
STRUCT
    bComplete : BOOL;
    bError : BOOL;
END_STRUCT
END_TYPE
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">TYPE</span><span style="color: #D4D4D4"> ST_Response </span></span>
<span class="line"><span style="color: #D4D4D4">STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">    bComplete : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    bError : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">END_STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">END_TYPE</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
METHOD PUBLIC MoveDistance : ST_Response
VAR_INPUT
    Distance : LREAL; // feet 
END_VAR
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PUBLIC</span><span style="color: #D4D4D4"> MoveDistance : ST_Response</span></span>
<span class="line"><span style="color: #D4D4D4">VAR_INPUT</span></span>
<span class="line"><span style="color: #D4D4D4">    Distance : LREAL; </span><span style="color: #6A9955">// feet </span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">When the method has completed, the state machine can then be moved to the next step. If it encounters an error during the process, the application can enter its error handling sequence.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
E_State.MOVE_CONVEYOR:
    respone := fbConveyor.MoveDistance(10); // move 10 feet
    
    IF respone.bComplete THEN
        eState := E_State.RUN_MACHINE;
    ELSIF respone.bError THEN
        eState := E_State.ERROR;
    END_IF
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D4D4D4">E_State.MOVE_CONVEYOR:</span></span>
<span class="line"><span style="color: #D4D4D4">    respone := fbConveyor.MoveDistance(</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">); </span><span style="color: #6A9955">// move 10 feet</span></span>
<span class="line"><span style="color: #D4D4D4">    </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> respone.bComplete </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">        eState := E_State.RUN_MACHINE;</span></span>
<span class="line"><span style="color: #D4D4D4">    ELSIF respone.bError </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">        eState := E_State.ERROR;</span></span>
<span class="line"><span style="color: #D4D4D4">    END_IF</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">An example of a method that takes one scan is&nbsp;calculating the torque of the conveyor. For calculating torque, it is often useful to implement a moving average or filter to smooth out any noise in the data. For example, a&nbsp;method can do all of the math inside and return the value in terms of foot-pounds. This would be an example of a private method because only the conveyor function block should be calling this. The torque could be accessed outside of the function block via a property, for example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// foot-pounds
METHOD PRIVATE CalculateTorque : REAL
VAR_INPUT
    rActualTorque : REAL; //0.1% of max torque 
END_VAR
VAR_INST
    fbMovingAverage : FB_MovingAverage;
END_VAR
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// foot-pounds</span></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIVATE</span><span style="color: #D4D4D4"> CalculateTorque : </span><span style="color: #569CD6">REAL</span></span>
<span class="line"><span style="color: #D4D4D4">VAR_INPUT</span></span>
<span class="line"><span style="color: #D4D4D4">    rActualTorque : </span><span style="color: #569CD6">REAL</span><span style="color: #D4D4D4">; </span><span style="color: #6A9955">//0.1% of max torque </span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span>
<span class="line"><span style="color: #D4D4D4">VAR_INST</span></span>
<span class="line"><span style="color: #D4D4D4">    fbMovingAverage : FB_MovingAverage;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Another very common return type is simply a BOOL. Of course, a BOOL can mean many things (sensor state, method complete successfully, etc.), so be sure to comment on what the return value means if it is not obvious!</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// true = enable successful, false = interlocks active 
METHOD PUBLIC Enable : BOOL
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// true = enable successful, false = interlocks active </span></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PUBLIC</span><span style="color: #D4D4D4"> Enable : BOOL</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Methods can also serve as a way of organizing code and maintaining readability in application code. This is an example of when a return is not needed. The following excerpt is taken from the OOP Extended Sample.&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// Call of actions

    // Init
    General_Init();

    // Mode and state requests
    General_Requests();
    
    // Enable for power supply, compressed air control and buttons
    General_Enable();
    
    // Input variables of separating and sorting modules
    General_ModuleInputs();
    
    // Output variables
    General_SetOutput();
    ...
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// Call of actions</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Init</span></span>
<span class="line"><span style="color: #D4D4D4">    General_Init();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Mode and state requests</span></span>
<span class="line"><span style="color: #D4D4D4">    General_Requests();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Enable for power supply, compressed air control and buttons</span></span>
<span class="line"><span style="color: #D4D4D4">    General_Enable();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Input variables of separating and sorting modules</span></span>
<span class="line"><span style="color: #D4D4D4">    General_ModuleInputs();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Output variables</span></span>
<span class="line"><span style="color: #D4D4D4">    General_SetOutput();</span></span>
<span class="line"><span style="color: #D4D4D4">    ...</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
METHOD PRIVATE General_Init
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIVATE</span><span style="color: #D4D4D4"> General_Init</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">A really powerful feature of Beckhoff is the ability to <a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/7145472907.html?id=6105454089919227750" target="_blank">call methods</a> via ADS. This, in turn, makes methods&nbsp;able to be called via OPCUA.&nbsp;Head on over to our <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10396/getting-started-with-opc-ua-in-beckhoff-twincat-3">blog</a>&nbsp;about setting up an OPCUA server if you have not already done so!</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
{attribute 'TcRpcEnable'}
METHOD PUBLIC MoveDistance : ST_Response
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">{attribute &apos;TcRpcEnable&apos;}</span></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PUBLIC</span><span style="color: #D4D4D4"> MoveDistance : ST_Response</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Here, I am using UaExpert to call the method.&nbsp;</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/CallMethod.png" alt=""/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/MethodResponse.png" alt=""/></figure>



<p class="wp-block-paragraph">This can make testing extremely efficient. No need to add debug bits to test your code, just call the method that is being tested!</p>



<p class="wp-block-paragraph">Another Beckhoff-specific implementation of a method is <a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/5094414603.html?id=6967794353598129051" target="_blank" rel="noreferrer noopener">FB_init</a>. This allows for initialization of the function block before it is called. A simple use case for this is when project variants are used (another plug for one of our <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10299/twincat-project-variants">blogs</a>!). Different initialized values can be used depending on the variant selected. For example, in the Simulation variant, the default conveyor speed is set to the maximum value to speed up any testing that is needed. Another common use case is initializing pointers and references to be used during runtime.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
METHOD FB_init : BOOL
VAR_INPUT
    bInitRetains : BOOL; 
    bInCopyCode : BOOL;  
END_VAR
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">METHOD</span><span style="color: #D4D4D4"> FB_init : BOOL</span></span>
<span class="line"><span style="color: #D4D4D4">VAR_INPUT</span></span>
<span class="line"><span style="color: #D4D4D4">    bInitRetains : BOOL; </span></span>
<span class="line"><span style="color: #D4D4D4">    bInCopyCode : BOOL;  </span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
{IF defined(Simulation)}
    lrSpeedSetpoint := MAX_SPEED;
{ELSE}    
    lrSpeedSetpoint := 100;
{END_IF}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">{IF defined(Simulation)}</span></span>
<span class="line"><span style="color: #D4D4D4">    lrSpeedSetpoint := MAX_SPEED;</span></span>
<span class="line"><span style="color: #6A9955">{ELSE}</span><span style="color: #D4D4D4">    </span></span>
<span class="line"><span style="color: #D4D4D4">    lrSpeedSetpoint := </span><span style="color: #B5CEA8">100</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #6A9955">{END_IF}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Obviously, this is just scratching the surface of what methods can do. There are varying schools of thought on how much logic a method should contain. Some implementations of methods simply move state machines from one state to another; other implementations may contain an entire sequencer inside a state. This depends on the architecture of the project.</p>



<p class="wp-block-paragraph">DMC is happy to discuss the implementation of your project and help decide which implementation of methods will work best for you!&nbsp;</p>



<h2 class="wp-block-heading" id="h-properties">Properties</h2>



<p class="wp-block-paragraph">Moving onto properties, a <a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/2530335371.html?id=7678313929092874522" target="_blank">property</a>&nbsp;is an object attribute that <em>encapsulates </em>data and provides a controlled way to access or modify the data associated with it. Properties allow you to expose the internal state of an object while enforcing rules and logic for data access.</p>



<p class="wp-block-paragraph">Properties are implemented using getter and setter methods. A getter is a method used to retrieve the value of a private attribute of an object. A setter is a method used to modify the value of a private attribute of an object.</p>



<p class="wp-block-paragraph">Properties have&nbsp;the same access modifiers as the methods described above.</p>



<p class="wp-block-paragraph">A simple example of this would be the speed setpoint of the previously mentioned conveyor.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// ft/min
PROPERTY PUBLIC lrSpeedSetpoint : LREAL
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// ft/min</span></span>
<span class="line"><span style="color: #569CD6">PROPERTY</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">PUBLIC</span><span style="color: #D4D4D4"> lrSpeedSetpoint : LREAL</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The setter can have conditions to make sure the speed is set within the proper bounds. In this example, a negative number is rejected, and a speed greater than the maximum is set to the maximum speed. The getter simply returns the speed here; however, a getter could convert a raw signal into a useful value, for example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// "Set"
IF lrSpeedSetpoint >= 0 THEN
    _lrSpeedSetpoint := SEL(lrSpeedSetpoint > MAX_SPEED, lrSpeedSetpoint, MAX_SPEED);
END_IF
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// &quot;Set&quot;</span></span>
<span class="line"><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> lrSpeedSetpoint &gt;= </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">    _lrSpeedSetpoint := SEL(lrSpeedSetpoint &gt; MAX_SPEED, lrSpeedSetpoint, MAX_SPEED);</span></span>
<span class="line"><span style="color: #D4D4D4">END_IF</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// "Get" 
lrSpeedSetpoint := _lrSpeedSetpoint;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// &quot;Get&quot; </span></span>
<span class="line"><span style="color: #D4D4D4">lrSpeedSetpoint := _lrSpeedSetpoint;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">To access properties, the following should be used:&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// Access "Set" 
fbConveyor.lrSpeedSetpoint := 100; // 100 ft/min
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// Access &quot;Set&quot; </span></span>
<span class="line"><span style="color: #D4D4D4">fbConveyor.lrSpeedSetpoint := </span><span style="color: #B5CEA8">100</span><span style="color: #D4D4D4">; </span><span style="color: #6A9955">// 100 ft/min</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">ST</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
// Access "Get" 
lrConveyorSpeedSetpoint:= fbConveyor.lrSpeedSetpoint;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955">// Access &quot;Get&quot; </span></span>
<span class="line"><span style="color: #D4D4D4">lrConveyorSpeedSetpoint:= fbConveyor.lrSpeedSetpoint;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">If a property does not need either the getter or the setter, it can simply be deleted.</p>



<p class="wp-block-paragraph">From my personal experience, I have not seen properties used a ton. There are some specific situations where they are useful, but often there are several different ways to achieve the same functionality. Methods, on the other hand, are essential to building an OOP-based project.</p>



<p class="wp-block-paragraph">Look out for part 2, interfaces, coming soon!</p>



<p class="wp-block-paragraph"><strong>Learn more about DMC&#8217;s&nbsp;<a href="/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">Beckhoff and TwinCAT 3 programming</a>&nbsp;expertise and&nbsp;<a href="/contact">contact us</a>&nbsp;for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17364/beckhoff-oop-part-one-methods-and-properties/">Beckhoff OOP: Part One &#8211; Methods and Properties</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</title>
		<link>https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Tue, 07 Mar 2023 11:37:39 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[EAP]]></category>
		<category><![CDATA[Ethernet IP]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[PLC Communication]]></category>
		<category><![CDATA[TwinCAT]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/</guid>

					<description><![CDATA[<p>Beckhoff&#8217;s Industrial Personal Computers (IPCs) allow for easy configuration into a wide variety of PLC-to-PLC communications. Internal links between IPCs running TwinCAT XAR are the simplest and will be the first that this series of articles explore. This article demonstrates a holistic approach to establishing a connection between two&#160;Beckhoff IPCs. IPC Configuration: All PLCs mentioned [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/">Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Beckhoff&rsquo;s Industrial Personal Computers (IPCs) allow for easy configuration into a wide variety of PLC-to-PLC communications. Internal links between IPCs running TwinCAT XAR are the simplest and will be the first that this series of articles explore.</p>

<p class="wp-block-paragraph">This article demonstrates a holistic approach to establishing a connection between two&nbsp;Beckhoff IPCs.</p>

<h2 class="wp-block-heading">IPC Configuration:</h2>

<p class="wp-block-paragraph">All PLCs mentioned are the BECKHOFF C6017 model.</p>

<p class="wp-block-paragraph">In order to &ldquo;discover&rdquo; another PLC, the Beckhoff IPC will need to have its network and port configured to be visible across an ethernet or network connection. In this example I will be using a PLC that is networked to an internal server with 20 to&nbsp;40 other Beckhoff IPCs.</p>

<p class="wp-block-paragraph"><strong><u>Process:</u></strong></p>

<ol class="wp-block-list">
 <li>Connect the Beckhoff IPC to a monitor and peripherals to control the system. This specific model calls for a Display Port (DP) connection and any USB integrated keyboard and mouse.</li>
</ol>

<ol class="wp-block-list" start="2">
 <li>Sign into the IPC. If no configuration has been set, this will be Beckhoff&rsquo;s default login:
 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li>Username: ADMINISTRATOR</li>
  <li>Password: 1</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="3">
 <li>If this is your first time accessing the PLC, click&nbsp;<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Install%20Software" target="_blank">HERE</a>&nbsp;for a step-by-step setup process.

 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li><strong>IMPORTANT</strong>: make sure to follow step 8 for the appropriate firewall settings.</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="4">
 <li>Like <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Install RTE Driver">step 6</a> in the linked article, we need to install the Beckhoff Real-Time Ethernet Driver for our networked port.

 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li>Regardless of whether you use direct or networked ethernet communication, this driver will&nbsp;need to be installed on the appropriate ethernet port.</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="5">
 <li>Navigate to&nbsp;<strong>C:\TwinCAT\3.1\System</strong>&nbsp;and run&nbsp;<strong>TcRteInstall.exe:</strong></li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><strong><img decoding="async" alt="TcRteInstall_Location" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TCREInstall.png"  /></strong></p>

<ol class="wp-block-list" start="6">
 <li>Install the driver onto the Networked port. For a networked connection, the IPv4 properties found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Changing NIC Settings">step 2</a> of the linked article will need to include an appropriate IP address, subnet mask, and gateway to the local server.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="IPv4_Properties" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/IPv4-protocol.png"  /></p>

<p class="wp-block-paragraph" style="text-align: center;"><em>Note: if you as a user also have access to this internal network through local access or a VPN, you can program the PLC from this networked port and no longer need a physical connection to the IPC.</em></p>

<ol class="wp-block-list" start="7">
 <li>With the correct configuration of your IPv4&nbsp;network properties, you should be able to discover other devices on the server.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="IPC_Ping_Test" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Ping.png"  /></p>

<ol class="wp-block-list" start="8">
 <li>Next, we need to set the AMS NetId to partner with the expected service. This step will ensure that there are no conflicting communication paths between PLCs. At DMC&nbsp;these are typically set to the PLC IP address and extended with a .1.1, as seen below, to match the expected 6-byte TwinCAT network ID.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="AMS_NetID_set_1" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ams1.png"  /><img decoding="async" alt="AMS_NetID_set_2" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ams2.png"  /></p>

<h2 class="wp-block-heading">TwinCAT XAE&nbsp;Configuration:</h2>

<p class="wp-block-paragraph">We can now migrate to the TwinCAT XAE environment and begin&nbsp;creating EAP masters through the networked ports on the IPC, as shown above or by using the EL-6601 or EL-6614 hardware options, which extend the IPCs available ethernet ports.</p>

<p class="wp-block-paragraph" style="text-align: center;"><em>Note: the EL-6652 supports Ethernet/IP communication to other PLC platforms and will be covered in a future blog. &nbsp;&nbsp;&nbsp;</em></p>

<p class="wp-block-paragraph"><strong><u>TwinCAT XAE EtherCAT Automation Protocol (EAP) Setup:</u></strong></p>

<p class="wp-block-paragraph">For this tutorial, we will be using the EAP Master that is linked to an internal IPC network port.</p>

<ol class="wp-block-list">
 <li>Begin by right-clicking on Devices in the IO tree here:</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Add_a_EAP_Master" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/EAP1.png"  /></p>

<p class="wp-block-paragraph">&nbsp; &nbsp; &nbsp; &nbsp;2. Then, select the EAP Master:</p>

<p class="wp-block-paragraph" style="margin-left: 40px; text-align: center;"><img decoding="async" alt="EAP_Master_2" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Eap2.png"  /></p>

<p class="wp-block-paragraph">Once instantiated, the box is ready to set up publishers and subscribers. Publishers can &ldquo;publish&rdquo; or send data out across an EAP connection while subscribers will&nbsp;&ldquo;subscribe&rdquo; and listen for that data. These can be instantiated by right-clicking on the EAP master and adding a new device.</p>

<p class="wp-block-paragraph"><u><strong>Publishers:</strong></u></p>

<p class="wp-block-paragraph">There are a few ways to set up the communication bridge. At DMC, the two most common are the UDP/IP Unicast and&nbsp;the RT-Ethernet Unicast with the AMS NetId. Unless you are using multicast, it will be one box per PLC to PLC connection.</p>

<ol class="wp-block-list">
 <li>To publish with UDP, specify the Unicast destination which is the Networked IP address of the desired IPC and the default gateway hosting the server traffic.</li>
</ol>

<p class="wp-block-paragraph">&nbsp;</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="UDP_Unicast" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Casting1.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">2. To publish with RT-Ethernet, set the AMS NetId of the subscriber. This requires the two networked IPCs to be on the same server and discoverable by one another.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="RT_Casting" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/RTCast2_1.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">3. Regardless of your chosen method, you can now instantiate networked variables to publish from your boxes. To do this, right click on the publisher box and select &apos;add new item&apos;. Then, configure the data you need to send.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Insert_Network_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Network-Variable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">4.Next, link the instantiated publisher variable data to the PLC variable you wish to send out within the outputs sub-selection on the publisher box:</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Data_Link" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Linking.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">5.Continue this process for all the variables you wish to use in EAP communication, and then activate the configuration to change the memory space.</p>

<p class="wp-block-paragraph"><u><b>Subscribers:</b></u></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">1.Similar to publishers on an EAP Master, add a new item and select Network Variable Subscriber.</p>

<p class="wp-block-paragraph" style="margin-left: 40px;">2. There are a couple of options for adding subscriber variables. The easiest is to browse for computers. This requires the RT-Ethernet setup on the publisher. To do so, right click on the subscriber box and select &apos;add new item&apos;. Then, select &apos;browse for computer.&apos;</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Import_Network_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Networkvariable2.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">3. Add the appropriate dialog route for your search, and establish the connection.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Connect_to_the_PLC" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ConnectToPLC.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">4. After establishing a connection, the published variables will populate to the network variables list.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Select_A_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/SelectVariable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">5. Select the variables you wish to subscribe to, and link them to subscriber IPC inputs to use in logic. Note that the quality tag can be used as a heartbeat monitor and that a value of 0 is a successful connection. Activate the configuration and check to see if the connection is present.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Linked_Subscriber" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkedVariable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">6. For the UDP Unicast Publisher, set up the subscriber to receive from any publisher because the publisher is providing the IPC pointing. Then, instead of browsing&nbsp;for a computer, use &apos;create a new variable,&apos; and give it the definition the publisher is providing whether that be INT, BOOL, or any other data type.</p>

<p class="wp-block-paragraph" style="margin-left: 40px;">7. Next, in the subscribe tab of the new variable, provide the expected publisher variable ID and link like in step 5. This will also come with a quality check for the connection state.</p>

<p class="wp-block-paragraph">Now that the publisher and subscriber have achieved a connection, the networked variables and connection quality are available to the subscriber PLC to use in any desired logic.</p>

<p class="wp-block-paragraph"><strong>Learn more about DMC&apos;s <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">Beckhoff and TwinCAT Programming</a> expertise and <a href="https://static.dmcinfo.com/contact">contact us</a> for your next project.&nbsp;</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/">Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting Started with OPC UA in Beckhoff TwinCAT 3</title>
		<link>https://static.dmcinfo.com/blog/17976/getting-started-with-opc-ua-in-beckhoff-twincat-3/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Thu, 15 Dec 2022 10:15:37 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[OPC UA]]></category>
		<category><![CDATA[TwinCAT]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17976/getting-started-with-opc-ua-in-beckhoff-twincat-3/</guid>

					<description><![CDATA[<p>Table of Contents 1. Introduction OPC UA (short for Open Platform Communications Unified Architecture) is a client/server technology used for data exchange in industrial applications, commonly used for machine-to-machine and&#160;PC-to-machine communication. Because of its versatility, OPC UA was adopted in a variety of industries such as the automotive, food and beverage, gas and oil, energy [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17976/getting-started-with-opc-ua-in-beckhoff-twincat-3/">Getting Started with OPC UA in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-table-of-contents">Table of Contents</h2>



<ol class="wp-block-list">
<li><a href="#h-introduction">Introduction</a></li>



<li><a href="#h-2-things-you-ll-need-to-download-and-install">Things You’ll Need to Download and Install</a></li>



<li><a href="#h-3-step-by-step-procedure">Step by Step Procedure</a></li>



<li><a href="#h-4-notes-on-security">Notes on Security</a></li>
</ol>



<h2 class="wp-block-heading" id="h-1-introduction">1. Introduction</h2>



<p class="wp-block-paragraph">OPC UA (short for Open Platform Communications Unified Architecture) is a client/server technology used for data exchange in industrial applications, commonly used for machine-to-machine and&nbsp;PC-to-machine communication. Because of its versatility, OPC UA was adopted in a variety of industries such as the automotive, food and beverage, gas and oil, energy and utilities, and packaging industries. It can also be used in applications ranging from embedded components to cloud servers.</p>



<p class="wp-block-paragraph">Setting up an OPC UA server in Beckhoff is very simple and can allow you to connect your Beckhoff project to other software, like Ignition and other SCADA platforms. This guide will teach you how to set up an OPC UA server on your programming PC or your Beckhoff IPC and set up your TwinCAT project to display tags from that server.</p>



<p class="wp-block-paragraph">For this demonstration, we will be connecting to an OPC UA server on our local Windows 10 machine, but the process should be similar for connecting to an OPC UA server on a remote machine like a Beckhoff IPC, with just a few additional steps to allow that server to be accessed on whichever network you’re using.</p>



<h2 class="wp-block-heading" id="h-2-things-you-ll-need-to-download-and-install">2. Things You’ll Need to Download and Install</h2>



<h3 class="wp-block-heading" id="h-2-1-twincat">2.1 TwinCAT</h3>



<ul class="wp-block-list">
<li><strong>2.1.1. TwinCAT XAE Shell<br></strong>This is where the PLC will be set up, code will be written, and other settings will be chosen. If you’re looking for this guide, you most likely have TwinCAT installed. Otherwise, you can download it from <a href="https://www.beckhoff.com/en-us/support/download-finder/" target="_blank" rel="noreferrer noopener">Beckhoff’s Website</a>.</li>



<li><strong>2.1.2. TwinCAT XAR Runtime<br></strong>XAR is used to run TwinCAT on a Beckhoff IPC, and we&#8217;ll need to install it on the end PLC if we&#8217;re not installing XAE on that machine. This means that this download is only necessary if you intend to host your OPC server on a different machine than your programming PC. You will still need to get TwinCAT XAE on your programming PC. XAR can also be downloaded from <a href="https://www.beckhoff.com/en-us/support/download-finder/" target="_blank" rel="noreferrer noopener">Beckhoff’s Website</a>.</li>
</ul>



<h3 class="wp-block-heading" id="h-2-2-nbsp-tf6100-twincat-3-opc-ua-server-and-configurator">2.2.&nbsp;TF6100 | TwinCAT 3 OPC UA Server and Configurator</h3>



<p class="wp-block-paragraph">These are necessary to actually create the OPC UA Server and initialize it. The OPC UA Server is the actual runtime program, while the OPC UA Configurator is only needed to initialize the server. TF6100 includes two other products that are not required to set up the server (OPC UA Gateway and OPC UA Client). They&nbsp;won’t be used in this guide, but can be installed to facilitate the use of the OPC UA server, depending on the application. These applications need a license, but they do have a trial you can activate from TwinCAT. These applications can also be found on the <a href="https://www.beckhoff.com/en-us/products/automation/twincat/" target="_blank" rel="noreferrer noopener">Beckhoff Website</a>.</p>



<h3 class="wp-block-heading" id="h-2-3-any-opc-ua-tester">2.3 Any OPC UA Tester</h3>



<p class="wp-block-paragraph">This is useful to test that our tags created in TwinCAT are actually findable in the OPC Server. You can use UaExpert, Ignition, or Beckhoff’s OPC UA Client. Anything that can connect to an OPC Server and see its contents will be enough.</p>



<h2 class="wp-block-heading" id="h-3-step-by-step-procedure">3. Step by Step Procedure</h2>



<p class="wp-block-paragraph">First, install the above software in the following locations:</p>



<p class="wp-block-paragraph">Programming Computer: the computer you&#8217;ll do your programming on.</p>



<ul class="wp-block-list">
<li>TwinCAT XAE</li>



<li>OPC UA Configurator</li>



<li>OPC UA Test Client (optional)</li>
</ul>



<p class="wp-block-paragraph">Runtime Device: the device you&#8217;ll be running the OPC UA server on. It could be your programming computer (for testing) or a Beckhoff IPC.</p>



<ul class="wp-block-list">
<li>TwinCAT XAR (if this runtime device does not have TwinCAT XAE installed on it)</li>



<li>OPC UA Server</li>



<li>OPC UA Test Client (optional)</li>
</ul>



<p class="wp-block-paragraph">Next, open TwinCAT XAE, and either load an existing project with a PLC or start a new TwinCAT Project. Under SYSTEM, double click License. If you have a license for the TF6100, it will be shown as in the picture below. </p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1_License_for_the_TF6100.png" alt="License for the TF6100"/></figure>



<p class="wp-block-paragraph">If you don’t have a license, you can go to the <strong>Manage Licenses</strong> tab and check the CPU license checkmark for the TF6100. Go back to the <strong>Order information</strong> tab and select <strong>7-Day Trial License.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2_Manage_Licenses_1.png" alt="Manage Liceses"/></figure>



<p class="wp-block-paragraph">Once this is done, save your project, close TwinCAT, and then <strong>RESTART YOUR PC/VM. The OPC UA Server software won’t work until after a restart. </strong>You can tell that the OPC UA server is running by an icon in the bottom right of the Windows tray.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3_OPC_UA_Server_is_running_icon.png" alt="OPC UA Server is running icon"/></figure>



<p class="wp-block-paragraph">Once you make sure the OPC UA Server is running, you will need to initialize the server. Open the OPC UA configurator and click <strong>Edit&gt;Get Endpoints</strong>, followed by <strong>Add</strong>, once the configurator has found the endpoints<strong>.</strong> If you’re performing this step from the same machine as the server, you can use <strong>opc.tcp:https://static.dmcinfo.com/</strong> as the server URL.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4_TwinCAT_OPC_UA_Configurator_Edit.png" alt="TwinCAT OPC UA Configurator Edit"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5_Configured_TwinCAT_OPC_UA_Servers.png" alt="Configured TwinCAT OPC UA Servers"/></figure>



<p class="wp-block-paragraph">Once you add the server, it should look something like this. If the configurator can’t find the endpoints, you should verify that&nbsp;the server is running by checking the Windows tray bar.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6_Server_is_running_Windows_tray_bar.png" alt="Server is running Windows tray bar"/></figure>



<p class="wp-block-paragraph">Go back to the main page of the configurator and click&nbsp;<b data-stringify-type="bold">Connect</b>. This should cause a pop-up to choose an Operating system user account for the server. For now, fill in the OS credentials for your IPC or VM. You’ll be able to add more users later. Once you fill those out, the server should initialize. Click&nbsp;<b data-stringify-type="bold">Connect</b>&nbsp;once more to make sure you can connect to the server</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7_Server_initialization.png" alt="Server initialization"/></figure>



<p class="wp-block-paragraph">Next, open TwinCAT again, right-click your PLC project, and check the “Autostart Boot Project.” This will avoid some pop-ups and ensure the PLC runs smoothly once it starts.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8_Autostart_Boot_Project.png" alt="Autostart Boot Project"/></figure>



<p class="wp-block-paragraph">Next, double click the PLC project (Untitled1 in the example) and go to the “Settings” tab. <strong><u>CHECK THE “TMC FILE” OPTION</u>. </strong>TwinCAT Module Class (.tmc files) contains the symbol information necessary for the our tags to be accessible via the OPC Server.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9_TMC_File_option.png" alt="TMC File options"/></figure>



<p class="wp-block-paragraph">Next, inside your MAIN program, make the changes you want. If you just want to test the OPC UA server, you can test it using the program below, which should flip the test variable from TRUE to FALSE every second.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Pascal</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>PROGRAM MAIN
VAR
	{attribute 'OPC.UA.DA' := '1'} 
	hi:BOOL;
	timer: ton;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">PROGRAM</span><span style="color: #D4D4D4"> MAIN</span></span>
<span class="line"><span style="color: #569CD6">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #6A9955">{attribute &apos;OPC.UA.DA&apos; := &apos;1&apos;}</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">	hi:BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">	timer: ton;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Pascal</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>timer(IN := NOT timer.Q, PT := T#1S) ;
IF timer.Q THEN
	hi := NOT hi;
END_IF</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">timer(</span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> := </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> timer.Q, PT := T</span><span style="color: #CE9178">#1</span><span style="color: #D4D4D4">S) ;</span></span>
<span class="line"><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> timer.Q </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">	hi := </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> hi;</span></span>
<span class="line"><span style="color: #D4D4D4">END_IF</span></span></code></pre></div>



<p class="wp-block-paragraph">Notice the line <u><strong>{attribute ‘OPC.UA.DA’ := ‘1’}</strong></u><strong>. </strong><strong>This line is necessary to expose any variables to the OPC UA Server. </strong>If you would like to specify read/write permissions, you can use the following line: <strong>{attribute &#8216;OPC.UA.DA.Access&#8217; := &#8216;x&#8217;}</strong>, where x = 1 will be read-only, x = 2 will be write access only, and x = 3 will be read and write access (the default option if this attribute is not specified).</p>



<p class="wp-block-paragraph">Once you’re done writing your code, <strong>activate the configuration</strong> with the button shown in the image below. Your project/tags will not show up on the server otherwise. You’ll want to activate the configuration every time you add new tags that are exposed to OPC UA. This will both download your code and restart the OPC UA Server, which must be done for new tags to show up. Alternatively, you can download/make online changes to your code and restart the OPC UA server using the server’s Windows tray icon.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10_activate_the_configuration_button.png" alt="Activate the configuration button"/></figure>



<p class="wp-block-paragraph">Once this is done, login, and run your code.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11_login.png" alt="Login"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12_run_the_code.png" alt="Run the code"/></figure>



<p class="wp-block-paragraph">After this, the server should be up and running, and your tags should be visible. If you are using UaExpert (or your program of choice) on the same machine the server is running, you can connect to it using <strong>opc.tcp:https://static.dmcinfo.com/ </strong>as the endpoint URL. If you’re prompted for credentials, use the ones you chose when initializing the server. After that, click <strong>connect</strong> to verify that your tags show up in the server.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13_14.png" alt="Add Server Hi"/></figure>



<p class="wp-block-paragraph">If you need to access your tags from a different device in your network (for example, if you’re hosting your OPC Server on your IPC, but would like to browse tags via your programming PC), you’ll need to first create a firewall rule to allow for inbound traffic through port 4840 on the device hosting the OPC server. 4840 is the default port for this, but if you’ve configured another port for your OPC UA server to use, you’ll have to open that port instead. Go to <strong>Settings&gt;Windows Security&gt;Firewall &amp; Network Settings&gt;Advanced Settings&gt;Inbound Rules</strong> and add a rule like the images below.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/15_Port.png" alt="Port"/></figure>



<p class="wp-block-paragraph">Select <strong>port</strong> and then <strong>TCP</strong>, add local port <strong>4840,</strong> allow connection, and give it a name.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/16_TCP.png" alt="TCP"/></figure>



<p class="wp-block-paragraph">Once this is done, open UaExpert (or your program of choice) and add a server using <strong>opc.tcp://<em>*OPC Host IP Address*</em>:4840 </strong>as the endpoint URL; the tags should be visible. If this is not the case, restart the computer hosting the server.</p>



<h2 class="wp-block-heading" id="h-4-notes-on-security">4. Notes on Security</h2>



<p class="wp-block-paragraph">This section will briefly touch on how to alter the security settings of your OPC UA server — including adding/removing users, editing current user passwords, changing security policies, and choosing the desired server port. This will all be done through the TF6100 TwinCAT OPC UA Configurator, the same application you used to the initialize server.</p>



<p class="wp-block-paragraph">Open the configurator and select <strong>Edit </strong>on the toolbar.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/17_Edit_1.png" alt="Edit"/></figure>



<p class="wp-block-paragraph">Click <strong>Get Endpoints</strong> followed by <strong>Add</strong>, which should add your server to the list. The result should look something like this</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/18_Get_Endpoints_and_Add.png" alt="Get Endpoints and Add"/></figure>



<p class="wp-block-paragraph">Double-click the name of the server to configure the server connection. Alter the information in the setting to match the ones at your server. If you didn’t change any of these when setting up the server, just fill in your identity (these are the credentials you chose when initializing the server). Click <strong>OK</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/19_OK.png" alt="OK"/></figure>



<p class="wp-block-paragraph">Click <strong>Connect</strong>. This will prompt a user authentication pop-up. Fill in the password you chose when you initialized the server.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/20_user_authentication_password.png" alt="User authentication password"/></figure>



<p class="wp-block-paragraph">Now you should be connected to the server. If the connection fails, double-check that&nbsp;the OPC Server is running by checking for its icon in the Windows tray. If you get an error similar to [BadUserAcessDenied] or [BadIdentityAcessDenied], that means your credentials are not correct.</p>



<p class="wp-block-paragraph">If you intend to add, remove, or edit users, click on the security tab, and then click the <strong>Open From Target</strong> Icon on the toolbar. Your screen should look something like the image below. Right-click on the users box, and select from <strong>Add</strong>, <strong>Remove,</strong> or <strong>Edit</strong>. In this example, we will be adding a new user.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/21_adding_a_new_user_1.png" alt="Adding a new user"/></figure>



<p class="wp-block-paragraph">A user detail pop-up should appear. On this pop-up, you can select the authentication provider from Server (choose any UserName and Password), OS (matches a user and password from your computer), and <strong>Anonymous</strong> (provides no credentials). When applicable, you can also select the username, password, and the member groups: which this user is part of.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/22_user_details.png" alt="User details"/></figure>



<p class="wp-block-paragraph">Once you add the users you desire, click <strong>Activate on Target, </strong>and the new user should be added to the server.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/23_Activate_on_Target.png" alt="Activate on Target"/></figure>



<p class="wp-block-paragraph">If you want to change the server port or the security policy of your server, click on the <strong>Server Settings</strong> tab, where both options should be visible, like the image below. Make sure to <strong>Activate on Target </strong>once you finish making your changes.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/24_TwinCAT_OPC_UA_Configurator.png" alt="TwinCAT OPC UA Configurator"/></figure>



<p class="wp-block-paragraph"><strong>Read more about&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming/">DMC’s Beckhoff and TwinCAT 3&nbsp;Programming</a>, and <a href="https://static.dmcinfo.com/contact/">contact us</a> today for your next project!</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17976/getting-started-with-opc-ua-in-beckhoff-twincat-3/">Getting Started with OPC UA in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Beckhoff XPlanar &#038; XTS</title>
		<link>https://static.dmcinfo.com/blog/18332/beckhoff-xplanar-xts/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Thu, 11 Aug 2022 09:35:59 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Product Development]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[XPlanar]]></category>
		<category><![CDATA[XTS]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18332/beckhoff-xplanar-xts/</guid>

					<description><![CDATA[<p>Earlier this year, Mike Rauch and Chris Mauban of Beckhoff&#160;were kind enough to host us at their Chicago (Woodridge, IL) office to show off some live demos that showcase the latest updates to XPlanar® and the eXtended Transport System® (XTS®).&#160; XPlanar Beckhoff has generated quite a buzz with their new XPlanar system — taking the [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18332/beckhoff-xplanar-xts/">Beckhoff XPlanar &#038; XTS</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Earlier this year, Mike Rauch and Chris Mauban of <a href="https://www.beckhoff.com/en-us/" target="_blank">Beckhoff</a>&nbsp;were kind enough to host us at their Chicago (Woodridge, IL) office to show off some live demos that showcase the latest updates to XPlanar® and the eXtended Transport System® (XTS®).&nbsp;</p>



<h2 class="wp-block-heading" id="h-xplanar">XPlanar</h2>



<p class="wp-block-paragraph">Beckhoff has generated quite a buzz with their new <a href="https://www.beckhoff.com/en-us/products/motion/xplanar-planar-motor-system/" target="_blank">XPlanar system</a> — taking the ability to move product off a conveyor or track and, instead, bringing it to a magnetic tile system with movers that fly above the surface with 6 degrees of freedom.</p>


<div data-oembed-url="https://www.youtube.com/watch?v=On_QL8znZHg*">
<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;"><iframe allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture;" allowfullscreen="" scrolling="no" src="https://www.youtube.com/embed/On_QL8znZHg?rel=0" style="top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0;"></iframe></div>
</div>


<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">New applications and ways to apply the freedom provided by XPlanar are still being discovered; high-end assembly, pharmaceuticals, and laboratory/life science automation are among the popular use cases.</p>



<p class="wp-block-paragraph">The XPlanar movers float and fly above tiles in a contactless manner. They allow two dimensional (X-Y) freedom of movement but can also move up and down in the Z-axis up to 5 mm. The tiles they travel across can be mounted at 90 degree angles or even upside down for some crazy creativity.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/xplanar-tile.png" alt="XPlanar Tile"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>XPlanar Tile</em></p></p>



<p class="wp-block-paragraph">Each mover can travel independently, allowing a lot of parallel multi-tasking and efficiency. They can also spin at up to 600 RPM, acting as a mixer or centrifuge (as shown below).</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/XPlanar-360-mover-rotation-centrifuge.gif" alt="Mixer or Centrifugre"/></figure>



<p class="wp-block-paragraph"><p align="center"><strong>Mover Types</strong></p></p>



<p class="wp-block-paragraph"><em>Note: the variants, speeds, payloads, surfaces, and dimensions show specifications that represent the maximum values which can be reached. Movers can be grouped to increase the total payload.</em></p>



<p class="wp-block-paragraph"><p align="center"><strong>APM4220-0000-0000 | XPlanar mover, 0.4 kg payload</strong></p></p>



<p class="wp-block-paragraph"><strong></strong></p>



<p class="wp-block-paragraph">This is the smallest mover (about 4.5 inches squared) in the APM4xxx family and is compatible with all tiles of the type APS4xxx. The aluminum body is hard coated and can move at speeds up to 2 meters/second. This mover handles small, lightweight products (up to 0.4 kg) and can be used in bidirectional operation.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><b>APM4221-0000-0000 | XPlanar mover, 1.0 kg payload</b></p></p>



<p class="wp-block-paragraph"><p align="center"></p></p>



<p class="wp-block-paragraph">This mover is the second largest (about 5 inches squared) in the APM4xxx family and is very similar to the APM4220 other than its slightly larger size and an increase in payload (up to 1.0kg).</p>



<p class="wp-block-paragraph"><p align="center"><strong>APM4330-0000-0000 | XPlanar mover, 1.5 kg payload</strong></p></p>



<p class="wp-block-paragraph"><p align="center"><strong></strong></p></p>



<p class="wp-block-paragraph">This mover is the all-rounder (about 6.1 inches squared) of the APM4xxx family and is also very similar to the APM4221. With a payload capacity of 1.5 kilograms, this mover is ideally suited for use as a universal tool to handle a wide variety of products. It is available in a stainless steel variant for applications with particularly demanding hygienic requirements.</p>



<p class="wp-block-paragraph"><p align="center"><strong>APM4330-0001-0000 | XPlanar mover, 1.0 kg payload, stainless steel</strong></p></p>



<p class="wp-block-paragraph"><p align="center"><strong></strong></p></p>



<p class="wp-block-paragraph">This hygienic mover is completely encapsulated in stainless steel and designed to be easy to clean. At about 6.1 inches squared and with a payload capacity of 1.0 kilograms, it can move at speeds up to 2 meters/second. The mover is particularly suitable for all applications with particularly demanding hygiene requirements such as food and pharmaceutical applications.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><strong>APM4550-0000-0000 | XPlanar mover, 4.2 kg payload</strong></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><strong></strong></p></p>



<p class="wp-block-paragraph">This mover offers the highest payload (about 9.25 inches squared) of the APM4xxx family and is compatible with all tiles of the type APS4xxx. The aluminum body is hard coated and can move at speeds up to 2 meters/second. With a high payload capacity of 4.2 kilograms, the mover is suitable for handling larger and heavier products with few limitations</p>



<h2 class="wp-block-heading" id="h-xts">XTS</h2>



<p class="wp-block-paragraph">While there are a few different track-based transport systems in the market, <a href="https://www.beckhoff.com/en-us/products/motion/xts-linear-product-transport/">Beckhoff’s eXtended Transport System (XTS)</a> has some key advantages and differentiators. It’s very good for high-speeds (4 m/s 10G acceleration) and extreme repeatability and positioning (10 microns when stationary, and an amazing 0.15 mm of predictable positioning while in motion).</p>



<p class="wp-block-paragraph">High-speed packaging machinery is a common application for XTS, along with assembly and laboratory projects. XTS is IP65 rated with IP69K hygienic options available as well. There are lower duty and heavier duty systems to accommodate different loads.</p>



<p class="wp-block-paragraph"><p align="center"><strong>Comparing the Beckhoff and HepcoMotion systems</strong></p></p>



<p class="wp-block-paragraph">The Beckhoff-manufactured XTS guide rails and movers can carry loads between 1.8 to 2.75 pounds. With a track made of aluminum and matching movers that have plastic rollers, the lack of required lubrication allows this system to be used in the pharmaceutical industry — among others.</p>



<p class="wp-block-paragraph"><p align="center"><strong>AT9014 | XTS Movers</strong></p></p>



<p class="wp-block-paragraph"><p align="center"><strong></strong></p></p>



<p class="wp-block-paragraph">This set of movers is ideal for higher payloads, higher mileage, and the smallest possible product spacing. The movers have a low overall weight and are available in 55mm and 70 mm lengths paths. The aluminum base body has partially plastic rollers and a magnetic plate set. With a high payload capacity of up to 1000 grams, the movers are suitable for flexible travel movements and individual travel paths.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/XTS-motor-modules.png" alt="XTS motor modules"/></figure>



<p class="wp-block-paragraph"><p align="center"><em>XTS motor modules</em></p></p>



<p class="wp-block-paragraph"><p align="center"></p></p>



<p class="wp-block-paragraph"><p align="center"><em>XTS guide rails and movers</em></p></p>



<p class="wp-block-paragraph"><p align="center"><em>From our live demo: Beckhoff’s eXtended Transport System using an oval track.</em></p></p>



<p class="wp-block-paragraph">Beckhoff teamed up with HepcoMotion to make a second, heavier duty XTS track option, the GFX. It allows you to mount a parallel <a href="https://www.beckhoff.com/en-us/products/motion/xts-linear-product-transport/at8x00-at9xxx-ath9xxx-xts-guide-rails-and-movers/gfx.html" target="_blank" rel="noreferrer noopener">Hepco guide rail system</a> on XTS motor modules from Beckhoff, and it can carry loads of 11 – 33 pounds as the movers are made for increased payloads and longer service life.</p>



<p class="wp-block-paragraph"><p style="text-align: right;"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"></p></p>



<p class="wp-block-paragraph">Depending on your company’s load requirements, one of these two systems can be customized for your application. Another feature Beckhoff offers is the option to allow the movers to switch tracks within your system. Through <a href="https://www.beckhoff.com/en-us/products/motion/xts-linear-product-transport/" target="_blank" rel="noreferrer noopener">XTS Track Management</a> hardware and software, you can exchange and switch movers from track to track in multiple XTS linear transport systems, as shown below.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/XTS-Track-Management-Track-Switching.gif" alt="XTS Track Management hardware and software"/></figure>



<p class="wp-block-paragraph"><em>Picture and multimedia credits: Beckhoff Automation, all rights reserved. Beckhoff®, eXtended Transport System®, XTS® and XPlanar® are registered trademarks of and licensed by Beckhoff Automation GmbH.</em></p>



<p class="wp-block-paragraph"><strong>Learn more about DMC’s </strong><a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming"><strong>Beckhoff expertise</strong></a><strong> as part of the </strong><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10118/dmc-joins-beckhoff-integrator-group-big"><strong>Beckhoff Integrator Group</strong></a><strong> and </strong><a href="https://static.dmcinfo.com/contact"><strong>contact us</strong></a><strong> today to get started on your next project!</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18332/beckhoff-xplanar-xts/">Beckhoff XPlanar &#038; XTS</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Link Hardware / IO in Beckhoff TwinCAT 3</title>
		<link>https://static.dmcinfo.com/blog/18463/how-to-link-hardware-io-in-beckhoff-twincat-3/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Tue, 07 Jun 2022 20:41:10 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[TwinCAT 3]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18463/how-to-link-hardware-io-in-beckhoff-twincat-3/</guid>

					<description><![CDATA[<p>One of the most essential tasks on any PLC platform is linking software variables to physical hardware inputs and outputs. Without the ability to do this, our software would&#160;be meaningless code executing on a processor, unable to affect&#160;the physical realm. As a mechanical engineer, I like to move things, so this is no good.&#160; Beckhoff [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18463/how-to-link-hardware-io-in-beckhoff-twincat-3/">How to Link Hardware / IO in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">One of the most essential tasks on any PLC platform is linking software variables to physical hardware inputs and outputs. Without the ability to do this, our software would&nbsp;be meaningless code executing on a processor, unable to affect&nbsp;the physical realm. As a mechanical engineer, I like to move things, so this is no good.&nbsp;</p>



<p class="wp-block-paragraph">Beckhoff TwinCAT 3 gives us a couple of options for&nbsp;performing this task. This blog will introduce both methods&nbsp;and, at the end, discuss some pros and cons of each method. I’ve also included basics on linking motion hardware —&nbsp;if you’re only interested in linking standard inputs/outputs, feel free to skip the “Motion” sections.</p>



<h2 id="h-table-of-contents" class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li><a href="#h-hardware-linking-basics">Hardware Linking Basics</a>
<ul class="wp-block-list">
<li><a href="#h-motion">Motion</a></li>
</ul>
</li>



<li><a href="#h-method-1-manual-linking">Method 1: Manual Linking</a>
<ul class="wp-block-list">
<li><a href="#h-motion-0">Motion</a></li>
</ul>
</li>



<li><a href="#h-method-2-attribute-linking">Method 2: Attribute Linking</a>
<ul class="wp-block-list">
<li><a href="#h-single-variables">Single Variables</a></li>



<li><a href="#h-nested-variables">Nested Variables</a></li>



<li><a href="#h-mismatched-variables-size-types">Mismatched variable sizes/types</a></li>



<li><a href="#h-motion-1">Motion</a></li>
</ul>
</li>



<li><a href="#h-comparisons">Comparisons</a></li>



<li><a href="#h-project-variants">Project Variants</a></li>



<li><a href="#h-further-reference">Further Reference</a></li>
</ol>



<h2 id="h-hardware-linking-basics" class="wp-block-heading">Hardware Linking Basics</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">Before we get into the two hardware linking methods, let’s discuss some basics that we’ll need for either method.&nbsp;</p>



<p class="wp-block-paragraph">In order to link a variable to hardware, we need to declare that variable as an input or output. A variable can be declared as an input by placing&nbsp;<strong><code>AT%I*</code></strong>&nbsp;before the type. Likewise, an output is declared by placing&nbsp;<strong><code>AT%Q*</code></strong>&nbsp;before the type.&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    boolInput1  AT %I* : BOOL;
    boolOutput1 AT %Q* : BOOL;

    intInput1   AT %I* : INT;
    intOutput1  AT %Q* : INT;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    boolInput1  AT %I* : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    boolOutput1 AT %Q* : BOOL;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    intInput1   AT %I* : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">    intOutput1  AT %Q* : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">We can declare IO of any type, including structures and function blocks. If we declare a structure or function block as IO, all memory within that item will be included as IO —&nbsp;so this probably makes more sense for structures than it does for function blocks. Also, all variables within that structure will either be an input or an output —&nbsp;both cannot&nbsp;be included when declaring this way.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Type definition
TYPE ST_Inputs :
STRUCT
    boolInput : BOOL;
    intInput  : INT;
END_STRUCT
END_TYPE


// Declaration
VAR
    structAsInput AT %I* : ST_Inputs;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">// Type definition</span></span>
<span class="line"><span style="color: #D4D4D4">TYPE ST_Inputs :</span></span>
<span class="line"><span style="color: #D4D4D4">STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">    boolInput : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    intInput  : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">END_STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">END_TYPE</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">// Declaration</span></span>
<span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    structAsInput AT %I* : ST_Inputs;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">We can also declare IO within structures/function blocks, which allows us to include both inputs and outputs, as well as variables that are neither inputs nor outputs.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Type definition
TYPE ST_IncludingIO :
STRUCT
    boolInput  AT %I* : BOOL;
    boolOutput AT %Q* : BOOL;

    intInput   AT %I* : INT;
    intOutput  AT %Q* : INT;

    notIOBool  : BOOL;
    notIOInt   : INT;
    notIOReal  : REAL;
END_STRUCT
END_TYPE


// Declaration
VAR
    structWithIO : ST_IncludingIO;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">// Type definition</span></span>
<span class="line"><span style="color: #D4D4D4">TYPE ST_IncludingIO :</span></span>
<span class="line"><span style="color: #D4D4D4">STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">    boolInput  AT %I* : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    boolOutput AT %Q* : BOOL;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    intInput   AT %I* : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">    intOutput  AT %Q* : INT;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    notIOBool  : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    notIOInt   : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">    notIOReal  : REAL;</span></span>
<span class="line"><span style="color: #D4D4D4">END_STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">END_TYPE</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">// Declaration</span></span>
<span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    structWithIO : ST_IncludingIO;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">Inputs/outputs can be declared like this pretty much anywhere in the program, with a few exceptions: methods and functions. This gives us the flexibility to architect our program however we like. For example, we could put all of the IO in a GVL for the convenience of having it all in once place, or we could nest our IO within the function block structure of our software for good organization.</p>



<p class="wp-block-paragraph">Once the program is compiled, all the IO variables that have been declared will appear under the PLC instance inputs and outputs. In this example, all our IO variables are declared in the&nbsp;<code><strong>VAR</strong></code>&nbsp;memory of the&nbsp;<code><strong>MAIN</strong></code>&nbsp;program, which is indicated in the path of each IO variable.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="410" height="585" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/DeclaredIO.png" alt="DeclaredIO" class="wp-image-18439" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/DeclaredIO.png 410w, https://static.dmcinfo.com/wp-content/uploads/2025/05/DeclaredIO-210x300.png 210w" sizes="(max-width: 410px) 100vw, 410px" /></figure>



<p class="wp-block-paragraph">Once our IO variables are declared and the project is compiled, we are ready to start linking standard IO.</p>



<h2 id="h-motion" class="wp-block-heading">Motion</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">Basic motion axis linking is a little different than standard IO.&nbsp;</p>



<p class="wp-block-paragraph">Standard IO variables can still be directly linked to PDOs to/from drive hardware, which is often done for more advanced motion&nbsp;functionality or certain functionality with third-party (i.e., non-Beckhoff) drives; however, most NC axis control is done through the NC task, a separate task on the Beckhoff PLC used specifically for motion control. Basically, the PLC communicates with the NC task, and the NC task directly communicates with the drive hardware. The NC task takes care of low-level motion control functionality, so we can abstract out to high-level, simple, PLCopen-style control within the PLC program.</p>



<p class="wp-block-paragraph">This means we need to link the PLC task to the NC task. Everything we need for this is included in the&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tcplclib_tc2_mc2/70132363.html?id=467387231256035047" target="_blank" rel="noreferrer noopener"><code><strong>AXIS_REF</strong></code>&nbsp;type</a>&nbsp;from Beckhoff’s&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tcplclib_tc2_mc2/index.html?id=4786081293094367280" target="_blank" rel="noreferrer noopener"><code><strong>Tc2_MC2</strong></code>&nbsp;library</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    axis1 : AXIS_REF;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    axis1 : AXIS_REF;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<figure class="wp-block-image size-full"><img decoding="async" width="275" height="252" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/DeclaredAxis.png" alt="DeclaredAxis" class="wp-image-18440"/></figure>



<p class="wp-block-paragraph">We’ll talk about how to link this&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;structure in the linking methods sections later, but one more thing must be done, regardless of which linking method is used. As mentioned previously, the NC task&nbsp;needs to be directly linked to the hardware. To do this, we’ll first need to create the NC task and axis. This may have been done already if an axis had been added to the hardware configuration previously.&nbsp;If it hasn’t, use the following steps:</p>



<ol class="wp-block-list">
<li><strong>[Solution] &gt; MOTION &gt; Right Click &gt; Add New Item…</strong></li>



<li>Select&nbsp;<strong>NC/PTP NCI Configuration</strong>&nbsp;and click&nbsp;<strong>Ok.</strong></li>



<li><strong>[Solution] &gt; MOTION &gt; [NC Task] &gt; Axes &gt; Right Click &gt; Add New Item…</strong></li>



<li>Enter the Axis name and click&nbsp;<strong>Ok</strong>.</li>
</ol>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img decoding="async" width="478" height="198" data-id="18441" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTask.png" alt="CreateNCTask" class="wp-image-18441" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTask.png 478w, https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTask-300x124.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="471" height="180" data-id="18442" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTaskPopup.png" alt="CreateNCTaskPopup" class="wp-image-18442" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTaskPopup.png 471w, https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateNCTaskPopup-300x115.png 300w" sizes="(max-width: 471px) 100vw, 471px" /></figure>
</figure>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img decoding="async" width="478" height="332" data-id="18443" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxis.png" alt="CreateAxis" class="wp-image-18443" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxis.png 478w, https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxis-300x208.png 300w" sizes="(max-width: 478px) 100vw, 478px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="460" height="237" data-id="18444" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxisPopup.png" alt="CreateAxisPopup" class="wp-image-18444" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxisPopup.png 460w, https://static.dmcinfo.com/wp-content/uploads/2025/05/CreateAxisPopup-300x155.png 300w" sizes="(max-width: 460px) 100vw, 460px" /></figure>
</figure>



<p class="wp-block-paragraph">Once the NC task/axis has been created, click on the axis and go to the&nbsp;<strong>Settings</strong>&nbsp;tab. The&nbsp;<strong>Link To I/O</strong>&nbsp;button will allow us to link the axis item in the NC task to an actual drive in the hardware configuration. Click on this button and select the desired hardware to link the NC axis to that hardware.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="885" height="284" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkNcAxis.png" alt="LinkNcAxis" class="wp-image-18445" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkNcAxis.png 885w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkNcAxis-300x96.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkNcAxis-768x246.png 768w" sizes="(max-width: 885px) 100vw, 885px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="659" height="344" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/SelectHardwareAxis.png" alt="SelectHardwareAxis" class="wp-image-18446" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/SelectHardwareAxis.png 659w, https://static.dmcinfo.com/wp-content/uploads/2025/05/SelectHardwareAxis-300x157.png 300w" sizes="(max-width: 659px) 100vw, 659px" /></figure>



<p class="wp-block-paragraph">The linked hardware will appear in the field, and the Axis Type will change appropriately.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="472" height="126" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkedNcHardwareAxis_1.png" alt="LinkedNcHardwareAxis 1" class="wp-image-18447" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkedNcHardwareAxis_1.png 472w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkedNcHardwareAxis_1-300x80.png 300w" sizes="(max-width: 472px) 100vw, 472px" /></figure>



<p class="wp-block-paragraph">At this point, the NC axis is properly configured and ready to be linked to the PLC code using one of the methods in the following sections! Alternatively, if we wanted to create a&nbsp;<a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tf50x0_tc3_nc_ptp/2834717323.html&amp;id=8250271195349757571">simulation on the axis</a>, we could leave this unlinked and make sure the Axis Type is&nbsp;<strong>Standard (Mapping via Encoder and Drive).</strong></p>



<h2 id="h-method-1-manual-linking" class="wp-block-heading">Method 1: Manual Linking</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">The first method for hardware linking is manual linking, which is a fairly straightforward process. First, expand the task inputs/outputs and select the desired variable.&nbsp;Right-click on it and select Change Link, or double-click and select the <strong>Linked to</strong> button on the <strong>Variable</strong> tab. This will open the link selection dialog box.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="879" height="365" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeVariableLink_1.png" alt="ChangeVariableLink 1" class="wp-image-18448" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeVariableLink_1.png 879w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeVariableLink_1-300x125.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeVariableLink_1-768x319.png 768w" sizes="(max-width: 879px) 100vw, 879px" /></figure>



<p class="wp-block-paragraph">From this dialog box, we can select the hardware card and specific channel to which the selected IO variable will be linked. The search bar and filters at the side of the dialog box like&nbsp;<strong>Only Unused</strong>&nbsp;and&nbsp;<strong>Matching Type/Size</strong>&nbsp;can be helpful in finding the proper/available hardware quickly. Select the proper channel and click&nbsp;<strong>Ok</strong>&nbsp;to link the variable.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="583" height="473" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkVariable.png" alt="LinkVariable" class="wp-image-18449" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkVariable.png 583w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkVariable-300x243.png 300w" sizes="(max-width: 583px) 100vw, 583px" /></figure>



<p class="wp-block-paragraph">We can also do this from the other direction – if we want to start from the hardware configuration, we can select a certain channel and open a similar dialog box to select the IO variable to which it should be linked.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="883" height="527" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeHardwareLink.png" alt="ChangeHardwareLink" class="wp-image-18450" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeHardwareLink.png 883w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeHardwareLink-300x179.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ChangeHardwareLink-768x458.png 768w" sizes="(max-width: 883px) 100vw, 883px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="583" height="470" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkHardware_1.png" alt="LinkHardware 1" class="wp-image-18451" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkHardware_1.png 583w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkHardware_1-300x242.png 300w" sizes="(max-width: 583px) 100vw, 583px" /></figure>



<p class="wp-block-paragraph">Once a variable or hardware channel is linked, a small square icon with an arrow will appear at the corner of the icon in the solution explorer. When variables are linked manually, this icon is gray.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="292" height="235" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ManuallyLinkedVariables.png" alt="ManuallyLinkedVariables" class="wp-image-18452"/></figure>



<p class="wp-block-paragraph">Helpfully, we can easily navigate between the now-linked items by right-clicking and selecting&nbsp;<strong>Go To Link Variable</strong>.&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="346" height="137" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromPLC_1.png" alt="GoToLinkFromPLC 1" class="wp-image-18453" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromPLC_1.png 346w, https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromPLC_1-300x119.png 300w" sizes="(max-width: 346px) 100vw, 346px" /></figure>



<h2 id="h-motion-0" class="wp-block-heading">Motion</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">For&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;structures, linking to the PLC is done from the NC task. Return to&nbsp;<strong>[Solution] &gt; MOTION &gt; [NC Task] &gt; Axes &gt; [Axis] &gt; Settings</strong>&nbsp;and use the&nbsp;<strong>Link To PLC</strong>&nbsp;button to select the desired&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;structure.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="873" height="297" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/AxisLinkToPlcButton.png" alt="AxisLinkToPlcButton" class="wp-image-18455" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/AxisLinkToPlcButton.png 873w, https://static.dmcinfo.com/wp-content/uploads/2025/05/AxisLinkToPlcButton-300x102.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/AxisLinkToPlcButton-768x261.png 768w" sizes="(max-width: 873px) 100vw, 873px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="462" height="216" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkAxisToPlc.png" alt="LinkAxisToPlc" class="wp-image-18456" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkAxisToPlc.png 462w, https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkAxisToPlc-300x140.png 300w" sizes="(max-width: 462px) 100vw, 462px" /></figure>



<p class="wp-block-paragraph">Once linked, the&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;variable will appear in the field, and the&nbsp;<code><strong>NcToPlc</strong></code>&nbsp;and&nbsp;<code><strong>PlcToNc</strong></code>&nbsp;members of the&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;structure will show gray boxed arrows in the PLC Instance inputs and outputs, indicating they are properly linked.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="885" height="473" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ManuallyLinkedAxis.png" alt="ManuallyLinkedAxis" class="wp-image-18457" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/ManuallyLinkedAxis.png 885w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ManuallyLinkedAxis-300x160.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/ManuallyLinkedAxis-768x410.png 768w" sizes="(max-width: 885px) 100vw, 885px" /></figure>



<h2 id="h-method-2-attribute-linking" class="wp-block-heading">Method 2: Attribute Linking</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">The second method for hardware linking is attribute linking using the&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/3107974923.html?id=3796864311828577666" target="_blank" rel="noreferrer noopener"><code><strong>TcLinkTo</strong></code></a>,&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/3107974923.html?id=3796864311828577666" target="_blank" rel="noreferrer noopener"><code><strong>TcLinkToOSO</strong></code></a>, and&nbsp;<a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/3107990667.html&amp;id=7493071042325947826" target="_blank" rel="noreferrer noopener"><code><strong>TcNcAxis</strong></code></a>&nbsp;attributes. This isn’t as straightforward as manual linking, but it has its advantages —&nbsp;especially when using&nbsp;<a href="https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/">version control</a>.</p>



<h3 id="h-single-variables" class="wp-block-heading">Single Variables</h3>



<p class="wp-block-paragraph">For most linking, we can just use the basic&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/3107974923.html?id=3796864311828577666" target="_blank" rel="noreferrer noopener"><code><strong>TcLinkTo</strong></code></a>&nbsp;attribute. Here are a few examples.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcLinkTo' :=
        'TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 4^Input'}
    boolInput2 AT %I* : BOOL;

    {attribute 'TcLinkTo' :=
        'TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 4^Output'}
    boolOutput2 AT %Q* : BOOL;

    {attribute 'TcLinkTo' :=
        'TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 4^Value'}
    intInput2 AT %I* : INT;

    {attribute 'TcLinkTo' :=
        'TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 4^Analog output'}
    intOutput2 AT %Q* : INT;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 4^Input&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    boolInput2 AT %I* : BOOL;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 4^Output&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    boolOutput2 AT %Q* : BOOL;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 4^Value&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    intInput2 AT %I* : INT;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 4^Analog output&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    intOutput2 AT %Q* : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">By placing the attribute line above the declaration, we are telling the compiler the hardware item to which we want the variable to be linked.&nbsp;<strong>The path to that hardware item must be exact and have the correct syntax.</strong>&nbsp;The easiest way to get the&nbsp;syntax for this path is to navigate to the hardware item in the solution explorer and&nbsp;copy the syntax from the&nbsp;<strong>Full Name</strong>&nbsp;field.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="883" height="569" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/HardwareFullName.png" alt="HardwareFullName" class="wp-image-18458" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/HardwareFullName.png 883w, https://static.dmcinfo.com/wp-content/uploads/2025/05/HardwareFullName-300x193.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/HardwareFullName-768x495.png 768w" sizes="(max-width: 883px) 100vw, 883px" /></figure>



<p class="wp-block-paragraph">After properly setting up the attribute, compiling the project should link the variables to their respective hardware. This can be confirmed by examining the instance&nbsp;inputs/outputs in the Solution Explorer. Again, we should see a small square icon with an arrow on linked variables, but this time it will be&nbsp;blue. We can still use the&nbsp;<strong>Go To Link Variable</strong>&nbsp;context menu option to jump to linked hardware item.&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="297" height="328" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedSingleVariables.png" alt="AttributeLinkedSingleVariables" class="wp-image-18459" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedSingleVariables.png 297w, https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedSingleVariables-272x300.png 272w" sizes="(max-width: 297px) 100vw, 297px" /></figure>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img decoding="async" width="292" height="118" data-id="18460" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromPLCAttribute.png" alt="GoToLinkFromPLCAttribute" class="wp-image-18460"/></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="340" height="123" data-id="18461" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromHardwareAttribute.png" alt="GoToLinkFromHardwareAttribute" class="wp-image-18461" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromHardwareAttribute.png 340w, https://static.dmcinfo.com/wp-content/uploads/2025/05/GoToLinkFromHardwareAttribute-300x109.png 300w" sizes="(max-width: 340px) 100vw, 340px" /></figure>
</figure>



<h3 id="h-nested-variables" class="wp-block-heading">Nested Variables</h3>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">IO variables nested within one or many layers of structures/function blocks can also be linked, with some extra syntax added to the&nbsp;<code><strong>TcLinkTo</strong></code>&nbsp;attribute. This is very powerful because it means that, even if we have IO variables declared within structures or function blocks, we can still link every instance of those reusable items individually.</p>



<p class="wp-block-paragraph">To link nested variables, we just need to add the path to the variables within the structure or function block to our attribute. Here is an&nbsp;example using the same structure definition as above:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcLinkTo' := '
        .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 5^Input;
        .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 5^Output;
        .intInput   := TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 5^Value;
        .intOutput  := TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 5^Analog output;
    '}
    structLinkedByAttribute : ST_IncludingIO;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 5^Input;</span></span>
<span class="line"><span style="color: #D4D4D4">        .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 5^Output;</span></span>
<span class="line"><span style="color: #D4D4D4">        .intInput   := TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 5^Value;</span></span>
<span class="line"><span style="color: #D4D4D4">        .intOutput  := TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 5^Analog output;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    structLinkedByAttribute : ST_IncludingIO;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<h3 id="h-mismatched-variables-size-types" class="wp-block-heading">Mismatched Variables Size/Types</h3>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">In certain cases, our IO variables may not have the same size as the hardware variable to which we want to link them; for example,&nbsp;accessing bits in a byte&nbsp;or combining separate bytes into a word. It may be simpler/more readable to just make sure the IO variable does match the type of the hardware variable and handle any interpretation within the PLC. But, in the event that this isn’t possible, there is a solution.&nbsp;</p>



<p class="wp-block-paragraph">The&nbsp;<a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/3107974923.html?id=3796864311828577666" target="_blank" rel="noreferrer noopener"><code><strong>TcLinkToOSO</strong></code></a>&nbsp;attribute allows us to select exactly which bit range from our hardware will be mapped to our IO variables in the PLC program. “OSO” stands for “Offset, Size, Offset,”&nbsp;which is the extra information we will have to supply. The syntax is&nbsp;<strong><code>&lt;x,y,z&gt;</code></strong>, where:&nbsp;</p>



<p class="wp-block-paragraph"><strong><code>x</code></strong>&nbsp;= Bit-offset of the PLC variable&nbsp;</p>



<p class="wp-block-paragraph"><strong><code>y</code></strong>&nbsp;= Number of bits to map&nbsp;</p>



<p class="wp-block-paragraph"><strong><code>z</code></strong>&nbsp;= Bit-offset of the hardware variable&nbsp;</p>



<p class="wp-block-paragraph">For example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcLinkToOSO' := '
        &lt;0,16,0>TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 6^Analog output;
        &lt;16,16,0>TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 7^Analog output;
    '}
    dintLinkedTo2Ints AT %Q* : DINT;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkToOSO&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,16,0</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 6^Analog output;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #F44747">16,16,0</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 7^Analog output;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    dintLinkedTo2Ints AT %Q* : DINT;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">Here&nbsp;we are linking a larger PLC variable to two&nbsp;smaller hardware variables. We specify that the first 16 bits of the PLC&nbsp;<code><strong>DINT</strong></code>&nbsp;(<strong><code>x</code></strong>=0,&nbsp;<strong><code>y</code></strong>=16) should be linked to the first 16 bits of the specified 16-bit&nbsp;integer input channel (<strong><code>y</code></strong>=16,&nbsp;<code><strong>z</strong></code>=0). The result is the prefix of the first line, with&nbsp;<strong><code>&lt;0,16,0&gt;</code></strong>.&nbsp;</p>



<p class="wp-block-paragraph">Then, starting at bit 16 in the PLC&nbsp;<code><strong>DINT</strong></code>&nbsp;(<code><strong>x</strong></code>=16), we link the next 16 bits (<code><strong>y</strong></code>=16) to the first 16 bits of a separate 16-bit&nbsp;integer input channel (<code><strong>y</strong></code>=16,&nbsp;<code><strong>z</strong></code>=0). The result is the prefix of the second line, with&nbsp;<code><strong>&lt;16,16,0&gt;</strong></code>.</p>



<p class="wp-block-paragraph">Another example, this time linking 2 smaller PLC variables to a larger hardware variable:&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcLinkToOSO' :=
        '&lt;0,8,0>TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 8^Analog output'}
    byte0LinkedToInt AT %Q* : BYTE;

    {attribute 'TcLinkToOSO' :=
        '&lt;0,8,8>TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 8^Analog output'}
    byte1LinkedToInt AT %Q* : BYTE;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkToOSO&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;</span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,8,0</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 8^Analog output&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    byte0LinkedToInt AT %Q* : BYTE;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkToOSO&apos; :=</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;</span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,8,8</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term4_EL4008^AO Outputs Channel 8^Analog output&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    byte1LinkedToInt AT %Q* : BYTE;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">Here, we link the first 8 bits of the first PLC byte (<code><strong>x</strong></code>=0,&nbsp;<code><strong>y</strong></code>=8) to the first 8 bits of the specified 16-bit integer input channel (<code><strong>y</strong></code>=8,&nbsp;<strong><code>z</code></strong>=0). The result is the attribute for the first variable,&nbsp;<code><strong>&lt;0,8,0&gt;</strong></code>.</p>



<p class="wp-block-paragraph">Then, we link the first 8 bits of the second PLC byte (<strong><code>x</code></strong>=0,&nbsp;<strong><code>y</code></strong>=8) to the second 8 bits of the same specified 16-bit integer input channel (<strong><code>y</code></strong>=8,&nbsp;<strong><code>z</code></strong>=8). The result is the attribute for the second variable,&nbsp;<code><strong>&lt;0,8,8&gt;</strong></code>.</p>



<p class="wp-block-paragraph">Variables linked with&nbsp;<code><strong>TcLinkToOSO</strong></code>&nbsp;can also be placed within structures/function blocks.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Type definition
TYPE ST_IntSplitToBytes :
STRUCT
    byteArr : ARRAY&#91;0..1&#93; OF BYTE;
END_STRUCT
END_TYPE


// Declaration
VAR
    {attribute 'TcLinkToOSO' := '
        .byteArr&#91;0&#93; := &lt;0,8,0>TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 6^Value;
        .byteArr&#91;1&#93; := &lt;0,8,8>TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 6^Value
    '}
    structOSOLinking AT %I* : ST_IntSplitToBytes;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">// Type definition</span></span>
<span class="line"><span style="color: #D4D4D4">TYPE ST_IntSplitToBytes :</span></span>
<span class="line"><span style="color: #D4D4D4">STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">    byteArr : ARRAY&#91;0..1&#93; OF BYTE;</span></span>
<span class="line"><span style="color: #D4D4D4">END_STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">END_TYPE</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">// Declaration</span></span>
<span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkToOSO&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .byteArr&#91;0&#93; := </span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,8,0</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 6^Value;</span></span>
<span class="line"><span style="color: #D4D4D4">        .byteArr&#91;1&#93; := </span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,8,8</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 6^Value</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    structOSOLinking AT %I* : ST_IntSplitToBytes;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<h3 id="h-motion-1" class="wp-block-heading">Motion</h3>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">Linking&nbsp;<code><strong>AXIS_REF</strong></code>&nbsp;structures uses a different attribute,&nbsp;<a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/3107990667.html&amp;id=7493071042325947826" target="_blank" rel="noreferrer noopener"><code><strong>TcNcAxis</strong></code></a>. All that is needed in this case is the axis name from the MOTION NC task setup, instead of the hardware path.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcNcAxis' := 'Axis2'}
    axis2 : AXIS_REF;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcNcAxis&apos; := &apos;Axis2&apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    axis2 : AXIS_REF;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<figure class="wp-block-image size-full"><img decoding="async" width="225" height="343" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedAxis.png" alt="AttributeLinkedAxis" class="wp-image-18462" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedAxis.png 225w, https://static.dmcinfo.com/wp-content/uploads/2025/05/AttributeLinkedAxis-197x300.png 197w" sizes="(max-width: 225px) 100vw, 225px" /></figure>



<p class="wp-block-paragraph"><code><strong>AXIS_REF</strong></code>&nbsp;structures can also be linked from within structures/function blocks.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Type definition
TYPE ST_Axis :
STRUCT
    axis : AXIS_REF;

    some      AT %I* : BOOL;
    other     AT %I* : INT;
    variables AT %I* : INT;

    included  : REAL;
END_STRUCT
END_TYPE


// Declaration
VAR
    {attribute 'TcNcAxis' := '
        .axis := Axis3;
    '}
    structAxis : ST_Axis;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">// Type definition</span></span>
<span class="line"><span style="color: #D4D4D4">TYPE ST_Axis :</span></span>
<span class="line"><span style="color: #D4D4D4">STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">    axis : AXIS_REF;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    some      AT %I* : BOOL;</span></span>
<span class="line"><span style="color: #D4D4D4">    other     AT %I* : INT;</span></span>
<span class="line"><span style="color: #D4D4D4">    variables AT %I* : INT;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    included  : REAL;</span></span>
<span class="line"><span style="color: #D4D4D4">END_STRUCT</span></span>
<span class="line"><span style="color: #D4D4D4">END_TYPE</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">// Declaration</span></span>
<span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcNcAxis&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .axis := Axis3;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    structAxis : ST_Axis;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Combining Linking Attributes</strong></p>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">We can mix and match the different linking attributes&nbsp;as we like; however, we can only use each attribute once —&nbsp;all subsequent uses of that attribute will be ignored. Of course, within a single use of an attribute, we can link multiple variables.</p>



<p class="wp-block-paragraph">For example, to link the rest of the variables in the above structure:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR
    {attribute 'TcNcAxis' := '
        .axis := Axis3;
    '}

    {attribute 'TcLinkTo' := '
        .some  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 8^Input;
        .other := TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 7^Value;
    '}

    {attribute 'TcLinkToOSO' := '
        .variables := &lt;0,4,0>TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 8^Value;
    '}

    structAxis : ST_Axis;
END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcNcAxis&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .axis := Axis3;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkTo&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .some  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 8^Input;</span></span>
<span class="line"><span style="color: #D4D4D4">        .other := TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 7^Value;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {attribute &apos;TcLinkToOSO&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">        .variables := </span><span style="color: #808080">&lt;</span><span style="color: #F44747">0,4,0</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">TIID^Master_EtherCAT^Coupler_EK1100^Term3_EL3008^AI Standard Channel 8^Value;</span></span>
<span class="line"><span style="color: #D4D4D4">    &apos;}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    structAxis : ST_Axis;</span></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<h2 id="h-comparisons" class="wp-block-heading">Comparisons</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">Now that we have multiple methods for linking PLC variables to hardware, why might we choose one over the others? Here are some pros/cons for each method —&nbsp;if you have other thoughts, please leave them in the comment section below!&nbsp;</p>



<p class="wp-block-paragraph"><strong>Manual</strong></p>



<p class="wp-block-paragraph"><em>Pros</em></p>



<ul class="wp-block-list">
<li>When variables are manually linked,&nbsp;the link will automatically update if the name of a hardware card/channel changes. With attribute linking, such a name change will break the hardware link until the attribute hardware path is updated in the PLC declaration code.</li>



<li>As mentioned above, when linking variables, we can start from either direction —&nbsp;PLC to hardware or hardware to PLC. Since attribute linking must be done within the PLC source code, it can only be done from PLC to hardware. The flexibility of manual linking might come in handy when reading from large IO sheets that are organized for electrical cabinet wiring.&nbsp;</li>
</ul>



<p class="wp-block-paragraph"><em>Cons</em></p>



<ul class="wp-block-list">
<li>Manual hardware links are stored in an XML format in&nbsp;<code><strong>.tsproj</strong></code>&nbsp;or&nbsp;<code><strong>.xti</strong></code>&nbsp;files (depending on a project&#8217;s&nbsp;<a href="https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/">independent project files</a>&nbsp;settings). These files may change often and contain plenty of other information not related to hardware linking. Also, the XML that defines the hardware mapping is not as directly readable as the hardware paths used for attribute linking. For these reasons, changes in hardware linking are less visible in version control —&nbsp;it may be harder to look through commit histories and find where these changes were made and what they mean.</li>



<li>Because manual hardware links are stored in XML format, manual hardware linking is more easily lost during merges. This can cause headaches, especially when working with a multi-developer team.</li>
</ul>



<p class="wp-block-paragraph"><strong>Attribute </strong></p>



<p class="wp-block-paragraph"><em>Pros</em></p>



<ul class="wp-block-list">
<li>Perhaps the biggest positive of using attribute linking is its compatibility with version control. Attribute linking exists within source code rather than being stuck in the XML of project files;&nbsp;therefore, it merges as easily as source code does and is much more visible for tracking/finding changes.&nbsp;</li>



<li>Manual linking is, well, manual, and must be set up one variable at a time. Attribute linking exists within code, with a predictable syntax. For this reason, depending on the architecture of our program, it may be very easy to write a simple program (in Python, for example) to automate our hardware linking for us.&nbsp;The program could&nbsp;take&nbsp;in a CSV of hardware points/IO variable names and output the attribute linking syntax required. Then updating IO linking is a breeze – just make updates to the CSV, run the Python program, and copy and paste the resulting attribute/declaration code into the project.&nbsp;</li>
</ul>



<p class="wp-block-paragraph"><em>Cons</em></p>



<ul class="wp-block-list">
<li>Attribute linking requires precise syntax, which can be tedious to get right.&nbsp;</li>



<li>If the name of a hardware card/channel changes, the link will not automatically update. The attribute linking source code must be updated to reflect this change. If this is a higher-level component, like an EtherCAT Master, this could mean editing a lot of code – or automating the update using find and replace or a custom program like mentioned above.</li>
</ul>



<h2 id="h-project-variants" class="wp-block-heading"><a id="Project Variants" name="Project Variants"></a>Project Variants</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">One of TwinCAT’s unique and powerful features is the concept of <a href="https://static.dmcinfo.com/blog/18781/twincat-project-variants/">project variants</a>, and one of their uses is to allow modification of hardware mapping depending on the selected variant. This can be used&nbsp;regardless of which linking method is used. For manual mapping, follow <a href="https://static.dmcinfo.com/blog/18463/how-to-link-hardware-io-in-beckhoff-twincat-3/">these instructions</a>. For attribute mapping, we can use <a href="https://static.dmcinfo.com/blog/18781/twincat-project-variants/">conditional pragmas</a>. Here is an example of how one might use these pragmas to change hardware linking based on the selected project variant. Keep in mind that we will have to build the project with a certain variant selected for that variant’s hardware linking to appear in the solution explorer.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">HTML</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>VAR

    {IF defined(Variant1)}
        {attribute 'TcLinkTo' := '
            .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 6^Input;
            .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 6^Output;
        '}
    {END_IF}

    {IF defined(Variant2)}
        {attribute 'TcLinkTo' := '
            .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 7^Input;
            .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 6^Output;
        '}
    {END_IF}

    variantsExample : ST_IncludingIO;

END_VAR</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">VAR</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {IF defined(Variant1)}</span></span>
<span class="line"><span style="color: #D4D4D4">        {attribute &apos;TcLinkTo&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">            .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 6^Input;</span></span>
<span class="line"><span style="color: #D4D4D4">            .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 6^Output;</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    {END_IF}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    {IF defined(Variant2)}</span></span>
<span class="line"><span style="color: #D4D4D4">        {attribute &apos;TcLinkTo&apos; := &apos;</span></span>
<span class="line"><span style="color: #D4D4D4">            .boolInput  := TIID^Master_EtherCAT^Coupler_EK1100^Term1_EL1008^Channel 7^Input;</span></span>
<span class="line"><span style="color: #D4D4D4">            .boolOutput := TIID^Master_EtherCAT^Coupler_EK1100^Term2_EL2008^Channel 6^Output;</span></span>
<span class="line"><span style="color: #D4D4D4">        &apos;}</span></span>
<span class="line"><span style="color: #D4D4D4">    {END_IF}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    variantsExample : ST_IncludingIO;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">END_VAR</span></span></code></pre></div>



<p class="wp-block-paragraph">Unfortunately, since each linking attribute can only be used once, every single&nbsp;variable link for a structure&nbsp;must be included in the conditional statement&nbsp;for every variant —&nbsp;regardless of whether a particular variable link changes depending on the project variant. This can be more tedious than manual linking while using project variants, but it&#8217;s a lot more explicit —&nbsp;since the two link lists are explicitly in code, rather than hidden away in the solution explorer menus.</p>



<p class="wp-block-paragraph">&nbsp;</p>



<h2 id="h-further-reference" class="wp-block-heading"><a id="Further Reference" name="Further Reference"></a>Further Reference</h2>



<p class="wp-block-paragraph"><a href="#h-table-of-contents">Back to Table of Contents</a></p>



<p class="wp-block-paragraph">For more information on the topics discussed in this blog, please see the following:</p>



<ul class="wp-block-list">
<li><a href="https://infosys.beckhoff.com/content/1033/tc3_plc_intro/3107974923.html?id=3796864311828577666" target="_blank"><code><strong>TcLinkTo</strong></code> / <code><strong>TcLinkToOSO</strong></code> Infosys Page</a></li>



<li><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/3107990667.html&amp;id=7493071042325947826" target="_blank"><code><strong>TcNcAxis</strong></code> Infosys Page</a></li>



<li><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tcplclib_tc2_mc2/70132363.html&amp;id=467387231256035047" target="_blank"><code><strong>AXIS_REF</strong></code> Infosys Page</a></li>



<li><a href="https://infosys.beckhoff.com/content/1033/tcplclib_tc2_mc2/index.html?id=4786081293094367280" target="_blank"><strong><code>Tc2_MC2</code></strong> Infosys Section</a></li>



<li><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tf50x0_tc3_nc_ptp/2834717323.html&amp;id=8250271195349757571" target="_blank">Simulation Axis Infosys Page</a></li>



<li><a href="https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/">TwinCAT with Version Control Blog</a></li>



<li><a href="https://static.dmcinfo.com/blog/18781/twincat-project-variants/">TwinCAT Project Variants Blog</a></li>
</ul>



<p class="wp-block-paragraph">That’s about all you need to know to get started with hardware linking in your TwinCAT projects! If you’ve got any further tips and tricks regarding this topic, please share them in the comments below!</p>



<p class="wp-block-paragraph"><strong>Learn more about <a href="/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">DMC&#8217;s Beckhoff and TwinCAT 3 Programming expertise</a>&nbsp;and <a href="/contact">contact us</a> today for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18463/how-to-link-hardware-io-in-beckhoff-twincat-3/">How to Link Hardware / IO in Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Version Control and Multi-user Development with Beckhoff TwinCAT 3</title>
		<link>https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Wed, 30 Mar 2022 14:05:50 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[TwinCAT 3]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/</guid>

					<description><![CDATA[<p>Why Version Control? If you&#8217;ve ever gone through a project archive, found something that looks like the following: &#8230;and been confused about what the most recent version of the project is, then you&#8217;ve experienced one of the many reasons to use version control systems!&#160; From backing up code to tracking changes to concurrent multi-user development, [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/">Version Control and Multi-user Development with Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Why Version Control?</h2>

<p class="wp-block-paragraph">If you&rsquo;ve ever gone through a project archive, found something that looks like the following:</p>

<ul class="wp-block-list">
 <li>Project_20180807</li>
 <li>Project_20180813</li>
 <li>Project_20180813_Final</li>
 <li>Project_20180813_FinalB</li>
 <li>Project_20180813_FinalFinal</li>
 <li>Project_20180813_Newest_I_SWEAR</li>
</ul>

<p class="wp-block-paragraph">&hellip;and been confused about what the most recent version of the project is, then you&rsquo;ve experienced one of the many reasons to use version control systems!&nbsp;</p>

<p class="wp-block-paragraph">From backing up code to tracking changes to concurrent multi-user development, <a href="https://towardsdatascience.com/version-control-101-definition-and-benefits-6fd7ad49e5f1" target="_blank">version control systems</a>&nbsp;(VCS) offer so many advantages that they should be an essential tool for any software engineer.&nbsp;Yet&nbsp;the automation industry has struggled to effectively use all the advantages that VCS offer.&nbsp;</p>

<p class="wp-block-paragraph">Proprietary and binary file formats that are common in the automation industry prevent the full use of many VCS, which generally provide the most benefit when tracking text-based files.</p>

<p class="wp-block-paragraph">Luckily, <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">Beckhoff TwinCAT 3 </a>stores project files and code in text-based file formats, making it a great candidate for&nbsp;<a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_sourcecontrol/index.html&amp;id=6468228250695776754" target="_blank">use with version control software</a>. This blog will discuss tips and tricks for optimizing the use of TwinCAT with version control and for development with multiple users.&nbsp;</p>

<p class="wp-block-paragraph">I&rsquo;ve also written a <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide">companion blog</a>&nbsp;with an easy, step-by-step guide to setting up a TwinCAT project for use with version control, so be sure to check that out!</p>

<p class="wp-block-paragraph"><strong>A couple quick disclaimers:</strong></p>

<p class="wp-block-paragraph">DMC leverages Git (specifically Gitlab) as a VCS to use with TwinCAT, but much of the information discussed in this blog will be applicable across many VCS.</p>

<p class="wp-block-paragraph">This blog will discuss many of the things&nbsp;DMC has learned through the years that have made our lives easier. By no means is our workflow the only workflow; one of the many beauties of version control is that it is flexible &ndash; use it however&nbsp;works best for you, and take or leave as many of our tips as you like!</p>

<p class="wp-block-paragraph">Alright, let&rsquo;s get started.</p>

<p class="wp-block-paragraph"><u><a id="Table of Contents" name="Table of Contents"></a>Table of Contents:</u></p>

<ol class="wp-block-list">
 <li><a href="#TwinCAT Project Settings">TwinCAT Project Settings</a>

 <ol class="wp-block-list">
  <li><a href="#Separating Project Components into Individual Files">Separating Project Components into Individual Files</a></li>
  <li><a href="#Keep Unrestored Links">Keep Unrestored Links</a></li>
 </ol>
 </li>
 <li><a href="#TwinCAT Version Management">TwinCAT Version Management</a>
 <ol class="wp-block-list">
  <li><a href="#Pinning Library Effective Versions">Pinning Library Effective Versions</a></li>
  <li><a href="#Standardizing Versions of TwinCAT and Add-On Modules">Standardizing Versions of TwinCAT and Add-On Modules</a></li>
 </ol>
 </li>
 <li><a href="#Tips for using Git with TwinCAT">Tips for using Git with TwinCAT</a>
 <ol class="wp-block-list">
  <li><a href="#Gitignore">Gitignore</a></li>
  <li><a href="#Merging">Merging</a>
  <ol class="wp-block-list">
   <li><a href="#General Workflow">General Workflow</a></li>
   <li><a href="#Conflicts">Conflicts</a></li>
   <li><a href="#Separating LineIDs">Separating LineIDs</a></li>
  </ol>
  </li>
 </ol>
 </li>
 <li><a href="#Other Tips">Other Tips</a></li>
 <li><a href="#Further Reference">Further Reference</a></li>
</ol>

<h2 class="wp-block-heading"><u><a id="TwinCAT Project Settings" name="TwinCAT Project Settings"></a>TwinCAT Project Settings</u></h2>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">There are some settings you can configure when setting up your TwinCAT solution that will optimize your project for use with version control. Instructions for this setup are&nbsp;detailed in my companion blog <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide">Setting up a TwinCAT 3 Project for Version Control</a>; however, I&rsquo;ve included additional details here to give background on why these settings are helpful.</p>

<p class="wp-block-paragraph"><u><a id="Separating Project Components into Individual Files" name="Separating Project Components into Individual Files"></a><strong>Separating Project Components into Individual Files</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Many TwinCAT project components, such as hardware configuration or variable mapping, default to being grouped together into project files. In the context of version control, this means changes to these files will happen often.&nbsp;</p>

<p class="wp-block-paragraph">The version control software will still track these changes, but it may be harder to follow the thread of changes to a specific component in the bulk project file. Furthermore, if every developer is making constant changes to the bulk project file, it increases the chances of merge conflicts and the headaches that may arise because of them.</p>

<p class="wp-block-paragraph">Many of these elements can be separated out into their own individual files. Much like the creation of this article, it is DMC&rsquo;s best practice to save as many elements as possible in separate files to better track and merge changes with them. Instructions for doing so can be found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide#Separate%20Project%20Components%20into%20Individual%20Files">Step 1 of the companion blog.</a></p>

<p class="wp-block-paragraph"><u><a id="Keep Unrestored Links" name="Keep Unrestored Links"></a><strong>Keep Unrestored Links</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">TwinCAT automatically deletes variable links that are found to be invalid in the process image. This can cause problems when merging branches.</p>

<p class="wp-block-paragraph">The process image is only updated when code is recompiled after a merge, not during the merge itself; therefore, although links might be valid after compilation occurs, they can be considered invalid just after a merge and then&nbsp;get deleted.</p>

<p class="wp-block-paragraph">Instructions to prevent this from happening can be found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide#2.%20Keep%20Unrestored%20Links">Step 2 of the Setup Blog</a>. This step also includes a method of exporting variable mappings so that they can later be reimported if they are lost.</p>

<h2 class="wp-block-heading"><u><a id="TwinCAT Version Management" name="TwinCAT Version Management"></a>TwinCAT Version Management</u></h2>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Beckhoff often releases new versions of TwinCAT along with various additional modules. Sometimes this causes problems when developing on a team with multiple engineers.</p>

<ul class="wp-block-list">
 <li><strong>&nbsp;Accidental Project/Component Upgrades</strong></li>
</ul>

<p class="wp-block-paragraph" style="margin-left: 40px;">Developers might work across several projects simultaneously, many of which could be on different TwinCAT versions. <a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_remote_manager/index.html&amp;id=1584127271344589360">TwinCAT Remote Manager</a> can be a great help in this situation &ndash; at least for PLC development &ndash;&nbsp; but developers with newer TwinCAT versions installed might inadvertently upgrade projects &ndash; causing problems for other developers.</p>

<ul class="wp-block-list">
 <li><strong>Library Mismatches</strong></li>
</ul>

<p class="wp-block-paragraph" style="margin-left: 40px;">Sometimes, new TwinCAT versions come with improvements to Beckhoff&rsquo;s standard libraries. Generally, projects are configured to use the most recent library version by default; however, if two engineers have different most recent versions, it can prevent one of them from going online even with otherwise identical code.</p>

<ul class="wp-block-list">
 <li><strong>Supporting Legacy Machines</strong></li>
</ul>

<p class="wp-block-paragraph" style="margin-left: 40px;">Legacy machines might use older versions of TwinCAT. In machine-down events or even less critical troubleshooting, dealing with project versioning/upgrades might eat up critical time. Some hardware may not even be compatible with upgraded versions. All around, it&rsquo;s less of a headache to just have the proper versions available to get online and solve problems with these machines quickly.</p>

<p class="wp-block-paragraph">The following are some actions you can take to ensure smooth support of many projects with varied TwinCAT versions by a team of multiple engineers.</p>

<p class="wp-block-paragraph"><u><a id="Pinning Project Version" name="Pinning Project Version"></a><strong>Pinning Project Version</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">TwinCAT XAE Projects can be pinned to a certain version of TwinCAT. By doing this, you ensure that&nbsp;the Remote Manager will automatically load the proper TwinCAT build&nbsp;&nbsp;whenever you open the project (so long as that build is installed on your system).</p>

<p class="wp-block-paragraph">This will prevent you from accidentally upgrading the project because you forgot to manually select the proper build in Remote Manager. Again, very helpful for a team of multiple engineers that might have many different TwinCAT versions installed on their computers.</p>

<p class="wp-block-paragraph">Instructions for pinning project versions can be found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide#3.%20Pin%20the%20Project%20Version">Step 3 of the Setup Blog</a>.</p>

<p class="wp-block-paragraph"><u><a id="Pinning Library Effective Versions" name="Pinning Library Effective Versions"></a><strong>Pinning Library Effective Versions</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Libraries in TwinCAT projects are set to use the newest version available on a developer&rsquo;s computer by default. This can be a problem, however,&nbsp;if one developer downloads to a PLC with one library version but another developer has a different library as their newest library version.&nbsp;The latter developer will not be able to log into the PLC without changes. At DMC we&rsquo;ve encountered this problem several times when multiple developers are onsite supporting a line.</p>

<p class="wp-block-paragraph">The solution to this is to pin the libraries&rsquo; versions. It generally doesn&rsquo;t matter which library version is picked for each library (unless newer versions have bugfixes that are necessary), so we usually just pick the newest library version available at the time of project creation or deployment.</p>

<p class="wp-block-paragraph">This can create a new problem (especially when supporting legacy machines) if some developers do not have the proper library versions available on their computers. These versions will need to be obtained and installed.</p>

<p class="wp-block-paragraph">Instructions for obtaining, installing, and pinning library versions can be found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide#4.%20Pin%20Library%20Effective%20Versions">Step 4 of the Setup Blog</a>.</p>

<p class="wp-block-paragraph"><u><a id="Standardizing Versions of TwinCAT and Add-On Modules" name="Standardizing Versions of TwinCAT and Add-On Modules"></a><strong>Standardizing Versions of TwinCAT and Add-On Modules</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Each of the above recommendations for keeping items in the project pinned rely on you having the proper TwinCAT/add-on module versions available on your computer in the first place.</p>

<p class="wp-block-paragraph">You can generally determine the project version before opening it by opening the project file in a text editor. For example, the <strong>.tsproj</strong> file for the XAE project shows the project version at the top of the XML.</p>

<figure class="wp-block-image"><img decoding="async" alt="Version control and multi user development with Twincat 3" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TwinCAT_Version_Control_Guide_1.png"  /></figure>

<p class="wp-block-paragraph">&nbsp;TE2000 TCHMI projects should also have version info in the <strong>.hmiproj</strong> file.</p>

<figure class="wp-block-image"><img decoding="async" alt="Version control and multi user development with Twincat" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TwinCAT_Version_Control_Guide_2.png"  /></figure>

<p class="wp-block-paragraph">&nbsp;You can also determine what version of TwinCAT/add-on modules are installed through your control panel&rsquo;s apps &amp; features list.</p>

<p class="wp-block-paragraph">&nbsp;<figure class="wp-block-image"><img decoding="async" alt="Version control and multi user development with Twincat" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TwinCAT_Version_Control_Guide_3.png"  /></figure></p>

<p class="wp-block-paragraph"><figure class="wp-block-image"><img decoding="async" alt="Version control and multi user development with Twincat" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TwinCAT_Version_Control_Guide_4.png"  /></figure><br />
&nbsp;I would definitely recommend downloading and using the most recent version of these tools from <a href="https://www.beckhoff.com/" target="_blank">Beckhoff&rsquo;s website</a> when starting a project.</p>

<p class="wp-block-paragraph">For TwinCAT, it&rsquo;s generally not harmful to upgrade to the most recent minor revision of a build (ex: 4018.33 &#8211;&gt; 4018.58) &ndash; though there are exceptions. It is <em><strong>not</strong></em> necessarily possible to upgrade between major revisions of builds (ex: 4018.33 &#8211;&gt; 4024.22).&nbsp;</p>

<p class="wp-block-paragraph">Beckhoff offers downloads for the <a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_remote_manager/index.html&amp;id=1584127271344589360" target="_blank">TwinCAT Remote Manager</a> of the most recent versions of major revisions for exactly this use, which is very handy.</p>

<p class="wp-block-paragraph">The Remote Manager is not available for additional modules including:&nbsp;</p>

<ul class="wp-block-list">
 <li>TE2000 TCHMI Engineering</li>
 <li>TF2000 TCHMI Runtime</li>
 <li>TF6100 OPC UA</li>
 <li>TE9000 Safety Editor</li>
</ul>

<p class="wp-block-paragraph">Upgrading usually works fairly well, so long as all developers install the same engineering version of each module (if applicable) on their development computers, but there may be situations (like legacy machines or multi-user projects) where upgrading is not practical or possible. For these situations, I recommend hanging onto the installers for the different components of a project and storing them in a central server or repository the whole team can access. This way developers can grab them and install them when necessary.&nbsp;</p>

<p class="wp-block-paragraph">However, <strong>BE WARNED!</strong> You cannot install an older version of TwinCAT on a machine where a newer version is installed. If Remote Manager does not satisfy your needs, you will need to set up a new development environment with the proper build or uninstall the newer builds before you install the old one.</p>

<p class="wp-block-paragraph">It is important to enforce that all developers have the same versions of the project components installed in their development environment. This will ensure the smoothest collaboration between multiple developers.</p>

<p class="wp-block-paragraph">If you&rsquo;d like to learn more about library/TwinCAT versioning, I&rsquo;d recommend reading <a href="https://alltwincat.com/2020/11/02/handling-different-versions-of-twincat/" target="_blank">this excellent blog</a>.</p>

<h2 class="wp-block-heading"><u><a id="Tips for using Git with TwinCAT" name="Tips for using Git with TwinCAT"></a>Tips for using Git with TwinCAT</u></h2>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">DMC commonly uses <a href="https://gitforwindows.org/" target="_blank">Git</a> as a VCS with TwinCAT for the many benefits Git offers for text-based version control. The following topics are by no means a thorough discussion of using Git (there are plenty of resources you can Google for that), but I&rsquo;ve included some tips DMC has discovered along the way that might help you to use Git with TwinCAT.</p>

<p class="wp-block-paragraph">Again, I&rsquo;ll state the disclaimer: by no means are these tips the only or the best way to use Git with TwinCAT! Not even everyone here at DMC uses Git in the same way &ndash; if you&rsquo;ve got suggestions or a workflow that works very well for you, we&rsquo;d love to hear down in the comments!</p>

<p class="wp-block-paragraph"><u><a id="Gitignore" name="Gitignore"></a><strong>Gitignore</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">The <a href="https://www.atlassian.com/git/tutorials/saving-changes/gitignore" target="_blank">.gitignore</a> file is used to tell Git which files it can ignore to prevent the repository from becoming bloated by tracking unnecessary changes. This can be very helpful with TwinCAT project folders which contain items like user-specific Visual Studio configuration files and builds that can be recompiled at will from the source code in the repository.</p>

<p class="wp-block-paragraph">A basic <a href="https://github.com/github/gitignore/blob/main/TwinCAT3.gitignore" target="_blank">TwinCAT 3 gitignore template</a> created by <a href="https://alltwincat.com/2019/12/02/gitignore-for-twincat/" target="_blank">Jakob Sagatowsk</a>i has been added to Github&rsquo;s <a href="https://github.com/github/gitignore" target="_blank">gitignore collection</a>. Of course, this is a basic template and may not cover everything you need to ignore in your project. Another good example, with more items included, is the gitignore for <a href="https://github.com/tcunit/TcUnit/blob/master/.gitignore" target="_blank">TcUnit</a>, by the same creator.</p>

<p class="wp-block-paragraph">The above gitignore examples include the <strong>*.tclrs</strong> file type, which holds license information. Oftentimes at DMC we store these license files in our repositories as a backup for our clients, so we opt not to include this in our gitignores. You can also remove any file types you&rsquo;d like to track as you see fit&nbsp;from your gitignore.</p>

<p class="wp-block-paragraph">After setting up a gitignore in your repository, you may still find that some temporary, user-specific, or unnecessary files are still tracked and not included in the gitignore. Feel free to add them to the gitignore file, but do so with caution. <strong>Make sure, if you&rsquo;re going to add something to the gitignore, you have a good reason for doing so and know that a file doesn&rsquo;t need to be tracked!&nbsp;</strong></p>

<p class="wp-block-paragraph">Some files in TwinCAT projects, like <strong>.xti</strong> files, might update often, even when it seems like you&rsquo;ve made no changes to the project. However, some of these files also include crucial information that you don&rsquo;t want to get lost (for example, IO links), so don&rsquo;t ignore them unless you know you can do so without losing information.</p>

<p class="wp-block-paragraph">In the event you do add a rule to your gitignore, you may find that files are still being tracked that match that rule. This is probably because these files were tracked before the change to the gitignore and need to be manually removed from tracking. Follow the instructions <a href="https://www.atlassian.com/git/tutorials/saving-changes/gitignore#ignoring-a-previously-committed" target="_blank">here</a> to do so.</p>

<p class="wp-block-paragraph"><u><a id="Merging" name="Merging"></a><strong>Merging</strong></u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">The ability to merge changes from different development branches into one project is one of the greatest strengths of using a VCS with TwinCAT. Other automation platforms may or may not have their own merge tools, but TwinCAT has an advantage with its plaintext file formats. This means we can leverage Git&rsquo;s built-in merging functionalities to make our lives much easier.</p>

<p class="wp-block-paragraph">Again, this&nbsp;is not an in-depth explanation of merging (which would require a much longer article), but it is just some tips and tricks DMC has found along the way.</p>

<p class="wp-block-paragraph"><u><a id="General Workflow" name="General Workflow"></a>General Workflow</u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Beckhoff recommends <a href="https://infosys.beckhoff.com/content/1033/tc3_sourcecontrol/409513611.html?id=7562613490256544816" target="_blank">configuring TcProjectCompare</a>, TwinCAT&rsquo;s merge tool, to merge projects and deactivating automatic merging.</p>

<p class="wp-block-paragraph">In general, DMC has not found this to be necessary. Although problems can occur, we often find that most merges done directly through Git are successful, especially when splitting the project into individual files.&nbsp;</p>

<p class="wp-block-paragraph">Merges involving hardware linking or multiple developers making changes to the same aspects of project configuration can sometimes be more suspect. They might require a closer eye on the merge result. In general, it is good practice to ensure the project compiles properly after a merge and that changes to project configuration are preserved. But for typical changes to POUs, DUTs, and other code objects, the merging process is generally quite smooth.</p>

<p class="wp-block-paragraph">If you&rsquo;ve run into situations where you often find items are lost in merges or have configured TcProjectCompare as a merge tool and have some thoughts, please leave a comment below!</p>

<p class="wp-block-paragraph"><u><a id="Conflicts" name="Conflicts"></a>Conflicts</u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Inevitably&nbsp;during multi-user development, you will run into conflicts when two developers have edited the same piece of code. To manually resolve them, a mergetool is needed. Mergetools allow you to manually indicate which portions of conflicting code you&rsquo;d like to keep.&nbsp;</p>

<p class="wp-block-paragraph">DMC often uses <a href="https://code.visualstudio.com/" target="_blank">VS Code</a> as a mergetool for TwinCAT development. To configure VS Code as a mergetool, see&nbsp;<a href="https://www.roboleary.net/vscode/2020/09/15/vscode-git.html" target="_blank">these instructions</a>. Of course, you can use whichever mergetool you prefer.</p>

<p class="wp-block-paragraph">One common merge conflict that is specific to TwinCAT is conflicts in the &ldquo;LineID&rdquo; XML elements at the end of code files. POUs, DUTs, and other code objects are stored in an XML format. Sometimes, if extensive changes have been made in two separate branches to that code object, conflicts occur in these elements. Using VS Code as a mergetool, these conflicts look like this:</p>

<p class="wp-block-paragraph"><br />
<figure class="wp-block-image"><img decoding="async" alt="Version control and multi user development with Twincat" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TwinCAT_Version_Control_Guide_5.png"  /></figure></p>

<p class="wp-block-paragraph">In this scenario, it generally doesn&rsquo;t matter which change is accepted. Accept one of the two changes, then make sure to open the project/code object in TwinCAT and compile before committing the in-progress merge.&nbsp;</p>

<p class="wp-block-paragraph">When opening the code object, TwinCAT should handle properly correcting the format of these XML elements. If there aren&rsquo;t problems in the compilation, you should be good to go.</p>

<p class="wp-block-paragraph"><u><a id="Separating LineIDs" name="Separating LineIDs"></a>Separating LineIDs</u></p>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">Alternatively, to avoid these conflicts and LineIDs appearing in source control altogether, you can activate the <a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_userinterface/4692665483.html&amp;id=">Separate LineIDs</a> option in your TwinCAT XAE environment.</p>

<p class="wp-block-paragraph">LineIDs are required for breakpoint handling and to ensure code lines can be assigned to machine code instructions. But instead of storing them with the source code (as is done by default), this option separates them into a file called&nbsp;<strong>LineIDs.dbg</strong>&nbsp;&#8211; a binary file which is rebuilt when the project is modified/saved.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/SeparateLineIDs_1-1.png"  /></figure>

<p class="wp-block-paragraph">If you paid close attention to the aforementioned gitignore templates, you might have noticed that <strong>LineIDs.dbg</strong>&nbsp;can be safely ignored by source control since it is constantly being rebuilt. Comparing the same source code file generated with this setting deactivated and with it activated, we can see that the only difference is the removal of the LineIDs section &#8211; which should prevent us from tracking changes and running into merge conflicts in this section.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/SeparateLineIDFileDifferences_1-1.png"  /></figure>

<p class="wp-block-paragraph"><strong>A word of caution</strong>&nbsp;&#8211; if you plan to use this setting with a multi-developer team, you&apos;ll need to make sure&nbsp;<strong><em>all</em></strong>&nbsp;developers have the same value for this setting in their development environments. Otherwise you may wreak havoc on your source control, with some developers constantly saving their files with separate LineIDs and others constantly saving their files with included LineIDs.</p>

<p class="wp-block-paragraph">Instructions for setting the <strong>Separate LineIDs</strong>&nbsp;setting can be found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide#5.%20Separating%20LineIDs">Step 5 of the Setup Blog</a>.</p>

<h2 class="wp-block-heading"><u><a id="Other Tips" name="Other Tips"></a>Other Tips</u></h2>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">It&rsquo;s generally a good idea to close the project before switching branches/performing merges. TCXAE will sometimes detect if the project has been externally modified (ex: by Git), but sometimes it won&rsquo;t. To make sure you&rsquo;re not accidentally editing the wrong project version, close the project and re-open after you&rsquo;re done performing Git operations.</p>

<h2 class="wp-block-heading"><u><a id="Further Reference" name="Further Reference"></a>Further Reference</u></h2>

<p class="wp-block-paragraph"><em><a href="#Table of Contents">Back to Table of Contents</a></em></p>

<p class="wp-block-paragraph">For more information on version control in general and with TwinCAT, please see the following links:</p>

<ul class="wp-block-list">
 <li style="margin-left: 40px;"><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10318/setting-up-a-twincat-3-project-for-version-control-a-step-by-step-guide">Setting up a TwinCAT 3 Project for Version Control: A Step-by-Step Guide</a></li>
 <li style="margin-left: 40px;"><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_sourcecontrol/index.html&amp;id=6468228250695776754" target="_blank">TwinCAT Source Control Infosys Section</a></li>
 <li style="margin-left: 40px;"><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_remote_manager/index.html&amp;id=1584127271344589360" target="_blank">TwinCAT Remote Manager Infosys Section</a></li>
 <li style="margin-left: 40px;"><a href="https://alltwincat.com/2020/11/02/handling-different-versions-of-twincat/" target="_blank">TwinCAT Versioning Blog</a></li>
 <li style="margin-left: 40px;"><a href="https://towardsdatascience.com/version-control-101-definition-and-benefits-6fd7ad49e5f1" target="_blank">Version Control Introduction</a></li>
 <li style="margin-left: 40px;"><a href="https://gitforwindows.org/" target="_blank">Git For Windows</a></li>
 <li style="margin-left: 40px;"><a href="https://code.visualstudio.com/" target="_blank">VS Code</a></li>
 <li style="margin-left: 40px;"><a href="https://www.roboleary.net/vscode/2020/09/15/vscode-git.html" target="_blank">Configuring VS Code as a Mergetool</a></li>
 <li style="margin-left: 40px;"><a href="https://www.atlassian.com/git/tutorials/saving-changes/gitignore" target="_blank">Atlassian&rsquo;s Gitignore Tutorial</a></li>
 <li style="margin-left: 40px;"><a href="https://alltwincat.com/2019/12/02/gitignore-for-twincat/" target="_blank">TwinCAT Gitignore Blog</a></li>
 <li style="margin-left: 40px;"><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_userinterface/4692665483.html&amp;id=">TwinCAT LineIDs Infosys Page</a></li>
</ul>

<p class="wp-block-paragraph">If you&rsquo;ve got any other suggestions for tips and tricks to use TwinCAT with version control and/or multiple users, please leave them in the comments below! DMC is always committed to improving our workflow, so we&rsquo;d love to hear your thoughts.</p>

<p class="wp-block-paragraph"><strong>Learn more about DMC&apos;s <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">Beckhoff and TwinCAT 3 programming </a>expertise and <a href="https://static.dmcinfo.com/contact">contact us</a> for your next project.&nbsp;</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18615/version-control-and-multi-user-development-with-beckhoff-twincat-3/">Version Control and Multi-user Development with Beckhoff TwinCAT 3</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Executing Command-Line Commands in TwinCAT</title>
		<link>https://static.dmcinfo.com/blog/19413/executing-command-line-commands-in-twincat/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Mon, 22 Mar 2021 15:33:02 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[TwinCAT]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/19413/executing-command-line-commands-in-twincat/</guid>

					<description><![CDATA[<p>From reading and writing XML files to restarting the IPC, TwinCAT PLCs offer a lot of functionality through their&#160;built-in libraries. Additionally, TwinCAT runs on a Windows environment that can offer an even wider variety of functionalities to the user. In this blog, I will be discussing how to leverage TwinCAT&#8217;s ability to send commands to [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19413/executing-command-line-commands-in-twincat/">Executing Command-Line Commands in TwinCAT</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">From reading and writing XML files to restarting the IPC, TwinCAT PLCs offer a lot of functionality through their&nbsp;built-in libraries. Additionally, TwinCAT runs on a Windows environment that can offer an even wider variety of functionalities to the user. In this blog, I will be discussing how to leverage TwinCAT&rsquo;s ability to send commands to the Windows command-line interface in order to expand its capabilities.&nbsp;</p>

<p class="wp-block-paragraph">To send such commands through a TwinCAT PLC, we can use the function NT_StartProcess in the TwinCAT Utilities Library. This function simply starts a process on the Windows computer and allows you to pass in command-line parameters along with it. Therefore, with the correct syntax, we can pass in commands to the Windows command line.</p>

<h2 class="wp-block-heading">Process</h2>

<p class="wp-block-paragraph">To start, we must make sure we import the Utilities Library. This can be done by right-clicking the references tab in the project tree and clicking &quot;Add Library.&quot; Select the Utilities Library and press &quot;OK.&quot;</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Utilities-Library.png"  /></figure>

<p class="wp-block-paragraph">To utilize the NT_StartProcess function, you first need to locate the path to the executable. The best way to find the path is to open the command prompt and enter:</p>

<pre class="”brush:xml”">
 
where cmd
</pre>

<p class="wp-block-paragraph">&nbsp;<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Command-Prompt.png"  /></figure></p>

<p class="wp-block-paragraph"><em>Note: The path will likely be at C:\Windows\System32\cmd.exe</em></p>

<p class="wp-block-paragraph">Once you&rsquo;ve located the path to the executable, you need to pass in the path to the command-line executable on the system as PATHSTR, and a string for the command you wish to execute as COMDLINE. In order to properly format the command string, all you have to do is prepend &lsquo;/C &lsquo; to whatever command you wish to execute, making sure to include the space.&nbsp;</p>

<h2 class="wp-block-heading">Moving&nbsp;Files</h2>

<p class="wp-block-paragraph">For this example, I&rsquo;ll demonstrate how we can move a file on the Windows file system. This is something that is able to be done entirely within TwinCAT, but&nbsp;is much easier and quicker to do through the command-line interface. Here we are using the CONCAT function to build out our command.</p>

<pre class="”brush:xml”">

// Build Command String
sCommand := &apos;/C &apos;; 				// Special command indicating command string input
sCommand := CONCAT(sCommand, &apos;move &apos;);		// Add move command
sCommand := CONCAT(sCommand, sTargetFilePath);	// Add target file
sCommand := CONCAT(sCommand, &apos; &apos;);			// Required space for command 
sCommand := CONCAT(sCommand, sTargetDirectory);	// Add target location

</pre>

<p class="wp-block-paragraph">Passing both strings into NT_StartProcess and triggering the START bit will cause that command to be executed.</p>

<pre class="”brush:xml”">

Process(
	NETID := &apos;&apos;, 						// Local System
	PATHSTR := &apos;C:\Windows\System32\cmd.exe&apos;, 		// Path to local cmd executable
	COMNDLINE := sCommand,				// Command to be executed
	ERR =&gt; bError,						// Error Output
	ERRID =&gt; iErrorId					// Error Id Output
);

</pre>

<p class="wp-block-paragraph">You will likely not see the command prompt appear, but it may for more lengthy processes.&nbsp;</p>

<p class="wp-block-paragraph">Keep in mind that it can be difficult to debug these command executions.&nbsp;If the path to the executable or the syntax of the command is incorrect,&nbsp;you will never see any command window pop up&nbsp;and likely will not receive an error. I suggest confirming the command works in an instance of the command prompt before porting it over to TwinCAT. More information on the other functionalities of the NT_StartProcess function can be found on <a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tcplclib_tc2_utilities/35042443.html&amp;id=" target="_blank">Beckhoff&rsquo;s website</a>.</p>

<h2 class="wp-block-heading">Working Example</h2>

<p class="wp-block-paragraph"><strong>Variable Declaration</strong></p>

<pre class="”brush:xml”">

PROGRAM MAIN
VAR
	Process			: NT_StartProcess;
	sTargetFilePath  	: STRING(255);
	sTargetDirectory 	: STRING(255);
	sCommand		: STRING(255);
	bTrigger		: BOOL := FALSE;
	bError			: BOOL;
	iErrorId			: UDINT;
END_VAR

</pre>

<p class="wp-block-paragraph"><strong>Logic</strong></p>

<pre class="”brush:xml”">

// File Locations
sTargetFilePath := &apos;C:\NET-DRIVE\NewOrders\Original.xml&apos;;
sTargetDirectory := &apos;C:\NET-DRIVE\OldOrders&apos;;

// Build Command String
sCommand := &apos;/C &apos;; 					// Special command indicating command string input
sCommand := CONCAT(sCommand, &apos;move &apos;);		// Add move command
sCommand := CONCAT(sCommand, sTargetFilePath);	// Add target file
sCommand := CONCAT(sCommand, &apos; &apos;);			// Required space for command 
sCommand := CONCAT(sCommand, sTargetDirectory);	// Add target location

// Output -&gt; &lsquo;/C move C:\NET-DRIVE\NewOrders\Original.xml &apos;C:\NET-DRIVE\OldOrders&rsquo;



Process(
	NETID := &apos;&apos;, 					// Local System
	PATHSTR := &apos;C:\Windows\System32\cmd.exe&apos;, 	// Path to local cmd executable
	COMNDLINE := sCommand,			// Comnmand to be executed
	ERR =&gt; bError,					// Error Output
	ERRID =&gt; iErrorId				// Error Id Output
);

// Trigger Command
IF bTrigger THEN
	bTrigger := FALSE;
	Process(START:=TRUE);
	Process(START:=FALSE);
END_IF

</pre>

<p class="wp-block-paragraph">TwinCAT natively offers a large amount of functionality to the user. The NT_StartProcess function&nbsp;is a great way to expand its&nbsp;capabilities&nbsp;to start programs and custom scripts from the PLC. Now, through the process described in this article, we can use the TwinCAT PLC to access the windows command prompt!</p>

<p class="wp-block-paragraph"><strong>Read more about DMC&rsquo;s </strong><a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming"><strong>Beckhoff and TwinCAT programming expertise</strong></a><strong> and </strong><a href="/contact"><strong>contact us</strong></a><strong> to get started on your next project. </strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/19413/executing-command-line-commands-in-twincat/">Executing Command-Line Commands in TwinCAT</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
