<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Hi all,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I’m completely new to EtherCAT, so bear with me. I’m in the process of trying to bring up an EL3204 4-channel analog input terminal. I’m running into an issue where it doesn’t look like I’m getting any PDO data back. The working counter
 seems stuck at [0/1]. I have some code based on the dc_user example project (see code below). Our system has the following slave terminals.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Taken from:<o:p></o:p></p>
<p class="MsoNormal">// > ethercat slaves<o:p></o:p></p>
<p class="MsoNormal">// 0  0:0  PREOP  +  EK1100 EtherCAT-Koppler (2A E-Bus)<o:p></o:p></p>
<p class="MsoNormal">// 1  0:1  PREOP  +  EL1809 16K. Dig. Eingang 24V, 3ms<o:p></o:p></p>
<p class="MsoNormal">// 2  0:2  PREOP  +  EL2809 16K. Dig. Ausgang 24V, 0.5A<o:p></o:p></p>
<p class="MsoNormal">// 3  0:3  PREOP  +  EL6224 (IO Link Master)<o:p></o:p></p>
<p class="MsoNormal">// 4  0:4  PREOP  +  EL7031 1K. Schrittmotor-Endstufe (24V, 1.5A)<o:p></o:p></p>
<p class="MsoNormal">// 5  0:5  PREOP  +  EL3204-0200 4K. Ana. Ein. PT1000 (RTD)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">For right now I’m only interested in setting up the EL3204. I ran the “ethercat cstruct” command to get the sync manager and pdo listings for slave 5. Using those I was able to create a ec_pdo_entry_reg_t registration list containing the
 4 channel values. I pass the sync info objects through ecrt_slave_config_pdos, and pass the domain registration list through ecrt_domain_reg_pdo_entry_list. Everything seems to work and the slave node goes to OP state after activating the master.  I printed
 out the byte offset mappings and it looks like ec  master was able to allocate a data buffer and assign the PDOs. Everything looks good.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">But I’m still not getting any PDO data. Everything is reporting back as 0 and the WC is not incrementing. I ran a little experiment and setup some SDO request objects and tried reading back the sensor values using SDOs instead of PDOs,
 and it worked! The readings I’m getting back from the SDOs match the values I was seeing in TwinCAT. So I know the comms are good.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Anyway, if anyone has any suggestions, it would be appreciated.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal">Dave M<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/*****************************************************************************<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  Copyright (C) 2007-2022  Florian Pose, Ingenieurgemeinschaft IgH<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  This file is part of the IgH EtherCAT Master.<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  The IgH EtherCAT Master is free software; you can redistribute it and/or<o:p></o:p></p>
<p class="MsoNormal">*  modify it under the terms of the GNU General Public License version 2, as<o:p></o:p></p>
<p class="MsoNormal">*  published by the Free Software Foundation.<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  The IgH EtherCAT Master is distributed in the hope that it will be useful,<o:p></o:p></p>
<p class="MsoNormal">*  but WITHOUT ANY WARRANTY; without even the implied warranty of<o:p></o:p></p>
<p class="MsoNormal">*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General<o:p></o:p></p>
<p class="MsoNormal">*  Public License for more details.<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  You should have received a copy of the GNU General Public License along<o:p></o:p></p>
<p class="MsoNormal">*  with the IgH EtherCAT Master; if not, write to the Free Software<o:p></o:p></p>
<p class="MsoNormal">*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  ---<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">*  The license mentioned above concerns the source code only. Using the<o:p></o:p></p>
<p class="MsoNormal">*  EtherCAT technology and brand is only permitted in compliance with the<o:p></o:p></p>
<p class="MsoNormal">*  industrial property and similar rights of Beckhoff Automation GmbH.<o:p></o:p></p>
<p class="MsoNormal">*<o:p></o:p></p>
<p class="MsoNormal">****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include <errno.h><o:p></o:p></p>
<p class="MsoNormal">#include <signal.h><o:p></o:p></p>
<p class="MsoNormal">#include <stdio.h><o:p></o:p></p>
<p class="MsoNormal">#include <string.h><o:p></o:p></p>
<p class="MsoNormal">#include <sys/resource.h><o:p></o:p></p>
<p class="MsoNormal">#include <sys/time.h><o:p></o:p></p>
<p class="MsoNormal">#include <sys/types.h><o:p></o:p></p>
<p class="MsoNormal">#include <unistd.h><o:p></o:p></p>
<p class="MsoNormal">#include <time.h><o:p></o:p></p>
<p class="MsoNormal">#include <sys/mman.h><o:p></o:p></p>
<p class="MsoNormal">#include <malloc.h><o:p></o:p></p>
<p class="MsoNormal">#include <sched.h> /* sched_setscheduler() */<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include "ecrt.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Application parameters<o:p></o:p></p>
<p class="MsoNormal">#define FREQUENCY 1000<o:p></o:p></p>
<p class="MsoNormal">#define CLOCK_TO_USE CLOCK_MONOTONIC<o:p></o:p></p>
<p class="MsoNormal">#define MEASURE_TIMING<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Taken from ethercat slaves<o:p></o:p></p>
<p class="MsoNormal">// 0  0:0  PREOP  +  EK1100 EtherCAT-Koppler (2A E-Bus)<o:p></o:p></p>
<p class="MsoNormal">// 1  0:1  PREOP  +  EL1809 16K. Dig. Eingang 24V, 3ms<o:p></o:p></p>
<p class="MsoNormal">// 2  0:2  PREOP  +  EL2809 16K. Dig. Ausgang 24V, 0.5A<o:p></o:p></p>
<p class="MsoNormal">// 3  0:3  PREOP  +  EL6224 (IO Link Master)<o:p></o:p></p>
<p class="MsoNormal">// 4  0:4  PREOP  +  EL7031 1K. Schrittmotor-Endstufe (24V, 1.5A)<o:p></o:p></p>
<p class="MsoNormal">// 5  0:5  PREOP  +  EL3204-0200 4K. Ana. Ein. PT1000 (RTD)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Taken from ethercat cstruct<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/* Master 0, Slave 5, "EL3204-0200"<o:p></o:p></p>
<p class="MsoNormal">* Vendor ID:       0x00000002<o:p></o:p></p>
<p class="MsoNormal">* Product code:    0x0c843052<o:p></o:p></p>
<p class="MsoNormal">* Revision number: 0x001200c8<o:p></o:p></p>
<p class="MsoNormal">*/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">ec_pdo_entry_info_t slave_5_pdo_entries[] = {<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x01, 1}, /* Underrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x02, 1}, /* Overrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 4}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x07, 1}, /* Error */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 7}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x0f, 1}, /* TxPDO State */<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x10, 1}, /* TxPDO Toggle */<o:p></o:p></p>
<p class="MsoNormal">    {0x6000, 0x11, 16}, /* Value */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x01, 1}, /* Underrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x02, 1}, /* Overrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 4}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x07, 1}, /* Error */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 7}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x0f, 1}, /* TxPDO State */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x10, 1}, /* TxPDO Toggle */<o:p></o:p></p>
<p class="MsoNormal">    {0x6010, 0x11, 16}, /* Value */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x01, 1}, /* Underrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x02, 1}, /* Overrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 4}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x07, 1}, /* Error */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 7}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x0f, 1}, /* TxPDO State */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x10, 1}, /* TxPDO Toggle */<o:p></o:p></p>
<p class="MsoNormal">    {0x6020, 0x11, 16}, /* Value */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x01, 1}, /* Underrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x02, 1}, /* Overrange */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 4}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x07, 1}, /* Error */<o:p></o:p></p>
<p class="MsoNormal">    {0x0000, 0x00, 7}, /* Gap */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x0f, 1}, /* TxPDO State */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x10, 1}, /* TxPDO Toggle */<o:p></o:p></p>
<p class="MsoNormal">    {0x6030, 0x11, 16}, /* Value */<o:p></o:p></p>
<p class="MsoNormal">};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">ec_pdo_info_t slave_5_pdos[] = {<o:p></o:p></p>
<p class="MsoNormal">    {0x1a00, 8, slave_5_pdo_entries + 0}, /* RTD TxPDO-Map Ch.1 */<o:p></o:p></p>
<p class="MsoNormal">    {0x1a01, 8, slave_5_pdo_entries + 8}, /* RTD TxPDO-Map Ch.2 */<o:p></o:p></p>
<p class="MsoNormal">    {0x1a02, 8, slave_5_pdo_entries + 16}, /* RTD TxPDO-Map Ch.3 */<o:p></o:p></p>
<p class="MsoNormal">    {0x1a03, 8, slave_5_pdo_entries + 24}, /* RTD TxPDO-Map Ch.4 */<o:p></o:p></p>
<p class="MsoNormal"><span lang="FR">};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="FR">ec_sync_info_t slave_5_syncs[] = {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">    </span>{0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},<o:p></o:p></p>
<p class="MsoNormal">    {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},<o:p></o:p></p>
<p class="MsoNormal">    {2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},<o:p></o:p></p>
<p class="MsoNormal">    {3, EC_DIR_INPUT, 4, slave_5_pdos + 0, EC_WD_DISABLE},<o:p></o:p></p>
<p class="MsoNormal">    <span lang="FR">{0xff}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="FR">// typedef struct {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint16_t alias;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint16_t position;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint32_t vendor_id;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint32_t product_code;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint16_t index;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">//     uint8_t subindex;<o:p></o:p></span></p>
<p class="MsoNormal">//     unsigned int *offset;<o:p></o:p></p>
<p class="MsoNormal">//     unsigned int *bit_position;<o:p></o:p></p>
<p class="MsoNormal">// } ec_pdo_entry_reg_t;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">unsigned int val1Offset = 0u;<o:p></o:p></p>
<p class="MsoNormal">unsigned int val1bit = 0u;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">unsigned int val2Offset = 0u;<o:p></o:p></p>
<p class="MsoNormal">unsigned int val2bit = 0u;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">unsigned int val3Offset = 0u;<o:p></o:p></p>
<p class="MsoNormal">unsigned int val3bit = 0u;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">unsigned int val4Offset = 0u;<o:p></o:p></p>
<p class="MsoNormal">unsigned int val4bit = 0u;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Taken from ethercat cstruct<o:p></o:p></p>
<p class="MsoNormal">ec_pdo_entry_reg_t registrationList[] = {<o:p></o:p></p>
<p class="MsoNormal">    { 0, 5, 2, 0xc843052, 0x6000, 0x11, &val1Offset, &val1bit },<o:p></o:p></p>
<p class="MsoNormal">    { 0, 5, 2, 0xc843052, 0x6010, 0x11, &val2Offset, &val2bit },<o:p></o:p></p>
<p class="MsoNormal">    { 0, 5, 2, 0xc843052, 0x6020, 0x11, &val3Offset, &val3bit },<o:p></o:p></p>
<p class="MsoNormal">    { 0, 5, 2, 0xc843052, 0x6030, 0x11, &val4Offset, &val4bit }<o:p></o:p></p>
<p class="MsoNormal">};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#define NSEC_PER_SEC (1000000000L)<o:p></o:p></p>
<p class="MsoNormal">#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#define DIFF_NS(A, B) (((B).tv_sec - (A).tv_sec) * NSEC_PER_SEC + \<o:p></o:p></p>
<p class="MsoNormal">        (B).tv_nsec - (A).tv_nsec)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#define TIMESPEC2NS(T) ((uint64_t) (T).tv_sec * NSEC_PER_SEC + (T).tv_nsec)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// EtherCAT<o:p></o:p></p>
<p class="MsoNormal">static ec_master_t *master = NULL;<o:p></o:p></p>
<p class="MsoNormal">static ec_master_state_t master_state = {};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span lang="FR">static ec_domain_t *domain1 = NULL;<o:p></o:p></span></p>
<p class="MsoNormal">static ec_domain_state_t domain1_state = {};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// process data<o:p></o:p></p>
<p class="MsoNormal">static uint8_t *domain1_pd = NULL;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#define BusCouplerPos    0, 0<o:p></o:p></p>
<p class="MsoNormal">#define DigInSlavePos   0, 1<o:p></o:p></p>
<p class="MsoNormal">#define CounterSlavePos  0, 2<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#define Beckhoff_EK1100 0x00000002, 0x044c2c52<o:p></o:p></p>
<p class="MsoNormal">#define Beckhoff_EL3204 0x00000002, 0x0c843052 // TODO Set to the EL3204<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// offsets for PDO entries<o:p></o:p></p>
<p class="MsoNormal">static int off_dig_out;<o:p></o:p></p>
<p class="MsoNormal">static int off_counter_in;<o:p></o:p></p>
<p class="MsoNormal">static int off_counter_out;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">static unsigned int counter = 0;<o:p></o:p></p>
<p class="MsoNormal">static unsigned int blink = 0;<o:p></o:p></p>
<p class="MsoNormal">static unsigned int sync_ref_counter = 0;<o:p></o:p></p>
<p class="MsoNormal">const struct timespec cycletime = {0, PERIOD_NS};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">struct timespec timespec_add(struct timespec time1, struct timespec time2)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    struct timespec result;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {<o:p></o:p></p>
<p class="MsoNormal">        result.tv_sec = time1.tv_sec + time2.tv_sec + 1;<o:p></o:p></p>
<p class="MsoNormal">        result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;<o:p></o:p></p>
<p class="MsoNormal">    } else {<o:p></o:p></p>
<p class="MsoNormal">        result.tv_sec = time1.tv_sec + time2.tv_sec;<o:p></o:p></p>
<p class="MsoNormal">        result.tv_nsec = time1.tv_nsec + time2.tv_nsec;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    return result;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void check_domain1_state(void)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    ec_domain_state_t ds;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    ecrt_domain_state(domain1, &ds);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if (ds.working_counter != domain1_state.working_counter)<o:p></o:p></p>
<p class="MsoNormal">        printf("Domain1: WC %u.\n", ds.working_counter);<o:p></o:p></p>
<p class="MsoNormal">    if (ds.wc_state != domain1_state.wc_state)<o:p></o:p></p>
<p class="MsoNormal">        printf("Domain1: State %u.\n", ds.wc_state);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    domain1_state = ds;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void check_master_state(void)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    ec_master_state_t ms;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    ecrt_master_state(master, &ms);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if (ms.slaves_responding != master_state.slaves_responding)<o:p></o:p></p>
<p class="MsoNormal">        printf("%u slave(s).\n", ms.slaves_responding);<o:p></o:p></p>
<p class="MsoNormal">    if (ms.al_states != master_state.al_states)<o:p></o:p></p>
<p class="MsoNormal">        printf("AL states: 0x%02X.\n", ms.al_states);<o:p></o:p></p>
<p class="MsoNormal">    if (ms.link_up != master_state.link_up)<o:p></o:p></p>
<p class="MsoNormal">        printf("Link is %s.\n", ms.link_up ? "up" : "down");<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    master_state = ms;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void cyclic_task()<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    struct timespec wakeupTime, time;<o:p></o:p></p>
<p class="MsoNormal">#ifdef MEASURE_TIMING<o:p></o:p></p>
<p class="MsoNormal">    struct timespec startTime, endTime, lastStartTime = {};<o:p></o:p></p>
<p class="MsoNormal">    uint32_t period_ns = 0, exec_ns = 0, latency_ns = 0,<o:p></o:p></p>
<p class="MsoNormal">             latency_min_ns = 0, latency_max_ns = 0,<o:p></o:p></p>
<p class="MsoNormal">             period_min_ns = 0, period_max_ns = 0,<o:p></o:p></p>
<p class="MsoNormal">             <span lang="FR">exec_min_ns = 0, exec_max_ns = 0;<o:p></o:p></span></p>
<p class="MsoNormal">#endif<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // get current time<o:p></o:p></p>
<p class="MsoNormal">    clock_gettime(CLOCK_TO_USE, &wakeupTime);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    while(1) {<o:p></o:p></p>
<p class="MsoNormal">        wakeupTime = timespec_add(wakeupTime, cycletime);<o:p></o:p></p>
<p class="MsoNormal">        clock_nanosleep(CLOCK_TO_USE, TIMER_ABSTIME, &wakeupTime, NULL);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        // Write application time to master<o:p></o:p></p>
<p class="MsoNormal">        //<o:p></o:p></p>
<p class="MsoNormal">        // It is a good idea to use the target time (not the measured time) as<o:p></o:p></p>
<p class="MsoNormal">        // application time, because it is more stable.<o:p></o:p></p>
<p class="MsoNormal">        //<o:p></o:p></p>
<p class="MsoNormal">        ecrt_master_application_time(master, TIMESPEC2NS(wakeupTime));<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#ifdef MEASURE_TIMING<o:p></o:p></p>
<p class="MsoNormal">        clock_gettime(CLOCK_TO_USE, &startTime);<o:p></o:p></p>
<p class="MsoNormal">        latency_ns = DIFF_NS(wakeupTime, startTime);<o:p></o:p></p>
<p class="MsoNormal">        period_ns = DIFF_NS(lastStartTime, startTime);<o:p></o:p></p>
<p class="MsoNormal">        exec_ns = DIFF_NS(lastStartTime, endTime);<o:p></o:p></p>
<p class="MsoNormal">        lastStartTime = startTime;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        if (latency_ns > latency_max_ns) {<o:p></o:p></p>
<p class="MsoNormal">            latency_max_ns = latency_ns;<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        if (latency_ns < latency_min_ns) {<o:p></o:p></p>
<p class="MsoNormal">            latency_min_ns = latency_ns;<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        if (period_ns > period_max_ns) {<o:p></o:p></p>
<p class="MsoNormal">            period_max_ns = period_ns;<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        if (period_ns < period_min_ns) {<o:p></o:p></p>
<p class="MsoNormal">            period_min_ns = period_ns;<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        if (exec_ns > exec_max_ns) {<o:p></o:p></p>
<p class="MsoNormal">            exec_max_ns = exec_ns;<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        if (exec_ns < exec_min_ns) {<o:p></o:p></p>
<p class="MsoNormal">            <span lang="FR">exec_min_ns = exec_ns;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">        </span>}<o:p></o:p></p>
<p class="MsoNormal">#endif<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        // receive process data<o:p></o:p></p>
<p class="MsoNormal">        ecrt_master_receive(master);<o:p></o:p></p>
<p class="MsoNormal">        ecrt_domain_process(domain1);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        // check process data state (optional)<o:p></o:p></p>
<p class="MsoNormal">        check_domain1_state();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        if (counter) {<o:p></o:p></p>
<p class="MsoNormal">            counter--;<o:p></o:p></p>
<p class="MsoNormal">        } else { // do this at 1 Hz<o:p></o:p></p>
<p class="MsoNormal">            counter = FREQUENCY;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">            // check for master state (optional)<o:p></o:p></p>
<p class="MsoNormal">            check_master_state();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#ifdef MEASURE_TIMING<o:p></o:p></p>
<p class="MsoNormal">            // output timing stats<o:p></o:p></p>
<p class="MsoNormal">            printf("period     %10u ... %10u\n",<o:p></o:p></p>
<p class="MsoNormal">                    period_min_ns, period_max_ns);<o:p></o:p></p>
<p class="MsoNormal">            printf("exec       %10u ... %10u\n",<o:p></o:p></p>
<p class="MsoNormal">                    exec_min_ns, exec_max_ns);<o:p></o:p></p>
<p class="MsoNormal">            printf("latency    %10u ... %10u\n",<o:p></o:p></p>
<p class="MsoNormal">                    latency_min_ns, latency_max_ns);<o:p></o:p></p>
<p class="MsoNormal">            period_max_ns = 0;<o:p></o:p></p>
<p class="MsoNormal">            period_min_ns = 0xffffffff;<o:p></o:p></p>
<p class="MsoNormal">            exec_max_ns = 0;<o:p></o:p></p>
<p class="MsoNormal">            exec_min_ns = 0xffffffff;<o:p></o:p></p>
<p class="MsoNormal">            latency_max_ns = 0;<o:p></o:p></p>
<p class="MsoNormal">            latency_min_ns = 0xffffffff;<o:p></o:p></p>
<p class="MsoNormal">#endif<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        // Read process data<o:p></o:p></p>
<p class="MsoNormal">        int16_t val1 = EC_READ_S16(domain1_pd + val1Offset);<o:p></o:p></p>
<p class="MsoNormal">        int16_t val2 = EC_READ_S16(domain1_pd + val1Offset);<o:p></o:p></p>
<p class="MsoNormal">        int16_t val3 = EC_READ_S16(domain1_pd + val1Offset);<o:p></o:p></p>
<p class="MsoNormal">        int16_t val4 = EC_READ_S16(domain1_pd + val1Offset);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        <span lang="FR">printf("Val1: %d\nVal2: %d\nVal3: %d\nVal4: %d\n\n", val1, val2, val3, val4);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="FR">        </span>if (sync_ref_counter) {<o:p></o:p></p>
<p class="MsoNormal">            sync_ref_counter--;<o:p></o:p></p>
<p class="MsoNormal">        } else {<o:p></o:p></p>
<p class="MsoNormal">            sync_ref_counter = 1; // sync every cycle<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">            clock_gettime(CLOCK_TO_USE, &time);<o:p></o:p></p>
<p class="MsoNormal">            ecrt_master_sync_reference_clock_to(master, TIMESPEC2NS(time));<o:p></o:p></p>
<p class="MsoNormal">        }<o:p></o:p></p>
<p class="MsoNormal">        ecrt_master_sync_slave_clocks(master);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">        ecrt_master_send(master);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#ifdef MEASURE_TIMING<o:p></o:p></p>
<p class="MsoNormal">        clock_gettime(CLOCK_TO_USE, &endTime);<o:p></o:p></p>
<p class="MsoNormal">#endif<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">int main(int argc, char **argv)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    ec_slave_config_t *sc;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {<o:p></o:p></p>
<p class="MsoNormal">        perror("mlockall failed");<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    master = ecrt_request_master(0);<o:p></o:p></p>
<p class="MsoNormal">    if (!master)<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    domain1 = ecrt_master_create_domain(master);<o:p></o:p></p>
<p class="MsoNormal">    if (!domain1)<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // Create configuration for bus coupler<o:p></o:p></p>
<p class="MsoNormal">    sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);<o:p></o:p></p>
<p class="MsoNormal">    if (!sc)<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if (!(sc = ecrt_master_slave_config(master,<o:p></o:p></p>
<p class="MsoNormal">                    DigInSlavePos, Beckhoff_EL3204))) {<o:p></o:p></p>
<p class="MsoNormal">        fprintf(stderr, "Failed to get slave configuration.\n");<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if ( ecrt_slave_config_pdos(sc, 5, &slave_5_syncs[0] ) )<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        printf("Failed to set sync manager data\n");<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    printf("Registering PDO entries...\n");<o:p></o:p></p>
<p class="MsoNormal">    if (ecrt_domain_reg_pdo_entry_list(domain1, &registrationList[0])) {<o:p></o:p></p>
<p class="MsoNormal">        fprintf(stderr, "Failed to set slave pdos.\n");<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // configure SYNC signals for this slave<o:p></o:p></p>
<p class="MsoNormal">    // NOTE: EL3204 uses the same assignActivate value<o:p></o:p></p>
<p class="MsoNormal">    ecrt_slave_config_dc(sc, 0x0700, PERIOD_NS, 4400000, 0, 0);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    printf("Activating master...\n");<o:p></o:p></p>
<p class="MsoNormal">    if (ecrt_master_activate(master))<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    if (!(domain1_pd = ecrt_domain_data(domain1))) {<o:p></o:p></p>
<p class="MsoNormal">        return -1;<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">    printf( "Domain Size Is %d bytes\n", ecrt_domain_size( domain1 ) );<o:p></o:p></p>
<p class="MsoNormal">    printf( "   Domain Val1 Offset Is %d\n", val1Offset );<o:p></o:p></p>
<p class="MsoNormal">    printf( "   Domain Val2 Offset Is %d\n", val2Offset );<o:p></o:p></p>
<p class="MsoNormal">    printf( "   Domain Val3 Offset Is %d\n", val3Offset );<o:p></o:p></p>
<p class="MsoNormal">    printf( "   Domain Val4 Offset Is %d\n", val4Offset );<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    /* Set priority */<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    struct sched_param param = {};<o:p></o:p></p>
<p class="MsoNormal">    param.sched_priority = sched_get_priority_max(SCHED_FIFO);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    printf("Using priority %i.", param.sched_priority);<o:p></o:p></p>
<p class="MsoNormal">    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {<o:p></o:p></p>
<p class="MsoNormal">        perror("sched_setscheduler failed");<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    printf("Starting cyclic function.\n");<o:p></o:p></p>
<p class="MsoNormal">    cyclic_task();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    return 0;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/****************************************************************************/<o:p></o:p></p>
</div>
This e-mail and the information, including any attachments it contains, are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not
 the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message.
 Thank you. Please consider the environment before printing this email.
<br><br>
<P align=center><FONT style="BACKGROUND-COLOR: #ffffff">This message has been scanned for malware by Websense.  </FONT><A href="http://www.websense.com/"><FONT style="BACKGROUND-COLOR: #ffffff" color=#000000>www.websense.com</FONT></A></P>
</body>
</html>