SOES/soes/doc/html/tutorial_8txt.html

424 lines
28 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>SOES: tutorial.txt File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<!-- Generated by Doxygen 1.7.4 -->
<div id="top">
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">SOES&#160;<span id="projectnumber">v1.0.0</span></div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main&#160;Page</span></a></li>
<li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
<li class="current"><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
<div id="navrow2" class="tabs2">
<ul class="tablist">
<li><a href="files.html"><span>File&#160;List</span></a></li>
<li><a href="globals.html"><span>Globals</span></a></li>
</ul>
</div>
</div>
<div class="header">
<div class="headertitle">
<div class="title">tutorial.txt File Reference</div> </div>
</div>
<div class="contents">
<table class="memberdecls">
</table>
<hr/><a name="details" id="details"></a><h2>Detailed Description</h2>
<div class="textblock"><h2><a class="anchor" id="general"></a>
General</h2>
<p>The SOES is a library that provides the Micro Controller user application with the means to access the EtherCAT fieldbus communication environment:</p>
<ul>
<li>EtherCAT State Machine</li>
<li>Mailbox Interfaces</li>
<li>Protocols<ul>
<li>CoE</li>
<li>FoE + bootstrap template</li>
</ul>
</li>
</ul>
<p>Support for mailbox and protocols are typical examples when you need a slave stack to control the Application Layer of EtherCAT. The PDI used for such applications is either SPI or some Micro Controller Interface</p>
<p>The following sections show some basic examples on how to get the SOES up and running, as well as a lightweight example on howto design your slave. Since all code is local to the application or global variables, it is possible to tweak and optimize when possible.</p>
<p>Our target Application:</p>
<ul>
<li>Inputs 40bit<ul>
<li>One button 8bit</li>
<li>One encoder value 32bit</li>
</ul>
</li>
<li>Outputs 8bit<ul>
<li>LED 8bit</li>
</ul>
</li>
<li>Parameters<ul>
<li>Encoder settings</li>
</ul>
</li>
<li>Slave commands<ul>
<li>Reset counter</li>
</ul>
</li>
</ul>
<p>Now to translate and implement on top of SOES.</p>
<p>First look on the start up code. This example shows how to add a main function that will be called by startup code. In this example main's only purpose is to spawn two new tasks. One that executes SOES and one that control the ERROR LED. Some ESCs provided a pin for the RUN LED, some even for the ERROR LED, if it don't you can control them from the slave Micro Controller. We'll focus on the "soes" task.</p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">int</span> main (<span class="keywordtype">void</span>)
{
rprintp (<span class="stringliteral">&quot;SOES (Simple Open EtherCAT Slave)\nsoes test\n&quot;</span>);
<span class="comment">/* task_spawn (&quot;led_run&quot;, led_error, 15, 512, NULL); /</span>
<span class="comment"> task_spawn (&quot;led_error&quot;, led_error, 15, 512, NULL);</span>
<span class="comment"> task_spawn (&quot;soes&quot;, soes, 9, 1024, NULL);</span>
<span class="comment"></span>
<span class="comment"> return (0);</span>
<span class="comment">}</span>
</pre></div><h2><a class="anchor" id="configuration"></a>
Configuration</h2>
<p>The function soes is our EtherCAT slave device and can be split in 3 parts. Hardware Init, Software Init and Application loop. We will start with the Hardware Init.</p>
<ul>
<li>Hardware Init<ul>
<li>esc_reset, special function used for ESC reset if no Physical EEPROM used. This is local to the Application not part of the generic ESC handling.</li>
<li>ESC_init, initialise SPI communication or similar</li>
<li>Wait for ESC is started, waiting for SPI to be up and running, we'll query the ESC register DL status if EEPROM loaded OK and PDI operational, eg. SPI OK.</li>
</ul>
</li>
</ul>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> soes (<span class="keywordtype">void</span> *arg)
{
TXPDOsize = <a class="code" href="esc_8h.html#ab08e40af06cd134cb90dd192accbb15c">SM3_sml</a> = <a class="code" href="esc__coe_8c.html#a5d1fb9538a28be98ec8ee762140ada35">sizeTXPDO</a> ();
RXPDOsize = <a class="code" href="esc_8h.html#a8381cf08815e916991c9e9f07faecf90">SM2_sml</a> = <a class="code" href="esc__coe_8c.html#a836e3ff62cd9bba1ca2a5f5481104ba9">sizeRXPDO</a> ();
esc_reset ();
<a class="code" href="esc_8h.html#a1e57480c1f1963ef43315a2da703af69">ESC_init</a> ((<span class="keywordtype">void</span> *)spi_name);
task_delay (tick_from_ms (200));
<span class="comment">// wait until ESC is started up</span>
<span class="keywordflow">while</span> ((<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a> &amp; 0x0001) == 0)
{
<a class="code" href="esc_8h.html#a2664adef01c5c5f228f8512fcae3eb57">ESC_read</a> (<a class="code" href="esc_8h.html#a7307fb7c3f7d54c7a44910f7100574cf">ESCREG_DLSTATUS</a>, (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>,
sizeof (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>), (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a>);
<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a> = etohs (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>);
}
<span class="comment">// reset ESC to init state</span>
<a class="code" href="esc_8c.html#a9794dd94da984eb6bfb88879aabf4e3d">ESC_ALstatus</a> (<a class="code" href="esc_8h.html#abbfee5404d9c373b5dd4145d7468a17a">ESCinit</a>);
...
}
</pre></div><ul>
<li>Software Init<ul>
<li>Reset the slave into Init state by writing AL Status register.</li>
<li>Clear Errors by writing AL Status Code register.</li>
<li>Stop the Application Layer, basically we disable the SyncManagers that implicitly block the data exchange.</li>
</ul>
</li>
</ul>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> soes (<span class="keywordtype">void</span> *arg)
{
...
<span class="keywordflow">while</span> ((<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a> &amp; 0x0001) == 0)
{
<a class="code" href="esc_8h.html#a2664adef01c5c5f228f8512fcae3eb57">ESC_read</a> (<a class="code" href="esc_8h.html#a7307fb7c3f7d54c7a44910f7100574cf">ESCREG_DLSTATUS</a>, (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>,
sizeof (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>), (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a>);
<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a> = etohs (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#aa8a709bebf153046f21e9731a7bf4061">DLstatus</a>);
}
<span class="comment">// reset ESC to init state</span>
<a class="code" href="esc_8c.html#a9794dd94da984eb6bfb88879aabf4e3d">ESC_ALstatus</a> (<a class="code" href="esc_8h.html#abbfee5404d9c373b5dd4145d7468a17a">ESCinit</a>);
<a class="code" href="esc_8c.html#ae49fff6e6440edd2c55a077d724b898c">ESC_ALerror</a> (<a class="code" href="esc_8h.html#acd028c8cb5d08a99cc31bc2ee46c97fd">ALERR_NONE</a>);
<a class="code" href="esc_8c.html#af114806603011938e35ae366d115d90f">ESC_stopmbx</a> ();
<a class="code" href="esc_8c.html#a81ea48b9683662e8bed01fbb77826236">ESC_stopinput</a> ();
<a class="code" href="esc_8c.html#aea60761cf8862550e8901aa996069f8d">ESC_stopoutput</a> ();
<span class="comment">// application run loop</span>
<span class="keywordflow">while</span> (1)
...
}
</pre></div><ul>
<li>Application loop<ul>
<li>ALevent handling, ALevent hold information on changes in ALControl or SyncManagers. ALControl for state changes and SyncManagers for changes written by EtherCAT in local memory mapped to active SyncManagers</li>
<li>ESC_state for state handling, such as state step up or down with correct error and acknowledge response.</li>
<li>Mailbox handler, generic support of mailboxes used by all Application Layer protocols.</li>
<li>On mailbox actions we'll also check if we need to use a specific protocol handler to handle the incoming or outgoing Mailbox data.</li>
</ul>
</li>
</ul>
<p>Up until the now we're using the SOES protocol stack without any application specific calls. Next up we'll look at the application Code, here named DIG_process ().</p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> soes (<span class="keywordtype">void</span> *arg)
{
...
<span class="comment">// application run loop</span>
<span class="keywordflow">while</span> (1)
{
<span class="keywordflow">if</span>((<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#acd205a5c7f82b724686f0794f06a12cd">ALstatus</a> &amp; 0x0f) == <a class="code" href="esc_8h.html#abbfee5404d9c373b5dd4145d7468a17a">ESCinit</a>)
{
txpdomap = DEFAULTTXPDOMAP;
rxpdomap = DEFAULTRXPDOMAP;
<a class="code" href="esc__coe_8c.html#a5ddbd167b7b79d375b2ce53e2b536347">txpdoitems</a> = DEFAULTTXPDOITEMS;
<a class="code" href="esc__coe_8c.html#a8bf6e1739ce6b8147f92dc36162b9e54">rxpdoitems</a> = DEFAULTTXPDOITEMS;
}
<a class="code" href="esc_8h.html#a2664adef01c5c5f228f8512fcae3eb57">ESC_read</a> (<a class="code" href="esc_8h.html#a6da09b045593c131194d037cf180af6e">ESCREG_LOCALTIME</a>, (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#ac435e669f2d950b9c8ba9d5599dc87e6">Time</a>, sizeof (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#ac435e669f2d950b9c8ba9d5599dc87e6">Time</a>),
(<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a>);
<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#ac435e669f2d950b9c8ba9d5599dc87e6">Time</a> = etohl (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#ac435e669f2d950b9c8ba9d5599dc87e6">Time</a>);
<a class="code" href="esc_8h.html#a5786bd4c441fafac35331fa755730f84">ESC_ALevent</a>();
<a class="code" href="esc_8c.html#a1f4da4aa96dc469b218abf33ff857130">ESC_state</a> ();
<span class="keywordflow">if</span> (<a class="code" href="esc_8c.html#ae75d37a1bdce82374c3b262f18945cb3">ESC_mbxprocess</a> ())
{
<a class="code" href="esc__coe_8c.html#a71c76794b7e4ed125cc9cda0e8508ccd">ESC_coeprocess</a> ();
<a class="code" href="esc__foe_8c.html#a57ace265be44ccc2a0af313d007261b2">ESC_foeprocess</a> ();
<a class="code" href="esc_8c.html#aa783bb45ace470b98607ce7c4af0460f">ESC_xoeprocess</a> ();
}
DIG_process ();
};
}
</pre></div><h2><a class="anchor" id="application"></a>
Application</h2>
<p>The function DIG_process is the User part of the application and could be joined by more cyclic User functions for executing other parts of the application. The example code can be split in 2 parts</p>
<ul>
<li>Outputs<ul>
<li>Start by evaluating if we're in a state supporting update of outputs, eg. Operational state.</li>
<li>If we're in OP we can read the current PDO data in the 3-buffer SyncManager mapped to the output SM, the default is SyncManager2, we read the ESC RAM address of SM2 and store it at the local address of the local variable Wb.LED. We'll read RXPDOsize bytes to trigger a complete SyncManager read.</li>
<li>After local variables have been refreshed we basically write the local PDO variables to the User application, ex. a GPIO.</li>
<li>Basically this is the API of the SOES toward the User Application.</li>
<li>This function also include a watchdog mechanism, if triggered it will shutdown the outputs and trigger a state changes to safe operational. AlError is updated with cause of error to inform the Master.</li>
</ul>
</li>
</ul>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> RXPDO_update (<span class="keywordtype">void</span>)
{
<a class="code" href="esc_8h.html#a2664adef01c5c5f228f8512fcae3eb57">ESC_read</a> (<a class="code" href="esc_8h.html#a17b011cd3b4d2c7aaa4d97a3f9140d9e">SM2_sma</a>, &amp;Wb.LED, RXPDOsize, (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a>);
}
<span class="keywordtype">void</span> DIG_process (<span class="keywordtype">void</span>)
{
<span class="keywordflow">if</span> (App.state &amp; APPSTATE_OUTPUT)
{
<span class="keywordflow">if</span> (<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a> &amp; <a class="code" href="esc_8h.html#a7f4270f5e37d8e797a3033523e0f84d0">ESCREG_ALEVENT_SM2</a>) <span class="comment">// SM2 trigger ?</span>
{
RXPDO_update ();
reset_wd ();
gpio_set(GPIO_LED, Wb.LED &amp; BIT(0));
}
<span class="keywordflow">if</span> (!wd_cnt)
{
<a class="code" href="esc_8c.html#aea60761cf8862550e8901aa996069f8d">ESC_stopoutput</a> ();
<span class="comment">// watchdog, invalid outputs</span>
<a class="code" href="esc_8c.html#ae49fff6e6440edd2c55a077d724b898c">ESC_ALerror</a> (<a class="code" href="esc_8h.html#af236abe4b811bcebfb6556e3ddd85a20">ALERR_WATCHDOG</a>);
<span class="comment">// goto safe-op with error bit set</span>
<a class="code" href="esc_8c.html#a9794dd94da984eb6bfb88879aabf4e3d">ESC_ALstatus</a> (<a class="code" href="esc_8h.html#a8badc20d57f274700ff6786013f4dba8">ESCsafeop</a> | <a class="code" href="esc_8h.html#abc139331f4812b302e34bb3709ff915b">ESCerror</a>);
wd_trigger = 1;
}
}
<span class="keywordflow">else</span>
{
reset_wd ();
}
...
}
</pre></div><ul>
<li>Inputs<ul>
<li>Is handled a bit simpler than outputs but in reverse order, the slave will continue update the inputs in state Safe Operational.</li>
<li>Here we first read User application data from ex. GPIO and then write to local PDO variables.</li>
<li>After the local variables have been refreshed we write those to the current PDO data 3-buffer SyncManager mapped to the input SM, the default is SyncManager3. This way we update the ESC RAM address with User Application data accessed by the EtherCAT master.</li>
</ul>
</li>
</ul>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> TXPDO_update (<span class="keywordtype">void</span>)
{
<a class="code" href="esc_8h.html#a1e2ef25b8a36c48016abd5ff20166d9f">ESC_write</a> (<a class="code" href="esc_8h.html#a115f471e25ada517dc92451cbf921416">SM3_sma</a>, &amp;Rb.button, TXPDOsize, (<span class="keywordtype">void</span> *) &amp;<a class="code" href="esc_8h.html#ad2be96a7ede58a01fd408ed9ad4e0970">ESCvar</a>.<a class="code" href="struct__ESCvar.html#a447ec4716c0a1139f9987ea6df3ae364">ALevent</a>);
}
<span class="keywordtype">void</span> DIG_process (<span class="keywordtype">void</span>)
{
...
Rb.button = gpio_get(GPIO_WAKEUP);
Cb.reset_counter++;
Rb.encoder = Cb.reset_counter;
TXPDO_update ();
}
</pre></div><h2><a class="anchor" id="ApplicationdataProcessdata"></a>
ApplicationdataProcessdata</h2>
<p>To run application data through EtherCAT processdata we need to describe for the fieldbus what data we have and will read/write. For this we have 3 objects, the ESI file, SII-EEPROM and CoE Object Dictionary. The first 2 are mandatory and the third is a very convenient way of describing complex slaves.</p>
<p>Our strategy is to keep the ESI file and the SII-EEPROM as thin as possible to avoid duplication of data that need to be maintained. Both will hold the bare minimum of mandatory + optional data to pass CTT. Optional data will be included to tell EtherCAT that detailed information can be retrieved via CoE from the OD stored in the slave it self.</p>
<h2><a class="anchor" id="SII-EEPROM"></a>
SII-EEPROM</h2>
<p>Snapshot from SII information matrix from EtherCAT communication slides.</p>
<div class="image">
<img src="sii_pdo.png" alt="sii_pdo.png"/>
<div class="caption">
Our target slave is Fixed PDO and OD</div></div>
<h2><a class="anchor" id="ESI-file"></a>
ESI-file</h2>
<p>Snapshot from ESI tree from EtherCAT communication slides.</p>
<div class="image">
<img src="esi_pdo.png" alt="esi_pdo.png"/>
<div class="caption">
mandatory and optional ESI data</div></div>
<p>To briefly give a hint what are describe in the ESI and SII we're listing a set of included elements marked M for mandatory and O for optional.</p>
<div class="fragment"><pre class="fragment"> - Vendor (M) , Describes the identity.
- Id (M), Hex, EtherCAT Vendor ID, OD 1018.01
- Name (M), NameType, Expedient vendor name
- Descriptions (M), Describes the EtherCAT device(s) using elements.
- Groups (M), Similar devices can be assigned to one group.
- Group (M), One group groups similar devices with slightly different features
- Type (M), A reference handle corresponding to the GroupType value in Description:Devices:Device:Group
- Name (M), Name for this group show by a configuration tool
- Devices (M), Element devices may describe one or several devices with their EtherCAT features such as SyncManagers, FMMUs and Dictionaries
- Device (O), Holds all information about the device like syncmanagers and FMMU, <span class="keywordtype">object</span> dictionary, data types and the PDO mapping and assign description
- Device ATT: Physics (M),<span class="keywordtype">string</span>, Physics at individual ports
- Type (M), Device identity
- Type ATT:ProductCode=&quot;<span class="preprocessor">#x98123467&quot; </span>
<span class="preprocessor"></span> - Type ATT:RevisionNo=<span class="stringliteral">&quot;#x00000001&quot;</span>
- Name (M), Detailed name of device shown by a configuration tool (not used <span class="keywordflow">for</span> identification)
- GroupType (M), Reference to a group (described in element Groups) to which <span class="keyword">this</span> device should be assigned to. Name of the handle used in element Groups:Group:Type
- Fmmu (O), String to describe function, Outputs -&gt; RxPDO, Inputs -&gt; TxPDO , MBoxState -&gt; FMMU is used to poll Input Mailbox
- Sm (O), Description of SyncManager including start address and direction.
- MBoxOut Mailbox Data Master -&gt; Slave
- MBoxIn Mailbox Data Slave -&gt; Master
- Outputs Process Data Master -&gt; Slave
- Inputs Process Data Slave -&gt; master
- Sm ATT:DefaultSize=<span class="stringliteral">&quot;128&quot;</span> , Size
- Sm ATT:StartAddress=<span class="stringliteral">&quot;#x1000&quot;</span> , Start address
- Sm ATT:ControlByte=<span class="stringliteral">&quot;#x26&quot;</span> , Settings , Bit [1][0] = 10, Operation mode Mailbox, 00 Buffered 3.
- Sm ATT:Enable=<span class="stringliteral">&quot;1&quot;</span>, Enabled
- Mailbox (O), Description of available mailbox protocols
- Mailbox ATT: DataLinkLayer=<span class="stringliteral">&quot;true&quot;</span>, Support of Mailbox Data Link Layer is mandatory.
- CoE (O), Device support CoE
- CoE (O) ATT: SdoInfo=&quot;true&quot; , SDO Information Service
- CoE (O) ATT: CompleteAccess=&quot;false&quot; , SDO complete access not supported
- CoE (O) ATT: PdoUpload=&quot;true&quot;, PDO description uploaded from the slave&#39;s <span class="keywordtype">object</span> dictionary and SyncManager length calculated based on the same
- Dc (O), describes synchronization modes supported by the device.
- OpMode (O), Definition of supported operation modes
- Name (M), Internal Handle of operation mode
- Desc (O(M)), description of operation mode, recommended, Free Run (no sync), SM Synchronous, DC Synchronous
- AssignActive (M), Value of Latch and Sync Control registers
- Eeprom (O, use is mandatory)
- Data (M)
Or
- ByteSize (M), Byte Size of connected EEPROM device
- ConfigData (M), First 7 words of EEPROM, Configuration Areas
- BootStrap (O), Start address and length of mailboxes for BootStrap
</pre></div><p>So to describe the application we use CoE and Object Dictionary. The mapping between Object Dictionary and the User Application are done via local variables defined as user types. The Object Dictionary itself is stored in a matrix where all the indexes are listed. Every index then have a submatrix with its subindex.</p>
<h2><a class="anchor" id="ObjectDictionary"></a>
ObjectDictionary</h2>
<p>The Object Dictionary used as example follow the CANopen DS301 ranges.</p>
<ul>
<li>0x0000 - 0x0FFF, Data Type Area</li>
<li>0x1000 - 0x1FFF, Communication Area</li>
<li>0x2000 - 0x5FFF, Manufacture specific area</li>
<li>0x6000 - 0x6FFF, Input area</li>
<li>0x7000 - 0x7FFF, Output area</li>
<li>0x8000 - 0x8FFF, Configuration area</li>
<li>0x9000 - 0x9FFF, Information area</li>
<li>0xA000 - 0xAFFF, Diagnosis Area</li>
<li>0xB000 - 0xBFFF, Service Transfer Area</li>
<li>0xC000 - 0xEFFF, Reserved Area</li>
<li>0xF000 - 0xFFFF, Device Area</li>
</ul>
<p>RxPDO , 0x1600 - 0x17FF TxPDO , 0x1A00 - 0x1BFF</p>
<p>Example, on how the the OD index are linked. Top index, SyncManagers Communication Types. In index 0 the 0x04 indicates we have 4 SyncManagers defined. Every SyncManager is assigned a type, in index 1-4, we have standard settings SM0 = 1, SM1 = 2, SM2 = 3, SM3 = 4 from ETG 1000.6, 5.6.7.4.</p>
<ul>
<li>0, Unused</li>
<li>1, MailBox Receive, master to slave</li>
<li>2, MailBox Send, slave to master</li>
<li>3, Processdata output, master to slave</li>
<li>4, Processdata input, slave to master</li>
</ul>
<div class="fragment"><pre class="fragment">objectlist.h
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objectlist SDOobjects[] =
...
{0x1C00, OTYPE_ARRAY, 4, 0, &amp;acName1C00[0], &amp;SDO1C00[0]},
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objd SDO1C00[] =
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acNameNOE[0], 0x04, nil},
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acName1C00_01[0], 0x01, nil},
{0x02, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acName1C00_02[0], 0x02, nil},
{0x03, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acName1C00_03[0], 0x03, nil},
{0x04, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acName1C00_04[0], 0x04, nil}
</pre></div><p>SyncManagers channels 0-31 are listed in SDO1C10-SDO1C2F. If we look at SyncManager channel 2, we see.</p>
<ul>
<li>Type 3, Processdata output, master to slave</li>
</ul>
<p>It got one RxPDO index 0x1600 connected, and the submatrix for 0x1600 link one PDO object index 0x7000 subindex 1. The output object 0x70000108 give you the index 0x7000, subindex 1 and PDO object length 1(byte).</p>
<div class="fragment"><pre class="fragment">objectlist.h
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objd SDO1C12[] =
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acNameNOE[0], 0x01, nil},
{0x01, DTYPE_UNSIGNED16, 16, ATYPE_R, &amp;acNameMO[0], 0x1600, nil}
};
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objd SDO1600[] =
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acNameNOE[0], 0x01, nil},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_R, &amp;acNameMO[0], 0x70000108, nil}
};
</pre></div><p>At PDO level we make the connection between the local application and the object dictionary. For all subindex in the PDO the last element is the address to the local variable.</p>
<div class="fragment"><pre class="fragment">objectlist.h
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objd SDO7000[] =
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acNameNOE[0], 0x01, nil},
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_RW, &amp;acName7000_01[0], 0, &amp;(Wb.LED)}
};
utypes.h
<span class="keyword">typedef</span> <span class="keyword">struct</span>
{
uint8 LED;
} _Wbuffer;
</pre></div><p>Beside SyncManager to PDO mapping we also have mandatory data as</p>
<p>0x1000 Device Type 0x1018 Object Identity 0x10C0 SyncManager Communication Type, as we used as top index when figuring out our PDOs in the Object Dictionary.</p>
<p>For a complete description of the object dictionary you can get guidance by the ETG1000.6 EcatAlProtocols</p>
<p>A useful feature is the Asynchronous use of SDO parameters. In the example we have Parameter set holding an encoder scale value, just for show we also have a read only mirror value of the encoder scale. Parameters defined as a RW SDO parameter and can be written/read by SDO Download or Upload. In addition there is a ESC_objecthandler Hook on SDO Download where you can add additional logic, ex. we execute the mirror of the encoder scale value by assigning the encoder scale value to the mirror.</p>
<div class="fragment"><pre class="fragment">objectlist.h
<a class="code" href="esc_8h.html#af31f651275638bf31941470751b421c6">FLASHSTORE</a> _objd SDO7100[] =
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &amp;acNameNOE[0], 0x02, nil},
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RW, &amp;acName7100_01[0], 0, &amp;(encoder_scale)},
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_R, &amp;acName7100_02[0], 0, &amp;(encoder_scale_mirror)}
};
soes.c
<span class="keywordtype">void</span> <a class="code" href="esc__coe_8h.html#a414bacd094d9023838a396174a695f8d">ESC_objecthandler</a> (uint16 index, uint8 subindex)
{
<span class="keywordflow">switch</span> (index)
{
...
<span class="keywordflow">case</span> 0x7100:
{
<span class="keywordflow">switch</span> (subindex)
{
<span class="keywordflow">case</span> 0x01:
{
encoder_scale_mirror = encoder_scale;
<span class="keywordflow">break</span>;
}
}
<span class="keywordflow">break</span>;
}
...
}
</pre></div><p> This tutorial is just one way of doing it. Enjoy and happy coding!</p>
<p>Andreas Karlsson, rt-labs AB, www.rt-labs.com </p>
</div></div>
<hr class="footer"/><address class="footer"><small>Generated on Wed Jul 10 2013 11:14:19 for SOES by&#160;
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.7.4 </small></address>
</body>
</html>