examples/user/main.c
branchstable-1.5
changeset 2555 18c226b66533
parent 2549 933a1b36b05f
child 2556 674fcdccc0f3
equal deleted inserted replaced
2554:770881d887c5 2555:18c226b66533
     1 ../../../ccat/unittest/main.c
     1 /*****************************************************************************
       
     2  *
       
     3  *  $Id: main.c,v 6a6dec6fc806 2012/09/19 17:46:58 fp $
       
     4  *
       
     5  *  Copyright (C) 2007-2009  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
       
    10  *  modify it under the terms of the GNU General Public License version 2, as
       
    11  *  published by the Free Software Foundation.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    16  *  Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License along
       
    19  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *  ---
       
    23  *
       
    24  *  The license mentioned above concerns the source code only. Using the
       
    25  *  EtherCAT technology and brand is only permitted in compliance with the
       
    26  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    27  *
       
    28  ****************************************************************************/
       
    29 
       
    30 #include <errno.h>
       
    31 #include <signal.h>
       
    32 #include <stdio.h>
       
    33 #include <string.h>
       
    34 #include <sys/resource.h>
       
    35 #include <sys/time.h>
       
    36 #include <sys/types.h>
       
    37 #include <unistd.h>
       
    38 
       
    39 /****************************************************************************/
       
    40 
       
    41 #include "ecrt.h"
       
    42 
       
    43 /****************************************************************************/
       
    44 
       
    45 // Application parameters
       
    46 #define FREQUENCY 100
       
    47 #define PRIORITY 0
       
    48 
       
    49 /****************************************************************************/
       
    50 
       
    51 // EtherCAT
       
    52 static ec_master_t *master = NULL;
       
    53 static ec_master_state_t master_state = {};
       
    54 
       
    55 static ec_domain_t *domain1 = NULL;
       
    56 static ec_domain_state_t domain1_state = {};
       
    57 
       
    58 static ec_slave_config_t *sc_ana_in = NULL;
       
    59 static ec_slave_config_state_t sc_ana_in_state = {};
       
    60 
       
    61 // Timer
       
    62 static unsigned int sig_alarms = 0;
       
    63 static unsigned int user_alarms = 0;
       
    64 
       
    65 /****************************************************************************/
       
    66 
       
    67 // process data
       
    68 static uint8_t *domain1_pd = NULL;
       
    69 
       
    70 #define BusCouplerPos  0, 3
       
    71 #define DigOutSlavePos 0, 0
       
    72 
       
    73 //#define Beckhoff_EK1100 0x00000002, 0x044c2c52
       
    74 #define Beckhoff_EK1100 0x00000002, 0x04562c52
       
    75 #define Beckhoff_EL1008 0x00000002, 0x03f03052
       
    76 #define Beckhoff_EL2004 0x00000002, 0x07d43052
       
    77 #define Beckhoff_EL2008 0x00000002, 0x07d83052
       
    78 #define Beckhoff_EL2032 0x00000002, 0x07f03052
       
    79 #define Beckhoff_EL3152 0x00000002, 0x0c503052
       
    80 #define Beckhoff_EL3102 0x00000002, 0x0c1e3052
       
    81 #define Beckhoff_EL4102 0x00000002, 0x10063052
       
    82 
       
    83 // offsets for PDO entries
       
    84 static unsigned int off_dig_in[1];
       
    85 static unsigned int off_dig_out[2];
       
    86 
       
    87 
       
    88 /*****************************************************************************/
       
    89 // Digital in ------------------------
       
    90 static ec_pdo_entry_info_t el1008_channels[] = {
       
    91     {0x6000, 1, 1},
       
    92     {0x6010, 1, 1},
       
    93     {0x6020, 1, 1},
       
    94     {0x6030, 1, 1},
       
    95     {0x6040, 1, 1},
       
    96     {0x6050, 1, 1},
       
    97     {0x6060, 1, 1},
       
    98     {0x6070, 1, 1},
       
    99 };
       
   100 
       
   101 static ec_pdo_info_t el1008_pdos[] = {
       
   102     {0x1a00, 1, &el1008_channels[0]},
       
   103     {0x1a01, 1, &el1008_channels[1]},
       
   104     {0x1a02, 1, &el1008_channels[2]},
       
   105     {0x1a03, 1, &el1008_channels[3]},
       
   106     {0x1a04, 1, &el1008_channels[4]},
       
   107     {0x1a05, 1, &el1008_channels[5]},
       
   108     {0x1a06, 1, &el1008_channels[6]},
       
   109     {0x1a07, 1, &el1008_channels[7]}
       
   110 };
       
   111 
       
   112 static ec_sync_info_t el1008_syncs[] = {
       
   113     {2, EC_DIR_OUTPUT},
       
   114     {3, EC_DIR_INPUT, 8, el1008_pdos},
       
   115     {0xff}
       
   116 };
       
   117 
       
   118 // Digital out ------------------------
       
   119 static ec_pdo_entry_info_t el2008_channels[] = {
       
   120     {0x7000, 1, 1},
       
   121     {0x7010, 1, 1},
       
   122     {0x7020, 1, 1},
       
   123     {0x7030, 1, 1},
       
   124     {0x7040, 1, 1},
       
   125     {0x7050, 1, 1},
       
   126     {0x7060, 1, 1},
       
   127     {0x7070, 1, 1},
       
   128 };
       
   129 
       
   130 static ec_pdo_info_t el2008_pdos[] = {
       
   131     {0x1600, 1, &el2008_channels[0]},
       
   132     {0x1601, 1, &el2008_channels[1]},
       
   133     {0x1602, 1, &el2008_channels[2]},
       
   134     {0x1603, 1, &el2008_channels[3]},
       
   135     {0x1604, 1, &el2008_channels[4]},
       
   136     {0x1605, 1, &el2008_channels[5]},
       
   137     {0x1606, 1, &el2008_channels[6]},
       
   138     {0x1607, 1, &el2008_channels[7]}
       
   139 };
       
   140 
       
   141 static ec_sync_info_t el2008_syncs[] = {
       
   142     {0, EC_DIR_OUTPUT, 8, el2008_pdos},
       
   143     {1, EC_DIR_INPUT},
       
   144     {0xff}
       
   145 };
       
   146 
       
   147 /*****************************************************************************/
       
   148 
       
   149 void check_domain1_state(void)
       
   150 {
       
   151     ec_domain_state_t ds;
       
   152 
       
   153     ecrt_domain_state(domain1, &ds);
       
   154 
       
   155     if (ds.working_counter != domain1_state.working_counter)
       
   156         printf("Domain1: WC %u.\n", ds.working_counter);
       
   157     if (ds.wc_state != domain1_state.wc_state)
       
   158         printf("Domain1: State %u.\n", ds.wc_state);
       
   159 
       
   160     domain1_state = ds;
       
   161 }
       
   162 
       
   163 /*****************************************************************************/
       
   164 
       
   165 void check_master_state(void)
       
   166 {
       
   167     ec_master_state_t ms;
       
   168 
       
   169     ecrt_master_state(master, &ms);
       
   170 
       
   171     if (ms.slaves_responding != master_state.slaves_responding)
       
   172         printf("%u slave(s).\n", ms.slaves_responding);
       
   173     if (ms.al_states != master_state.al_states)
       
   174         printf("AL states: 0x%02X.\n", ms.al_states);
       
   175     if (ms.link_up != master_state.link_up)
       
   176         printf("Link is %s.\n", ms.link_up ? "up" : "down");
       
   177 
       
   178     master_state = ms;
       
   179 }
       
   180 
       
   181 /*****************************************************************************/
       
   182 
       
   183 void check_slave_config_states(void)
       
   184 {
       
   185     ec_slave_config_state_t s;
       
   186 
       
   187     ecrt_slave_config_state(sc_ana_in, &s);
       
   188 
       
   189     if (s.al_state != sc_ana_in_state.al_state)
       
   190         printf("AnaIn: State 0x%02X.\n", s.al_state);
       
   191     if (s.online != sc_ana_in_state.online)
       
   192         printf("AnaIn: %s.\n", s.online ? "online" : "offline");
       
   193     if (s.operational != sc_ana_in_state.operational)
       
   194         printf("AnaIn: %soperational.\n",
       
   195                 s.operational ? "" : "Not ");
       
   196 
       
   197     sc_ana_in_state = s;
       
   198 }
       
   199 
       
   200 /****************************************************************************/
       
   201 
       
   202 void cyclic_task()
       
   203 {
       
   204     static unsigned int counter = 10;
       
   205     static uint8_t outputValue = 0;
       
   206     static int numAsyncCycles = 0;
       
   207     uint8_t inputValue = 0;
       
   208     static uint8_t error = 0;
       
   209 
       
   210     // receive process data
       
   211     ecrt_master_receive(master);
       
   212     ecrt_domain_process(domain1);
       
   213 
       
   214     // check process data state (optional)
       
   215     check_domain1_state();
       
   216     
       
   217 
       
   218 	inputValue = EC_READ_U8(domain1_pd + off_dig_in[0]);
       
   219 	
       
   220 	if(inputValue != outputValue) {
       
   221 		numAsyncCycles++;
       
   222 	} else {
       
   223 		numAsyncCycles = 0;
       
   224 	}
       
   225 	
       
   226 	if(numAsyncCycles > 2) {
       
   227 		if(error != 0xff) {
       
   228 			error++;
       
   229 		}
       
   230 	}
       
   231 	
       
   232 	
       
   233     if (counter) {
       
   234         counter--;
       
   235     } else {
       
   236         counter = 5; //update delay
       
   237         
       
   238         
       
   239 
       
   240         // calculate new process data
       
   241         outputValue++;
       
   242 
       
   243         // check for master state (optional)
       
   244         check_master_state();
       
   245 
       
   246         // check for islave configuration state(s) (optional)
       
   247         check_slave_config_states();
       
   248     }
       
   249 
       
   250     // write process data
       
   251     EC_WRITE_U8(domain1_pd + off_dig_out[1], outputValue);
       
   252     EC_WRITE_U8(domain1_pd + off_dig_out[0], error);
       
   253 
       
   254     // send process data
       
   255     ecrt_domain_queue(domain1);
       
   256     ecrt_master_send(master);
       
   257 }
       
   258 
       
   259 /****************************************************************************/
       
   260 
       
   261 void signal_handler(int signum) {
       
   262     switch (signum) {
       
   263         case SIGALRM:
       
   264             sig_alarms++;
       
   265             break;
       
   266     }
       
   267 }
       
   268 
       
   269 /****************************************************************************/
       
   270 
       
   271 int Init_EL2008(uint16_t position)
       
   272 {
       
   273     ec_slave_config_t *sc;
       
   274     if (!(sc = ecrt_master_slave_config(master, 0, position, Beckhoff_EL2008))) {
       
   275         fprintf(stderr, "Failed to get EL2008 configuration #%u.\n", position);
       
   276         return -1;
       
   277     }
       
   278     if (ecrt_slave_config_pdos(sc, EC_END, el2008_syncs)) {
       
   279         fprintf(stderr, "Failed to configure PDOs #%u.\n", position);
       
   280         return -1;
       
   281     }
       
   282     if (0 > (off_dig_out[position] = ecrt_slave_config_reg_pdo_entry(sc, 0x7000, 1, domain1, NULL))) {
       
   283 		fprintf(stderr, "Failed to configure reg PDOs #%u.\n", position);
       
   284 		return -1;
       
   285 	}
       
   286     fprintf(stderr, "EL2008 #%u configured offset: %d.\n", position, off_dig_out[position]);
       
   287     return 0;
       
   288 }
       
   289 
       
   290 int main(int argc, char **argv)
       
   291 {
       
   292     ec_slave_config_t *sc;
       
   293     struct sigaction sa;
       
   294     struct itimerval tv;
       
   295     uint16_t i;
       
   296 
       
   297     master = ecrt_request_master(0);
       
   298     if (!master)
       
   299         return -1;
       
   300 
       
   301     domain1 = ecrt_master_create_domain(master);
       
   302     if (!domain1)
       
   303         return -1;
       
   304 
       
   305     printf("Configuring PDOs...\n");
       
   306     if (!(sc_ana_in = ecrt_master_slave_config(master, 0, 2, Beckhoff_EL1008))) {
       
   307         fprintf(stderr, "Failed to get digital in configuration.\n");
       
   308         return -1;
       
   309     }
       
   310     if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el1008_syncs)) {
       
   311         fprintf(stderr, "Failed to configure PDOs.\n");
       
   312         return -1;
       
   313     }
       
   314     if (0 > (off_dig_in[0] = ecrt_slave_config_reg_pdo_entry(sc_ana_in, 0x6000, 1, domain1, NULL))) {
       
   315 		fprintf(stderr, "Failed to configure reg PDOs.\n");
       
   316 		return -1;
       
   317 	}
       
   318     printf("EL1008 configured.\n");
       
   319 
       
   320     for(i = 0; i < 2; ++i) {
       
   321         if(Init_EL2008(i)) {
       
   322             fprintf(stderr, "Failed to initialize EL2008 #%u.\n", i);
       
   323             return -1;
       
   324         }
       
   325     }
       
   326 
       
   327     // Create configuration for bus coupler
       
   328     sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);
       
   329     if (!sc)
       
   330         return -1;
       
   331     fprintf(stderr, "EK1100 configured.\n");
       
   332 
       
   333     printf("Activating master...\n");
       
   334     if (ecrt_master_activate(master))
       
   335         return -1;
       
   336 
       
   337     if (!(domain1_pd = ecrt_domain_data(domain1))) {
       
   338         return -1;
       
   339     }
       
   340 
       
   341 #if PRIORITY
       
   342     pid_t pid = getpid();
       
   343     if (setpriority(PRIO_PROCESS, pid, -19))
       
   344         fprintf(stderr, "Warning: Failed to set priority: %s\n",
       
   345                 strerror(errno));
       
   346 #endif
       
   347 
       
   348     sa.sa_handler = signal_handler;
       
   349     sigemptyset(&sa.sa_mask);
       
   350     sa.sa_flags = 0;
       
   351     if (sigaction(SIGALRM, &sa, 0)) {
       
   352         fprintf(stderr, "Failed to install signal handler!\n");
       
   353         return -1;
       
   354     }
       
   355 
       
   356     printf("Starting timer...\n");
       
   357     tv.it_interval.tv_sec = 0;
       
   358     tv.it_interval.tv_usec = 1000000 / FREQUENCY;
       
   359     tv.it_value.tv_sec = 0;
       
   360     tv.it_value.tv_usec = 1000;
       
   361     if (setitimer(ITIMER_REAL, &tv, NULL)) {
       
   362         fprintf(stderr, "Failed to start timer: %s\n", strerror(errno));
       
   363         return 1;
       
   364     }
       
   365 
       
   366     printf("Started.\n");
       
   367     while (1) {
       
   368         pause();
       
   369 
       
   370 #if 0
       
   371         struct timeval t;
       
   372         gettimeofday(&t, NULL);
       
   373         printf("%u.%06u\n", t.tv_sec, t.tv_usec);
       
   374 #endif
       
   375 
       
   376         while (sig_alarms != user_alarms) {
       
   377             cyclic_task();
       
   378             user_alarms++;
       
   379         }
       
   380     }
       
   381 
       
   382     return 0;
       
   383 }
       
   384 
       
   385 /****************************************************************************/