[etherlab-users] EtherCAT master fields access issue
Gavin Lambert
gavinl at compacsort.com
Wed Apr 27 02:16:15 CEST 2016
Anything not defined in "ecrt.h" or "ioctl.h" are opaque structures that
live in kernel space, and you cannot (or should not) play with their
internals.
If you want to get information about the master, call the functions defined
in ecrt.h. Don't try to play with it directly.
From: etherlab-users [mailto:etherlab-users-bounces at etherlab.org] On Behalf
Of Tommaso
Sent: Wednesday, 27 April 2016 02:29
To: etherlab-users at etherlab.org
Subject: [etherlab-users] EtherCAT master fields access issue
Good evening,
In order to understand properly each possible data value, I'm trying to
access to the EtherCAT master data fields using it like a structure (struct
ec_master). My code, attached at the end of this message, is a reworking of
the "user" example provided in the master documentation.
The issue that I have encountered is that when I try to include the file
"master.h" the compiler gives a missing "list.h" file to include but, when I
include its path, I found some errors of conflicting type (fd_set, dev_t,
nlink_t, etc.).
Could you give me any hints in order to solve this? Anyone has already tried
to access the EtherCAT master fields in this way before and can send the
code?
Thank you for your help.
Tommaso
#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"
/***************************************************************************
*/
#define FREQUENCY 1000
#define PRIORITY 1
#define CONFIGURE_PDOS 1
#define SDO_ACCESS 0
/***************************************************************************
*/
// EtherCAT
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 = {};
static ec_slave_config_t *sc_ana_in = NULL;
static ec_slave_config_state_t sc_ana_in_state = {};
static ec_slave_config_t *sc_ana_out = NULL;
static ec_slave_config_state_t sc_ana_out_state = {};
static ec_slave_config_t *sc_dig_in = NULL;
static ec_slave_config_state_t sc_dig_in_state = {};
static ec_slave_config_t *sc_dig_out = NULL;
static ec_slave_config_state_t sc_dig_out_state = {};
static unsigned int sig_alarms = 0;
static unsigned int user_alarms = 0;
static unsigned int counter = 0;
static unsigned int blink = 0;
// process data
static uint8_t *domain1_pd = NULL;
#define BusCouplerPos 0, 0
#define DigOutSlavePos 0, 1
#define DigInSlavePos 0, 3
#define AnaInSlavePos 0, 5
#define AnaOutSlavePos 0, 6
#define Beckhoff_EK1100 0x00000002, 0x044c2c52
#define Beckhoff_EL2004 0x00000002, 0x07D43052
#define Beckhoff_EL1014 0x00000002, 0x03f63052
#define Beckhoff_EL3062 0x00000002, 0x0bf63052
#define Beckhoff_EL4002 0x00000002, 0x0fa23052
// offsets for PDO entries
static unsigned int off_ana_in;
static unsigned int off_ana_out;
static unsigned int off_dig_in;
static unsigned int off_dig_out;
const static ec_pdo_entry_reg_t domain1_regs[] = {
{AnaInSlavePos, Beckhoff_EL3062, 0x6000, 0x11, &off_ana_in},
{AnaOutSlavePos, Beckhoff_EL4002, 0x7000, 1, &off_ana_out},
{DigInSlavePos, Beckhoff_EL1014, 0x6000, 1, &off_dig_in},
{DigOutSlavePos, Beckhoff_EL2004, 0x7000, 1, &off_dig_out},
{}
};
#if CONFIGURE_PDOS
// Analog in
-------------------------------------------------------------------------
ec_pdo_entry_info_t el3062_pdo_entries[] = {
{0x6000, 0x01, 1}, /* Underrange */
{0x6000, 0x02, 1}, /* Overrange */
{0x6000, 0x03, 2}, /* Limit 1 */
{0x6000, 0x05, 2}, /* Limit 2 */
{0x6000, 0x07, 1}, /* Error */
{0x0000, 0x00, 1}, /* Gap */
{0x0000, 0x00, 6}, /* Gap */
{0x6000, 0x0f, 1}, /* TxPDO State */
{0x6000, 0x10, 1}, /* TxPDO Toggle */
{0x6000, 0x11, 16}, /* Value */
{0x6010, 0x01, 1}, /* Underrange */
{0x6010, 0x02, 1}, /* Overrange */
{0x6010, 0x03, 2}, /* Limit 1 */
{0x6010, 0x05, 2}, /* Limit 2 */
{0x6010, 0x07, 1}, /* Error */
{0x0000, 0x00, 1}, /* Gap */
{0x0000, 0x00, 6}, /* Gap */
{0x6010, 0x0f, 1}, /* TxPDO State */
{0x6010, 0x10, 1}, /* TxPDO Toggle */
{0x6010, 0x11, 16}, /* Value */
};
ec_pdo_info_t el3062_pdos[] = {
{0x1a00, 10, el3062_pdo_entries + 0}, /* AI TxPDO-Map Standard Ch.1 */
{0x1a02, 10, el3062_pdo_entries + 10}, /* AI TxPDO-Map Standard Ch.2 */
};
ec_sync_info_t el3062_syncs[] = {
{2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
{3, EC_DIR_INPUT, 1, el3062_pdos + 0, EC_WD_DISABLE},
{0xff}
};
// Analog out
-------------------------------------------------------------------------
ec_pdo_entry_info_t el4002_pdo_entries[] = {
{0x7000, 0x01, 16}, /* Analog output */
{0x7010, 0x01, 16}, /* Analog output */
};
ec_pdo_info_t el4002_pdos[] = {
{0x1600, 1, el4002_pdo_entries + 0}, /* RxPDO-Map OutputsCh.1 */
{0x1601, 1, el4002_pdo_entries + 1}, /* RxPDO-Map OutputsCh.2 */
};
ec_sync_info_t el4002_syncs[] = {
{2, EC_DIR_OUTPUT, 2, el4002_pdos + 0, EC_WD_DISABLE},
{3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
{0xff}
};
// Digital in
-------------------------------------------------------------------------
ec_pdo_entry_info_t el1014_pdo_entries[] = {
{0x6000, 0x01, 1}, /* Input */
{0x6010, 0x01, 1}, /* Input */
{0x6020, 0x01, 1}, /* Input */
{0x6030, 0x01, 1}, /* Input */
};
ec_pdo_info_t el1014_pdos[] = {
{0x1a00, 1, el1014_pdo_entries + 0}, /* Channel 1 */
{0x1a01, 1, el1014_pdo_entries + 1}, /* Channel 2 */
{0x1a02, 1, el1014_pdo_entries + 2}, /* Channel 3 */
{0x1a03, 1, el1014_pdo_entries + 3}, /* Channel 4 */
};
ec_sync_info_t el1014_syncs[] = {
{1, EC_DIR_OUTPUT},
{0, EC_DIR_INPUT, 4, el1014_pdos + 0, EC_WD_DISABLE},
{0xff}
};
// Digital out
-------------------------------------------------------------------------
ec_pdo_entry_info_t el2004_channels[] = {
{0x7000, 0x01, 1}, /* Output */
{0x7010, 0x01, 1}, /* Output */
{0x7020, 0x01, 1}, /* Output */
{0x7030, 0x01, 1}, /* Output */
};
ec_pdo_info_t el2004_pdos[] = {
{0x1600, 1, &el2004_channels[0]},
{0x1601, 1, &el2004_channels[1]},
{0x1602, 1, &el2004_channels[2]},
{0x1603, 1, &el2004_channels[3]}
};
ec_sync_info_t el2004_syncs[] = {
{0, EC_DIR_OUTPUT, 4, el2004_pdos + 0, EC_WD_ENABLE},
{1, EC_DIR_INPUT},
{0xff}
};
#endif
/***************************************************************************
**/
#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;
}
/***************************************************************************
**/
void check_slave_config_states(void)
{
ec_slave_config_state_t s;
// Analog in
--------------------------------------------------------------
ecrt_slave_config_state(sc_ana_in, &s);
if (s.al_state != sc_ana_in_state.al_state)
printf("AnaIn: State 0x%02X.\n", s.al_state);
if (s.online != sc_ana_in_state.online)
printf("AnaIn: %s.\n", s.online ? "online" : "offline");
if (s.operational != sc_ana_in_state.operational)
printf("AnaIn: %soperational.\n", s.operational ? "" : "Not ");
sc_ana_in_state = s;
// Analog out
--------------------------------------------------------------
ecrt_slave_config_state(sc_ana_out, &s);
if (s.al_state != sc_ana_out_state.al_state)
printf("AnaOut: State 0x%02X.\n", s.al_state);
if (s.online != sc_ana_out_state.online)
printf("AnaOut: %s.\n", s.online ? "online" : "offline");
if (s.operational != sc_ana_out_state.operational)
printf("AnaOut: %soperational.\n", s.operational ? "" : "Not ");
sc_ana_out_state = s;
// Digital in
--------------------------------------------------------------
ecrt_slave_config_state(sc_dig_in, &s);
if (s.al_state != sc_dig_in_state.al_state)
printf("DigIn: State 0x%02X.\n", s.al_state);
if (s.online != sc_dig_in_state.online)
printf("DigIn: %s.\n", s.online ? "online" : "offline");
if (s.operational != sc_dig_in_state.operational)
printf("DigIn: %soperational.\n", s.operational ? "" : "Not ");
sc_dig_in_state = s;
// Digital out
--------------------------------------------------------------
ecrt_slave_config_state(sc_dig_out, &s);
if (s.al_state != sc_dig_out_state.al_state)
printf("DigOut: State 0x%02X.\n", s.al_state);
if (s.online != sc_dig_out_state.online)
printf("DigOut: %s.\n", s.online ? "online" : "offline");
if (s.operational != sc_dig_out_state.operational)
printf("DigOut: %soperational.\n", s.operational ? "" : "Not ");
sc_dig_out_state = s;
}
/***************************************************************************
**/
#if SDO_ACCESS
void read_sdo(void)
{
printf("Reading sdo request state..\n");
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
/***************************************************************************
*/
int initialize(void){
ec_slave_config_t *sc;
master = ecrt_request_master(0);
if (!master)
return -1;
domain1 = ecrt_master_create_domain(master);
if (!domain1)
return -1;
#if CONFIGURE_PDOS
// Analog in
--------------------------------------------------------------
if (!(sc_ana_in = ecrt_master_slave_config(master, AnaInSlavePos,
Beckhoff_EL3062))) {
fprintf(stderr, "Failed to get analog input slave
configuration.\n");
return -1;
}
printf("Configuring PDOs...\n");
if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3062_syncs)) {
fprintf(stderr, "Failed to configure analog input slave PDOs.\n");
return -1;
}
// Analog out
--------------------------------------------------------------
if (!(sc_ana_out = ecrt_master_slave_config(master, AnaOutSlavePos,
Beckhoff_EL4002))) {
fprintf(stderr, "Failed to get analog output slave
configuration.\n");
return -1;
}
if (ecrt_slave_config_pdos(sc_ana_out, EC_END, el4002_syncs)) {
fprintf(stderr, "Failed to configure analog output slave PDOs.\n");
return -1;
}
// Digital in
--------------------------------------------------------------
if (!(sc_dig_in = ecrt_master_slave_config(master, DigInSlavePos,
Beckhoff_EL1014))) {
fprintf(stderr, "Failed to get digital input slave
configuration.\n");
return -1;
}
if (ecrt_slave_config_pdos(sc_dig_in, EC_END, el1014_syncs)) {
fprintf(stderr, "Failed to configure digital input slave PDOs.\n");
return -1;
}
// Digital out
--------------------------------------------------------------
if (!(sc_dig_out = ecrt_master_slave_config(master, DigOutSlavePos,
Beckhoff_EL2004))) {
fprintf(stderr, "Failed to get digital output slave
configuration.\n");
return -1;
}
if (ecrt_slave_config_pdos(sc_dig_out, EC_END, el2004_syncs)) {
fprintf(stderr, "Failed to configure digital output slave PDOs.\n");
return -1;
}
#endif
#if SDO_ACCESS
fprintf(stderr, "Creating SDO requests...\n");
if (!(sdo = ecrt_slave_config_create_sdo_request(sc_ana_in, 0x6000,
0x11, 2))) {
fprintf(stderr, "Failed to create SDO request.\n");
return -1;
}
ecrt_sdo_request_timeout(sdo, 500); // ms
#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;
}
return 0;
}
/***************************************************************************
*/
void clean() {
printf("Stopping master...\n");
if (master) {
printf("Releasing master...\n");
ecrt_release_master(master);
}
printf("Unloading.\n");
}
/***************************************************************************
*/
void signal_handler(int signum) {
switch (signum) {
case SIGALRM:
sig_alarms++;
break;
}
}
/***************************************************************************
*/
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 {
counter = FREQUENCY;
// calculate new process data
blink = !blink;
// check for master state (optional)
check_master_state();
// check for islave configuration state(s) (optional)
check_slave_config_states();
#if SDO_ACCESS
// read process data SDO
read_sdo();
#endif
}
#if 1
// write process data
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09);
#endif
#if 0
// write process data
EC_WRITE_U8(domain1_pd + off_dig_out, EC_READ_U8(domain1_pd +
off_dig_in) & 0x0F);
#endif
// send process data
ecrt_domain_queue(domain1);
ecrt_master_send(master);
}
/***************************************************************************
*/
int main(void)
{
struct sigaction sa;
struct itimerval tv;
initialize();
#if PRIORITY
pid_t pid = getpid();
if (setpriority(PRIO_PROCESS, pid, -20))
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++;
}
}
clean();
return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20160427/59c64a1f/attachment-0004.htm>
More information about the Etherlab-users
mailing list