<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=utf-8"><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:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman",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;}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:12.0pt;
font-family:"Times New Roman",serif;}
span.EmailStyle18
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;
mso-fareast-language:EN-US;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
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-NZ link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri",sans-serif;mso-fareast-language:EN-US'>You’re halfway there. You also need to update the </span>domain1_regs<span style='font-size:11.0pt;font-family:"Calibri",sans-serif;mso-fareast-language:EN-US'> to reflect the layout of your network (type and position of all slave devices) and to define variables to receive the offsets into domain memory to use for transferring the corresponding PDOs.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri",sans-serif;mso-fareast-language:EN-US'><o:p> </o:p></span></p><div style='border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=MsoNormal><b><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'>From:</span></b><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'> Justin Hunt<br><b>Sent:</b> Tuesday, 4 April 2017 13:50<br><b>To:</b> etherlab-users@etherlab.org<br><b>Subject:</b> [etherlab-users] Beginner: Modifying the example code "user"<o:p></o:p></span></p></div></div><p class=MsoNormal><o:p> </o:p></p><div><p class=MsoNormal>Hello all,<o:p></o:p></p><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>I have an force sensor with ethercat communication. I got EtherCAT Master installed on my system (thanks to this form's help) and have been using the terminal commands included in the PDF manual to collect data, which has been working great.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-bottom:12.0pt'>I would now like to try to implement the equivalent commands in C++ so that I can stream the data and sample at a higher rate. However I am struggling to do so. I have tried to modify the example code "user" with the pdo entry info I get from the "ethercat cstruct" Konsole command, which outputs:<br><br>ec_pdo_entry_info_t slave_0_pdo_entries[] = {<br> {0x7010, 0x01, 32}, /* Control 1 */<br> {0x7010, 0x02, 32}, /* Control 2 */<br> {0x6000, 0x01, 32}, /* Fx/Gage0 */<br> {0x6000, 0x02, 32}, /* Fy/Gage1 */<br> {0x6000, 0x03, 32}, /* Fz/Gage2 */<br> {0x6000, 0x04, 32}, /* Tx/Gage3 */<br> {0x6000, 0x05, 32}, /* Ty/Gage3 */<br> {0x6000, 0x06, 32}, /* Tz/Gage3 */<br> {0x6010, 0x00, 32}, /* SubIndex 000 */<br> {0x6020, 0x00, 32}, /* SubIndex 000 */<br>};<br><br>ec_pdo_info_t slave_0_pdos[] = {<br> {0x1601, 2, slave_0_pdo_entries + 0}, /* DO RxPDO-Map */<br> {0x1a00, 8, slave_0_pdo_entries + 2}, /* DI TxPDO-Map */<br>};<br><br>ec_sync_info_t slave_0_syncs[] = {<br> {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},<br> {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},<br> {2, EC_DIR_OUTPUT, 1, slave_0_pdos + 0, EC_WD_ENABLE},<br> {3, EC_DIR_INPUT, 1, slave_0_pdos + 1, EC_WD_DISABLE},<br> {0xff}<br>};<br><br><o:p></o:p></p></div><div><p class=MsoNormal style='margin-bottom:12.0pt'>Since I am working with an analog force sensor, I replaced the analog input of the example code "user" with the above info and compiled the code. It compiles fine but when I try to run it I get the following error:<br><br>Configuring PDOs...<br>Failed to register PDO entry: No such file or directory<br>PDO entry registration failed!<o:p></o:p></p></div><div><p class=MsoNormal style='margin-bottom:12.0pt'>Any ideas why it can't register the PDO entry? I included my complete code below in case having a look helps. Thank you for your time all.<br><br><br>/*****************************************************************************<br> *<br> * $Id: main.c,v 6a6dec6fc806 2012/09/19 17:46:58 fp $<br> *<br> * Copyright (C) 2007-2009 Florian Pose, Ingenieurgemeinschaft IgH<br> *<br> * This file is part of the IgH EtherCAT Master.<br> *<br> * The IgH EtherCAT Master is free software; you can redistribute it and/or<br> * modify it under the terms of the GNU General Public License version 2, as<br> * published by the Free Software Foundation.<br> *<br> * The IgH EtherCAT Master is distributed in the hope that it will be useful,<br> * but WITHOUT ANY WARRANTY; without even the implied warranty of<br> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General<br> * Public License for more details.<br> *<br> * You should have received a copy of the GNU General Public License along<br> * with the IgH EtherCAT Master; if not, write to the Free Software<br> * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br> *<br> * ---<br> *<br> * The license mentioned above concerns the source code only. Using the<br> * EtherCAT technology and brand is only permitted in compliance with the<br> * industrial property and similar rights of Beckhoff Automation GmbH.<br> *<br> ****************************************************************************/<br><br>#include <errno.h><br>#include <signal.h><br>#include <stdio.h><br>#include <string.h><br>#include <sys/resource.h><br>#include <sys/time.h><br>#include <sys/types.h><br>#include <unistd.h><br><br>/****************************************************************************/<br><br>#include "ecrt.h"<br><br>/****************************************************************************/<br><br>// Application parameters<br>#define FREQUENCY 100<br>#define PRIORITY 1<br><br>// Optional features<br>#define CONFIGURE_PDOS 1<br>#define SDO_ACCESS 0<br><br>/****************************************************************************/<br><br>// EtherCAT<br>static ec_master_t *master = NULL;<br>static ec_master_state_t master_state = {};<br><br>static ec_domain_t *domain1 = NULL;<br>static ec_domain_state_t domain1_state = {};<br><br>static ec_slave_config_t *sc_ana_in = NULL;<br>static ec_slave_config_state_t sc_ana_in_state = {};<br><br>// Timer<br>static unsigned int sig_alarms = 0;<br>static unsigned int user_alarms = 0;<br><br>/****************************************************************************/<br><br>// process data<br>static uint8_t *domain1_pd = NULL;<br><br>#define BusCouplerPos 0, 0 //#define assigns 0, 0 to the name BusCouplerPos<br>#define DigOutSlavePos 0, 2<br>#define AnaInSlavePos 0, 3<br>#define AnaOutSlavePos 0, 4<br><br>#define Beckhoff_EK1100 0x00000002, 0x044c2c52<br>//#define Beckhoff_EL2004 0x00000002, 0x07d43052<br>#define Beckhoff_EL2032 0x00000002, 0x07f03052<br>#define Beckhoff_EL3152 0x00000002, 0x0c503052<br>#define Beckhoff_EL3102 0x00000002, 0x0c1e3052<br>#define Beckhoff_EL4102 0x00000002, 0x10063052<br>//test<br>// offsets for PDO entries<br>static unsigned int off_ana_in_status;<br>static unsigned int off_ana_in_value;<br>static unsigned int off_ana_out;<br>static unsigned int off_dig_out;<br><br>const static ec_pdo_entry_reg_t domain1_regs[] = {<br> {AnaInSlavePos, Beckhoff_EL3102, 0x6000, 1, &off_ana_in_status},<br> {AnaInSlavePos, Beckhoff_EL3102, 0x6000, 2, &off_ana_in_value},<br> {AnaOutSlavePos, Beckhoff_EL4102, 0x6000, 1, &off_ana_out},<br> {DigOutSlavePos, Beckhoff_EL2032, 0x6000, 1, &off_dig_out},<br> {}<br>};<br><br>static unsigned int counter = 0;<br>static unsigned int blink = 0;<br><br>/*****************************************************************************/<br><br>#if CONFIGURE_PDOS<br><br>// Analog in --------------------------<br><br>// static ec_pdo_entry_info_t el3102_pdo_entries[] = {<br>// {0x3101, 1, 8}, // channel 1 status<br>// {0x3101, 2, 16}, // channel 1 value<br>// {0x3102, 1, 8}, // channel 2 status<br>// {0x3102, 2, 16}, // channel 2 value<br>// {0x6401, 1, 16}, // channel 1 value (alt.)<br>// {0x6401, 2, 16} // channel 2 value (alt.)<br>// };<br>// <br>// static ec_pdo_info_t el3102_pdos[] = {<br>// {0x1A00, 2, el3102_pdo_entries},<br>// {0x1A01, 2, el3102_pdo_entries + 2}<br>// };<br>// <br>// static ec_sync_info_t el3102_syncs[] = {<br>// {2, EC_DIR_OUTPUT},<br>// {3, EC_DIR_INPUT, 2, el3102_pdos},<br>// {0xff}<br>// };<br><br>static ec_pdo_entry_info_t el3102_pdo_entries[] = {<br> {0x7010, 1, 32}, /* Control 1 */<br> {0x7010, 2, 32}, /* Control 2 */<br> {0x6000, 1, 32}, /* Fx/Gage0 */<br> {0x6000, 2, 32}, /* Fy/Gage1 */<br> {0x6000, 3, 32}, /* Fz/Gage2 */<br> {0x6000, 4, 32}, /* Tx/Gage3 */<br> {0x6000, 5, 32}, /* Ty/Gage3 */<br> {0x6000, 6, 32}, /* Tz/Gage3 */<br> {0x6010, 0, 32}, /* SubIndex 000 */<br> {0x6020, 0, 32}, /* SubIndex 000 */<br>};<br><br>static ec_pdo_info_t el3102_pdos[] = {<br> {0x1601, 2, el3102_pdo_entries + 0}, /* DO RxPDO-Map */<br> {0x1a00, 8, el3102_pdo_entries + 2}, /* DI TxPDO-Map */<br>};<br>ec_sync_info_t el3102_syncs[] = {<br> {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},<br> {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},<br> {2, EC_DIR_OUTPUT, 1, el3102_pdos + 0, EC_WD_ENABLE},<br> {3, EC_DIR_INPUT, 1, el3102_pdos + 1, EC_WD_DISABLE},<br> {0xff}<br>};<br><br><br><br><br>/*<br>// Analog out -------------------------<br><br>static ec_pdo_entry_info_t el4102_pdo_entries[] = {<br> {0x3001, 1, 16}, // channel 1 value<br> {0x3002, 1, 16}, // channel 2 value<br>};<br><br>static ec_pdo_info_t el4102_pdos[] = {<br> {0x1600, 1, el4102_pdo_entries},<br> {0x1601, 1, el4102_pdo_entries + 1}<br>};<br><br>static ec_sync_info_t el4102_syncs[] = {<br> {2, EC_DIR_OUTPUT, 2, el4102_pdos},<br> {3, EC_DIR_INPUT},<br> {0xff}<br>};<br><br>// Digital out ------------------------<br><br>static ec_pdo_entry_info_t el2004_channels[] = {<br> {0x3001, 1, 1}, // Value 1<br> {0x3001, 2, 1}, // Value 2<br> {0x3001, 3, 1}, // Value 3<br> {0x3001, 4, 1} // Value 4<br>};<br><br>static ec_pdo_info_t el2004_pdos[] = {<br> {0x1600, 1, &el2004_channels[0]},<br> {0x1601, 1, &el2004_channels[1]},<br> {0x1602, 1, &el2004_channels[2]},<br> {0x1603, 1, &el2004_channels[3]}<br>};<br><br>static ec_sync_info_t el2004_syncs[] = {<br> {0, EC_DIR_OUTPUT, 4, el2004_pdos},<br> {1, EC_DIR_INPUT},<br> {0xff}<br>};*/<br>#endif<br><br>/*****************************************************************************/<br><br>#if SDO_ACCESS<br>static ec_sdo_request_t *sdo;<br>#endif<br><br>/*****************************************************************************/<br><br>void check_domain1_state(void)<br>{<br> ec_domain_state_t ds;<br><br> ecrt_domain_state(domain1, &ds);<br><br> if (ds.working_counter != domain1_state.working_counter)<br> printf("Domain1: WC %u.\n", ds.working_counter);<br> if (ds.wc_state != domain1_state.wc_state)<br> printf("Domain1: State %u.\n", ds.wc_state);<br><br> domain1_state = ds;<br>}<br><br>/*****************************************************************************/<br><br>void check_master_state(void)<br>{<br> ec_master_state_t ms;<br> //printf("test");<br> ecrt_master_state(master, &ms);<br><br> if (ms.slaves_responding != master_state.slaves_responding)<br> printf("%u slave(s).\n", ms.slaves_responding);<br> if (ms.al_states != master_state.al_states)<br> printf("AL states: 0x%02X.\n", ms.al_states);<br> if (ms.link_up != master_state.link_up)<br> printf("test");<br> printf("Link is %s.\n", ms.link_up ? "up" : "down");<br> master_state = ms;<br> <br>}<br><br>/*****************************************************************************/<br>//printf("enter");<br>void check_slave_config_states(void)<br><br>{<br> <br> ec_slave_config_state_t s;<br><br> ecrt_slave_config_state(sc_ana_in, &s);<br>printf("test");<br> if (s.al_state != sc_ana_in_state.al_state)<br> printf("AnaIn: State 0x%02X.\n", s.al_state);<br> if (s.online != sc_ana_in_state.online)<br> printf("AnaIn: %s.\n", s.online ? "online" : "offline");<br> if (s.operational != sc_ana_in_state.operational)<br> printf("AnaIn: %soperational.\n",<br> s.operational ? "" : "Not ");<br><br> sc_ana_in_state = s;<br>}<br><br>/*****************************************************************************/<br><br>#if SDO_ACCESS<br>void read_sdo(void)<br>{<br> switch (ecrt_sdo_request_state(sdo)) {<br> case EC_REQUEST_UNUSED: // request was not used yet<br> ecrt_sdo_request_read(sdo); // trigger first read<br> break;<br> case EC_REQUEST_BUSY:<br> fprintf(stderr, "Still busy...\n");<br> break;<br> case EC_REQUEST_SUCCESS:<br> fprintf(stderr, "SDO value: 0x%04X\n",<br> EC_READ_U32(ecrt_sdo_request_data(sdo)));<br> ecrt_sdo_request_read(sdo); // trigger next read<br> break;<br> case EC_REQUEST_ERROR:<br> fprintf(stderr, "Failed to read SDO!\n");<br> ecrt_sdo_request_read(sdo); // retry reading<br> break;<br> }<br>}<br>#endif<br><br>/****************************************************************************/<br><br>void cyclic_task()<br>{<br> // receive process data<br> ecrt_master_receive(master);<br> ecrt_domain_process(domain1);<br><br> // check process data state (optional)<br> check_domain1_state();<br><br> if (counter) {<br> counter--;<br> } else { // do this at 1 Hz<br> counter = FREQUENCY;<br><br> // calculate new process data<br> blink = !blink;<br> //printf("test");<br> // check for master state (optional)<br> //check_master_state();<br>printf("test");<br> // check for islave configuration state(s) (optional)<br> check_slave_config_states();<br><br>#if SDO_ACCESS<br> // read process data SDO<br> read_sdo();<br>#endif<br><br> }<br><br>#if 0<br> // read process data<br> printf("AnaIn: state %u value %u\n",<br> EC_READ_U8(domain1_pd + off_ana_in_status),<br> EC_READ_U32(domain1_pd + off_ana_in_value));<br>#endif<br><br>#if 1<br> // write process data<br> EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09);<br>#endif<br><br> // send process data<br> ecrt_domain_queue(domain1);<br> ecrt_master_send(master);<br>}<br><br>/****************************************************************************/<br><br>void signal_handler(int signum) {<br> switch (signum) {<br> case SIGALRM:<br> sig_alarms++;<br> break;<br> }<br>}<br><br>/****************************************************************************/<br><br>int main(int argc, char **argv)<br>{<br> ec_slave_config_t *sc;<br> struct sigaction sa;<br> struct itimerval tv;<br><br> master = ecrt_request_master(0);<br> if (!master)<br> return -1;<br><br> domain1 = ecrt_master_create_domain(master);<br> if (!domain1)<br> return -1;<br><br> if (!(sc_ana_in = ecrt_master_slave_config(<br> master, AnaInSlavePos, Beckhoff_EL3102))) {<br> fprintf(stderr, "Failed to get slave configuration.\n");<br> return -1;<br> }<br><br>#if SDO_ACCESS<br> fprintf(stderr, "Creating SDO requests...\n");<br> if (!(sdo = ecrt_slave_config_create_sdo_request(sc_ana_in, 0x3102, 2, 2))) {<br> fprintf(stderr, "Failed to create SDO request.\n");<br> return -1;<br> }<br> ecrt_sdo_request_timeout(sdo, 500); // ms<br>#endif<br><br>#if CONFIGURE_PDOS<br> printf("Configuring PDOs...\n");<br> if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3102_syncs)) {<br> fprintf(stderr, "Failed to configure PDOs.\n");<br> return -1;<br> }<br><br>// if (!(sc = ecrt_master_slave_config(<br>// master, AnaOutSlavePos, Beckhoff_EL4102))) {<br>// fprintf(stderr, "Failed to get slave configuration.\n");<br>// return -1;<br>// }<br>// <br>// if (ecrt_slave_config_pdos(sc, EC_END, el4102_syncs)) {<br>// fprintf(stderr, "Failed to configure PDOs.\n");<br>// return -1;<br>// }<br>// <br>// if (!(sc = ecrt_master_slave_config(<br>// master, DigOutSlavePos, Beckhoff_EL2032))) {<br>// fprintf(stderr, "Failed to get slave configuration.\n");<br>// return -1;<br>// }<br><br>// if (ecrt_slave_config_pdos(sc, EC_END, el2004_syncs)) {<br>// fprintf(stderr, "Failed to configure PDOs.\n");<br>// return -1;<br>// }<br>#endif<br><br> // Create configuration for bus coupler<br> sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);<br> if (!sc)<br> return -1;<br><br> if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {<br> fprintf(stderr, "PDO entry registration failed!\n");<br> return -1;<br> }<br><br> printf("Activating master...\n");<br> if (ecrt_master_activate(master))<br> return -1;<br><br> if (!(domain1_pd = ecrt_domain_data(domain1))) {<br> return -1;<br> }<br><br>#if PRIORITY<br> pid_t pid = getpid();<br> if (setpriority(PRIO_PROCESS, pid, -19))<br> fprintf(stderr, "Warning: Failed to set priority: %s\n",<br> strerror(errno));<br>#endif<br><br> sa.sa_handler = signal_handler;<br> sigemptyset(&sa.sa_mask);<br> sa.sa_flags = 0;<br> if (sigaction(SIGALRM, &sa, 0)) {<br> fprintf(stderr, "Failed to install signal handler!\n");<br> return -1;<br> }<br><br> printf("Starting timer...\n");<br> tv.it_interval.tv_sec = 0;<br> tv.it_interval.tv_usec = 1000000 / FREQUENCY;<br> tv.it_value.tv_sec = 0;<br> tv.it_value.tv_usec = 1000;<br> if (setitimer(ITIMER_REAL, &tv, NULL)) {<br> fprintf(stderr, "Failed to start timer: %s\n", strerror(errno));<br> return 1;<br> }<br><br> printf("Started.\n");<br> while (1) {<br> //printf("test");<br> pause();<br><br>#if 0<br> struct timeval t;<br> gettimeofday(&t, NULL);<br> printf("%u.%06u\n", t.tv_sec, t.tv_usec);<br>#endif<br> <br> while (sig_alarms != user_alarms) {<br> cyclic_task();<br> user_alarms++;<br> }<br> }<br><br> return 0;<br>}<br><br>/****************************************************************************/<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div></div></div></div></body></html>