fp@1414: /***************************************************************************** fp@1414: * fp@1414: * $Id$ fp@1414: * fp@1414: * Copyright (C) 2007-2009 Florian Pose, Ingenieurgemeinschaft IgH fp@1414: * fp@1414: * This file is part of the IgH EtherCAT Master. fp@1414: * fp@1414: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1414: * modify it under the terms of the GNU General Public License version 2, as fp@1414: * published by the Free Software Foundation. fp@1414: * fp@1414: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1414: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1414: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1414: * Public License for more details. fp@1414: * fp@1414: * You should have received a copy of the GNU General Public License along fp@1414: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1414: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1414: * fp@1414: * --- fp@1414: * fp@1414: * The license mentioned above concerns the source code only. Using the fp@1414: * EtherCAT technology and brand is only permitted in compliance with the fp@1414: * industrial property and similar rights of Beckhoff Automation GmbH. fp@1414: * fp@1414: ****************************************************************************/ fp@1414: fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: #include fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: #include "ecrt.h" fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: // Application parameters fp@1414: #define FREQUENCY 100 fp@1414: #define PRIORITY 1 fp@1414: fp@1414: // Optional features fp@1414: #define CONFIGURE_PDOS 1 fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: // EtherCAT fp@1414: static ec_master_t *master = NULL; fp@1414: static ec_master_state_t master_state = {}; fp@1414: fp@1414: static ec_domain_t *domain1 = NULL; fp@1414: static ec_domain_state_t domain1_state = {}; fp@1414: fp@1414: // Timer fp@1414: static unsigned int sig_alarms = 0; fp@1414: static unsigned int user_alarms = 0; fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: // process data fp@1414: static uint8_t *domain1_pd = NULL; fp@1414: fp@1414: #define BusCouplerPos 0, 0 fp@1414: #define DigOutSlavePos 0, 1 fp@1414: #define CounterSlavePos 0, 2 fp@1414: fp@1414: #define Beckhoff_EK1100 0x00000002, 0x044c2c52 fp@1414: #define Beckhoff_EL2008 0x00000002, 0x07d83052 fp@1414: #define IDS_Counter 0x000012ad, 0x05de3052 fp@1414: fp@1414: // offsets for PDO entries fp@1414: static int off_dig_out; fp@1414: static int off_counter_in; fp@1414: static int off_counter_out; fp@1414: fp@1414: static unsigned int counter = 0; fp@1414: static unsigned int blink_counter = 0; fp@1414: static unsigned int blink = 0; fp@1414: static unsigned int sync_ref_counter = 0; fp@1414: struct timeval app_time; fp@1414: fp@1414: /*****************************************************************************/ fp@1414: fp@1414: void check_domain1_state(void) fp@1414: { fp@1414: ec_domain_state_t ds; fp@1414: fp@1414: ecrt_domain_state(domain1, &ds); fp@1414: fp@1414: if (ds.working_counter != domain1_state.working_counter) fp@1414: printf("Domain1: WC %u.\n", ds.working_counter); fp@1414: if (ds.wc_state != domain1_state.wc_state) fp@1414: printf("Domain1: State %u.\n", ds.wc_state); fp@1414: fp@1414: domain1_state = ds; fp@1414: } fp@1414: fp@1414: /*****************************************************************************/ fp@1414: fp@1414: void check_master_state(void) fp@1414: { fp@1414: ec_master_state_t ms; fp@1414: fp@1414: ecrt_master_state(master, &ms); fp@1414: fp@1414: if (ms.slaves_responding != master_state.slaves_responding) fp@1414: printf("%u slave(s).\n", ms.slaves_responding); fp@1414: if (ms.al_states != master_state.al_states) fp@1414: printf("AL states: 0x%02X.\n", ms.al_states); fp@1414: if (ms.link_up != master_state.link_up) fp@1414: printf("Link is %s.\n", ms.link_up ? "up" : "down"); fp@1414: fp@1414: master_state = ms; fp@1414: } fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: void cyclic_task() fp@1414: { fp@1414: int i; fp@1414: fp@1414: // receive process data fp@1414: ecrt_master_receive(master); fp@1414: ecrt_domain_process(domain1); fp@1414: fp@1414: // check process data state (optional) fp@1414: check_domain1_state(); fp@1414: fp@1414: if (counter) { fp@1414: counter--; fp@1414: } else { // do this at 1 Hz fp@1414: counter = FREQUENCY; fp@1414: fp@1414: // calculate new process data fp@1414: blink = !blink; fp@1414: fp@1414: // check for master state (optional) fp@1414: check_master_state(); fp@1414: fp@1414: } fp@1414: fp@1414: if (blink_counter) { fp@1414: blink_counter--; fp@1414: } else { fp@1414: blink_counter = 9; fp@1414: fp@1414: // calculate new process data fp@1414: blink = !blink; fp@1414: } fp@1414: fp@1414: // write process data fp@1414: EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x66 : 0x99); fp@1414: EC_WRITE_U8(domain1_pd + off_counter_out, blink ? 0x00 : 0x02); fp@1414: fp@1414: app_time.tv_usec += 1000000 / FREQUENCY; fp@1414: if (app_time.tv_usec >= 1000000) { fp@1414: app_time.tv_usec -= 1000000; fp@1414: app_time.tv_sec++; fp@1414: } fp@1414: fp@1414: if (sync_ref_counter) { fp@1414: sync_ref_counter--; fp@1414: } else { fp@1414: sync_ref_counter = 9; fp@1414: ecrt_master_sync_reference_clock(master, &app_time); fp@1414: } fp@1414: ecrt_master_sync_slave_clocks(master); fp@1414: fp@1414: // send process data fp@1414: ecrt_domain_queue(domain1); fp@1414: ecrt_master_send(master); fp@1414: } fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: void signal_handler(int signum) { fp@1414: switch (signum) { fp@1414: case SIGALRM: fp@1414: sig_alarms++; fp@1414: break; fp@1414: } fp@1414: } fp@1414: fp@1414: /****************************************************************************/ fp@1414: fp@1414: int main(int argc, char **argv) fp@1414: { fp@1414: ec_slave_config_t *sc; fp@1414: struct sigaction sa; fp@1414: struct itimerval tv; fp@1414: fp@1414: master = ecrt_request_master(0); fp@1414: if (!master) fp@1414: return -1; fp@1414: fp@1414: domain1 = ecrt_master_create_domain(master); fp@1414: if (!domain1) fp@1414: return -1; fp@1414: fp@1414: // Create configuration for bus coupler fp@1414: sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100); fp@1414: if (!sc) fp@1414: return -1; fp@1414: fp@1414: if (!(sc = ecrt_master_slave_config(master, fp@1414: DigOutSlavePos, Beckhoff_EL2008))) { fp@1414: fprintf(stderr, "Failed to get slave configuration.\n"); fp@1414: return -1; fp@1414: } fp@1414: fp@1414: off_dig_out = ecrt_slave_config_reg_pdo_entry(sc, fp@1414: 0x7000, 1, domain1, NULL); fp@1414: if (off_dig_out < 0) fp@1414: return -1; fp@1414: fp@1414: if (!(sc = ecrt_master_slave_config(master, fp@1414: CounterSlavePos, IDS_Counter))) { fp@1414: fprintf(stderr, "Failed to get slave configuration.\n"); fp@1414: return -1; fp@1414: } fp@1414: fp@1414: off_counter_in = ecrt_slave_config_reg_pdo_entry(sc, fp@1414: 0x6020, 0x11, domain1, NULL); fp@1414: if (off_counter_in < 0) fp@1414: return -1; fp@1414: fp@1414: off_counter_out = ecrt_slave_config_reg_pdo_entry(sc, fp@1414: 0x7020, 1, domain1, NULL); fp@1414: if (off_counter_out < 0) fp@1414: return -1; fp@1414: fp@1414: #if 1 fp@1414: // configure SYNC signals for this slave fp@1414: ecrt_slave_config_dc_assign_activate(sc, 0x0700); fp@1414: ecrt_slave_config_dc_sync_cycle_times(sc, 10000000, 0); fp@1414: ecrt_slave_config_dc_sync_shift_times(sc, 4400000, 0); fp@1414: #endif fp@1414: fp@1414: printf("Activating master...\n"); fp@1414: if (ecrt_master_activate(master)) fp@1414: return -1; fp@1414: fp@1414: if (!(domain1_pd = ecrt_domain_data(domain1))) { fp@1414: return -1; fp@1414: } fp@1414: fp@1414: #if PRIORITY fp@1414: pid_t pid = getpid(); fp@1414: if (setpriority(PRIO_PROCESS, pid, -19)) fp@1414: fprintf(stderr, "Warning: Failed to set priority: %s\n", fp@1414: strerror(errno)); fp@1414: #endif fp@1414: fp@1414: sa.sa_handler = signal_handler; fp@1414: sigemptyset(&sa.sa_mask); fp@1414: sa.sa_flags = 0; fp@1414: if (sigaction(SIGALRM, &sa, 0)) { fp@1414: fprintf(stderr, "Failed to install signal handler!\n"); fp@1414: return -1; fp@1414: } fp@1414: fp@1414: printf("Starting timer...\n"); fp@1414: tv.it_interval.tv_sec = 0; fp@1414: tv.it_interval.tv_usec = 1000000 / FREQUENCY; fp@1414: tv.it_value.tv_sec = 0; fp@1414: tv.it_value.tv_usec = 1000; fp@1414: if (setitimer(ITIMER_REAL, &tv, NULL)) { fp@1414: fprintf(stderr, "Failed to start timer: %s\n", strerror(errno)); fp@1414: return 1; fp@1414: } fp@1414: fp@1414: gettimeofday(&app_time, NULL); fp@1414: fp@1414: printf("Started.\n"); fp@1414: while (1) { fp@1414: pause(); fp@1414: fp@1414: #if 0 fp@1414: struct timeval t; fp@1414: gettimeofday(&t, NULL); fp@1414: printf("%u.%06u\n", t.tv_sec, t.tv_usec); fp@1414: #endif fp@1414: fp@1414: while (sig_alarms != user_alarms) { fp@1414: cyclic_task(); fp@1414: user_alarms++; fp@1414: } fp@1414: } fp@1414: fp@1414: return 0; fp@1414: } fp@1414: fp@1414: /****************************************************************************/