[etherlab-users] DeviceNet EL6752, "Timeout after 1000 ms while waiting for SDO 0xf800:0 download response."

Carlos Herkt ch at lessmueller.de
Wed Sep 24 15:45:24 CEST 2014


Hello,
sorry for the delay. Meanwhile we got the DeviceNet terminal running.

While tracing with Wireshark we noticed that the respsonse for downloading to 0xf800 took >2s to appear, which is more than etherlab waits for a response (default: 1s). Settting the constant EC_SDO_REQUEST_RESPONSE_TIMEOUT defined in master/sdo_request.c to 3000ms and recompiling the master module did the trick for us.

Also the complete_access download works properly. There is no need to configure it subindex by subindex.

To get the cstructs for PDO configuration, we were not able to use the XML file exported from TwinCAT. The terminal responded with "Invalid input configuration" and refused to go into OP mode.
Configuring the terminal with TwinCAT, quickly plugging the cat5 cable to the linux box running etherlab master and reading out the cstructs with the etherlab tool worked for us.

Attached you find an example (working in our setup), which initializes the terminal with one DeviceNet slave configured (MacId 1, 125kbaud).

Thanks for all your help! :)

Kind regards,
Carlos Herkt
Maximilian Pachl

Am 15.09.2014 21:36, schrieb Richard Hacker:
> Once again, for 0x8000 use the ecrt_slave_config_sdo*() set and not
> the _complete()! Yes, subindex 0 does have a special meaning and I
> don't recall ever having the need to set subindex 0.
>
> Then, try to reduce your SDO's to a bare minimum, leaving default
> values alone. There is a special startup tab in TwinCAT where you can
> see how and in which order TwinCAT configures the slave. Try to copy
> those commands -- only  those for 0x8000 and 0xf800, especially
> leaving out 0x1C12 & 0x1C13 (which the master does for you).
>
> Maybe try to start the slave without any SDO. Check the defaults and
> configure the DeviceNet Bus so that it fits the default values (128k
> baud, node 63, etc).
>
> On 09/15/2014 04:12 PM, Carlos Herkt wrote:
>> Hi,
>> the documentation seems inconsistent. f800:10 and f800:11 are shown in
>> TwinCATs CoE tab (see attachment) but not in the documentation.
>> Anyway, we tried not to set f800:0,11,12: the result is another error
>> message while writing 8000:0 :
>>
>> SDO download 0x8000 (110 bytes) aborted.
>> SDO abort message 0x08000021: "Data cannot be transferred or stored to
>> the application beaucse of local control".
>> SDO configuration failed.
>>
>> and the green MNS led is not starting to blink. (When writing 0x0b to
>> f800:0 the led starts blinking, but we are getting the timeout message)
>>
>> If we set the 8000:XY fields manually and not setting 8000:0, we're not
>> getting the "cannot be transferred..." error but later the pdo
>> assignment fails.
>>
>> It seems the subindex 0 has a "special" meaning for both of them.
>>
>> Even, when downloading values to 0x8000 with the ethercat tool, the
>> device seems to not keep the values. See an example:
>>
>> [etherlab at EtherLab ~]$ sudo ./ethercat-tool -p5 --type uint16 download
>> 0x8000 1 0x3f
>> [etherlab at EtherLab ~]$ sudo ./ethercat-tool -p5 --type uint16 upload
>> 0x8000 1
>> 0x0000 0
>>
>>
>> Kind regards
>>
>>
>> Codesnippet:
>> /**************************************************************************
>>
>> //ecrt_slave_config_sdo8(sc, 0xf800,  0, 0x0b);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 1, 0x003f);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 2, 0x0003);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 3, 0x006c);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 4, 0x000c);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 5, 0x0060);
>>      ecrt_slave_config_sdo16(sc, 0xf800, 6, 0x1a01);
>>      ecrt_slave_config_sdo32(sc, 0xf800, 7, 0x01785634);
>>      //ecrt_slave_config_sdo8(sc, 0xf800, 8, 0x0b); //octet_string
>> BECKHOFF EL6752-0000
>>      ecrt_slave_config_sdo16(sc, 0xf800, 9, 0x0000);
>>      //ecrt_slave_config_sdo8(sc, 0xf800, 10, 0x00);
>>      //ecrt_slave_config_sdo8(sc, 0xf800, 11, 0x00);
>>
>>
>>      //ecrt_slave_config_complete_sdo(sc, 0xf800, sdo_config_0xf800,
>> sizeof(sdo_config_0xf800));
>>      ecrt_slave_config_complete_sdo(sc, 0x8000, sdo_config_0x8000,
>> sizeof(sdo_config_0x8000));
>>
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 1, 0x003f);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x0D, 2);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x0E, 0x0064);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x10, 0x0064);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x11, 0x0014);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x17, 0x0014);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x1E, 0x0010);
>>      // ecrt_slave_config_sdo16(sc, 0x8000, 0x1F, 0x0001);
>>      // ecrt_slave_config_sdo8(sc, 0x8000, 0, 0x36);
>> *************************************************************************/
>>
>>
>>
>>
>> Am 15.09.2014 08:30, schrieb Richard Hacker:
>>> The first thing is to try to get the slave into OP somehow: do not set
>>> 0xf800:0, as well as subindices 10,11!! I do not see the latter in the
>>> documentation!
>>>
>>> Then:
>>> Have you tried to get the device running without using 0xF800? As far
>>> as I can read from the documentation, it may be possible - the slave
>>> address can also be set in 0x8000:there. Maybe that works (although I
>>> am not a specialist in DeviceNet)
>>>
>>>
>>>
>>> On 09/12/2014 01:23 PM, Carlos Herkt wrote:
>>>> Ok, we set the SDO's with the ecrt_slave_config_sdo8/16/32()
>>>> functions...:
>>>>
>>>> //**************************************************************************
>>>>
>>>>
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  1, 0x003c);//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  2, 0x0003);//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  3, 0x006c);//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  4, 0x000c);//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  5, 0x0060);//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  6, 0x1a01);//
>>>> //ecrt_slave_config_sdo32(sc, 0xf800,  7, 0x01785634);//
>>>> ////ecrt_slave_config_sdo8(sc, 0xf800,  8, 0x0b); //octet_string
>>>> BECKHOFF EL6752-0000//
>>>> //ecrt_slave_config_sdo16(sc, 0xf800,  9, 0x0000);//
>>>> //ecrt_slave_config_sdo8(sc, 0xf800,  10, 0x00);//
>>>> //ecrt_slave_config_sdo8(sc, 0xf800,  11, 0x00);
>>>> ///ecrt_slave_config_sdo8(sc, 0xf800,  0, 0x0b);//
>>>> /***************************************************************************/
>>>>
>>>>
>>>> /
>>>> ...but still get the timeout error.
>>>>
>>>>> Try to set SDO's explicitly using Index:SubIndex by using the
>>>>> ecrt_slave_config_sdo8/16/32() family of functions instead of
>>>>> complete
>>>>> access. In fact this the preferred method of setting SDO's.
>>>>>
>>>>> On 09/11/2014 05:25 PM, Carlos Herkt wrote:
>>>>>> Hello,
>>>>>>
>>>>>> referring to
>>>>>> http://lists.etherlab.org/pipermail/etherlab-users/2014/002613.html
>>>>>> we
>>>>>> managed to set up our devices properly.
>>>>>> We can communicate with our slaves on both devices (EL6631 &&
>>>>>> EL66731)!
>>>>>>
>>>>>> Now we're trying to initialize the Beckhoff EL6752 the same way we
>>>>>> did.
>>>>>> But another error arose:
>>>>>> /
>>>>>> dmesg: "Timeout after 1000 ms while  waiting for SDO 0xf800:0
>>>>>> download
>>>>>> response." /
>>>>>>
>>>>>> We doublechecked our configuration and everything seems alright.
>>>>>>
>>>>>> What does cause this failure?
>>>>>>
>>>>>> Is there a way to change that timeout?
>>>>>>
>>>>>> Any help is greatly appreciated.
>>>>>>
>>>>>> Best regards
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> etherlab-users mailing list
>>>>>> etherlab-users at etherlab.org
>>>>>> http://lists.etherlab.org/mailman/listinfo/etherlab-users
>>>>>>
>>>>>
>>>>> Mit freundlichem Gruß
>>>>>
>>>>> Richard Hacker
>>>>>
>>>>
>>>
>>> Mit freundlichem Gruß
>>>
>>> Richard Hacker
>>>
>>
>
> Mit freundlichem Gruß
>
> Richard Hacker
>

-------------- next part --------------
/*****************************************************************************
 *
 *  $Id$
 *
 *  Copyright (C) 2007-2009  Florian Pose, Ingenieurgemeinschaft IgH
 *
 *  This file is part of the IgH EtherCAT Master.
 *
 *  The IgH EtherCAT Master is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License version 2, as
 *  published by the Free Software Foundation.
 *
 *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 *  Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with the IgH EtherCAT Master; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  The license mentioned above concerns the source code only. Using the
 *  EtherCAT technology and brand is only permitted in compliance with the
 *  industrial property and similar rights of Beckhoff Automation GmbH.
 *
 ****************************************************************************/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

/****************************************************************************/

#include "ecrt.h"


/****************************************************************************/

// Application parameters
#define FREQUENCY 100
#define PRIORITY 1

// Optional features
#define CONFIGURE_PDOS  1
#define SDO_ACCESS      0

/****************************************************************************/

// EtherCAT
#define BusCouplerPos   0, 0
#define Beckhoff_EK1100 0x00000002, 0x044c2c52
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};

static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state = {};


// Timer
static unsigned int sig_alarms = 0;
static unsigned int user_alarms = 0;

/****************************************************************************/

/* Master 0, Slave 5, "EL6752", DeviceNet Master
 * Vendor ID:       0x00000002
 * Product code:    0x1a603052
 * Revision number: 0x00120000
 */

#define DeviceNetPos	0, 5
#define Beckhoff_EL6752 0x00000002, 0x1a603052

// DeviceNet SDOs (CoE init commands)
static unsigned char sdo_config_5_0xf800[] = {0x0b, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x6c, 0x00, 0x0c, 0x00, 0x60, 0x1a, 0x01, 0x01, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x14, 0x00};
static unsigned char sdo_config_5_0x8000[] = {0x36, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

ec_pdo_entry_info_t slave_5_pdo_entries[] = {
	{0x7000, 0x01, 64},	// Output 8 Bytes
	{0xf200, 0x01, 1},	// BitStrobe_MacId_0
	{0xf200, 0x02, 1},	// BitStrobe_MacId_1
	{0xf200, 0x03, 1},	//		...
	{0xf200, 0x04, 1},	//		...
	{0xf200, 0x05, 1},
	{0xf200, 0x06, 1},
	{0xf200, 0x07, 1},
	{0xf200, 0x08, 1},
	{0xf200, 0x09, 1},
	{0xf200, 0x0a, 1},
	{0xf200, 0x0b, 1},
	{0xf200, 0x0c, 1},
	{0xf200, 0x0d, 1},
	{0xf200, 0x0e, 1},
	{0xf200, 0x0f, 1},
	{0xf200, 0x10, 1},
	{0xf200, 0x11, 1},
	{0xf200, 0x12, 1},
	{0xf200, 0x13, 1},
	{0xf200, 0x14, 1},
	{0xf200, 0x15, 1},
	{0xf200, 0x16, 1},
	{0xf200, 0x17, 1},
	{0xf200, 0x18, 1},
	{0xf200, 0x19, 1},
	{0xf200, 0x1a, 1},
	{0xf200, 0x1b, 1},
	{0xf200, 0x1c, 1},
	{0xf200, 0x1d, 1},
	{0xf200, 0x1e, 1},
	{0xf200, 0x1f, 1},
	{0xf200, 0x20, 1},
	{0xf200, 0x21, 1},
	{0xf200, 0x22, 1},
	{0xf200, 0x23, 1},
	{0xf200, 0x24, 1},
	{0xf200, 0x25, 1},
	{0xf200, 0x26, 1},
	{0xf200, 0x27, 1},
	{0xf200, 0x28, 1},
	{0xf200, 0x29, 1},
	{0xf200, 0x2a, 1},
	{0xf200, 0x2b, 1},
	{0xf200, 0x2c, 1},
	{0xf200, 0x2d, 1},
	{0xf200, 0x2e, 1},
	{0xf200, 0x2f, 1},
	{0xf200, 0x30, 1},
	{0xf200, 0x31, 1},
	{0xf200, 0x32, 1},
	{0xf200, 0x33, 1},
	{0xf200, 0x34, 1},
	{0xf200, 0x35, 1},
	{0xf200, 0x36, 1},
	{0xf200, 0x37, 1},
	{0xf200, 0x38, 1},
	{0xf200, 0x39, 1},
	{0xf200, 0x3a, 1},
	{0xf200, 0x3b, 1},
	{0xf200, 0x3c, 1},
	{0xf200, 0x3d, 1},
	{0xf200, 0x3e, 1},
	{0xf200, 0x3f, 1},
	{0xf200, 0x40, 1},	// BitStrobe_MacId_64
	{0x6000, 0x01, 64},	// Inputs 8 Bytes
	{0xa000, 0x01, 8},	// HilscherSlave_MacState
	{0xf100, 0x01, 8},	// EL6752_Error
	{0xf100, 0x0d, 1},	// EL6752_DiagFlag
	{0xa000, 0x02, 1},	// HilscherSlave_DiagFlag
	{0x0000, 0x00, 14}, /* Gap */
};

ec_pdo_info_t slave_5_pdos[] = {
	{0x1600, 1, slave_5_pdo_entries + 0},	// HilscherSlave_OUT
	{0x1680, 64, slave_5_pdo_entries + 1},	// BitStrobes
	{0x1a00, 1, slave_5_pdo_entries + 65},	// HilscherSlave_IN
	{0x1a80, 5, slave_5_pdo_entries + 66},	// EL6725_IN
};

ec_sync_info_t slave_5_syncs[] = {
	{0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
	{1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
	{2, EC_DIR_OUTPUT, 2, slave_5_pdos + 0, EC_WD_DISABLE},
	{3, EC_DIR_INPUT, 2, slave_5_pdos + 2, EC_WD_DISABLE},
	{0xff}
};

/****************************************************************************/


// process data
static uint8_t *domain1_pd = NULL;

// offsets for PDO entries
static unsigned int off_devicenet_in0;
static unsigned int off_devicenet_out0;

const static ec_pdo_entry_reg_t domain1_regs[] = {
	{DeviceNetPos, Beckhoff_EL6752, 0x6000, 1, &off_devicenet_in0},
	{DeviceNetPos, Beckhoff_EL6752, 0x7000, 1, &off_devicenet_out0},
	{}
};

static unsigned int counter = 0;

/*****************************************************************************/

#if SDO_ACCESS
static ec_sdo_request_t *sdo;
#endif

/*****************************************************************************/

void check_domain1_state(void)
{
	ec_domain_state_t ds;

	ecrt_domain_state(domain1, &ds);

	if (ds.working_counter != domain1_state.working_counter)
		printf("Domain1: WC %u.\n", ds.working_counter);
	if (ds.wc_state != domain1_state.wc_state)
		printf("Domain1: State %u.\n", ds.wc_state);

	domain1_state = ds;
}

/*****************************************************************************/

void check_master_state(void)
{
	ec_master_state_t ms;

	ecrt_master_state(master, &ms);

	if (ms.slaves_responding != master_state.slaves_responding)
		printf("%u slave(s).\n", ms.slaves_responding);
	if (ms.al_states != master_state.al_states)
		printf("AL states: 0x%02X.\n", ms.al_states);
	if (ms.link_up != master_state.link_up)
		printf("Link is %s.\n", ms.link_up ? "up" : "down");

	master_state = ms;
}

/*****************************************************************************/

#if SDO_ACCESS
void read_sdo(void)
{
	switch (ecrt_sdo_request_state(sdo)) {
		case EC_REQUEST_UNUSED: // request was not used yet
			ecrt_sdo_request_read(sdo); // trigger first read
			break;
		case EC_REQUEST_BUSY:
			fprintf(stderr, "Still busy...\n");
			break;
		case EC_REQUEST_SUCCESS:
			fprintf(stderr, "SDO value: 0x%04X\n",
					EC_READ_U16(ecrt_sdo_request_data(sdo)));
			ecrt_sdo_request_read(sdo); // trigger next read
			break;
		case EC_REQUEST_ERROR:
			fprintf(stderr, "Failed to read SDO!\n");
			ecrt_sdo_request_read(sdo); // retry reading
			break;
	}
}
#endif

/****************************************************************************/

void cyclic_task()
{
	// receive process data
	ecrt_master_receive(master);
	ecrt_domain_process(domain1);

	// check process data state (optional)
	check_domain1_state();

	if (counter) {
		counter--;
	} else { // do this at 1 Hz
		counter = FREQUENCY;


		// check for master state (optional)
		check_master_state();

		// check for islave configuration state(s) (optional)
		//check_slave_config_states();
	}

	EC_WRITE_U8(domain1_pd + off_devicenet_out0, 0xAB);

	// send process data
	ecrt_domain_queue(domain1);
	ecrt_master_send(master);
}

/****************************************************************************/

void signal_handler(int signum) {
	switch (signum) {
		case SIGALRM:
			sig_alarms++;
			break;
	}
}

/****************************************************************************/

int main(int argc, char **argv)
{
	ec_slave_config_t *sc;
	struct sigaction sa;
	struct itimerval tv;

	master = ecrt_request_master(0);
	if (!master)
		return -1;

	domain1 = ecrt_master_create_domain(master);
	if (!domain1)
		return -1;

#if CONFIGURE_PDOS
	printf("Configuring SDOs....\n");

	if (!(sc = ecrt_master_slave_config(master, DeviceNetPos, Beckhoff_EL6752))) {
		fprintf(stderr, "Failed to get slave configuration.\n");
		return -1;
	}

	// configure sdos
	ecrt_slave_config_complete_sdo(sc, 0xf800, sdo_config_5_0xf800, sizeof(sdo_config_5_0xf800));
	ecrt_slave_config_complete_sdo(sc, 0x8000, sdo_config_5_0x8000, sizeof(sdo_config_5_0x8000));

	printf("Configuring PDOs...\n");
	if (ecrt_slave_config_pdos(sc, EC_END, slave_5_syncs)) {
		fprintf(stderr, "Failed to configure PDOs.\n");
		return -1;
	}
	
#endif

	// Create configuration for bus coupler
	sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);
	if (!sc)
		return -1;

	if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
		fprintf(stderr, "PDO entry registration failed!\n");
		return -1;
	}

	printf("Activating master...\n");
	if (ecrt_master_activate(master))
		return -1;
	if (!(domain1_pd = ecrt_domain_data(domain1))) {
		return -1;
	}

#if PRIORITY
	pid_t pid = getpid();
	if (setpriority(PRIO_PROCESS, pid, -19))
		fprintf(stderr, "Warning: Failed to set priority: %s\n",
				strerror(errno));
#endif

	sa.sa_handler = signal_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	if (sigaction(SIGALRM, &sa, 0)) {
		fprintf(stderr, "Failed to install signal handler!\n");
		return -1;
	}

	printf("Starting timer...\n");
	tv.it_interval.tv_sec = 0;
	tv.it_interval.tv_usec = 1000000 / FREQUENCY;
	tv.it_value.tv_sec = 0;
	tv.it_value.tv_usec = 1000;
	if (setitimer(ITIMER_REAL, &tv, NULL)) {
		fprintf(stderr, "Failed to start timer: %s\n", strerror(errno));
		return 1;
	}

	printf("Started.\n");
	while (1) {
		pause();

#if 0
		struct timeval t;
		gettimeofday(&t, NULL);
		printf("%u.%06u\n", t.tv_sec, t.tv_usec);
#endif

		while (sig_alarms != user_alarms) {
			cyclic_task();
			user_alarms++;
		}
	}

	return 0;
}

/****************************************************************************/


More information about the Etherlab-users mailing list