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; }
_______________________________________________ etherlab-users mailing list etherlab-users@etherlab.org http://lists.etherlab.org/mailman/listinfo/etherlab-users