win32/simple_test/simple_test.c
Go to the documentation of this file.
1 
12 #include <stdio.h>
13 #include <string.h>
14 //#include <Mmsystem.h>
15 
16 #include "osal.h"
17 #include "ethercat.h"
18 
19 #define EC_TIMEOUTMON 500
20 
21 char IOmap[4096];
24 boolean needlf;
25 volatile int wkc;
26 volatile int rtcnt;
27 boolean inOP;
29 
30 /* most basic RT thread for process data, just does IO transfer */
31 void CALLBACK RTthread(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
32 {
33  IOmap[0]++;
34 
37  rtcnt++;
38  /* do RT control stuff here */
39 }
40 
42 {
43  int retval;
44  uint16 u16val;
45 
46  // map velocity
47  uint16 map_1c12[4] = {0x0003, 0x1601, 0x1602, 0x1604};
48  uint16 map_1c13[3] = {0x0002, 0x1a01, 0x1a03};
49 
50  retval = 0;
51 
52  // Set PDO mapping using Complete Access
53  // Strange, writing CA works, reading CA doesn't
54  // This is a protocol error of the slave.
55  retval += ec_SDOwrite(slave, 0x1c12, 0x00, TRUE, sizeof(map_1c12), &map_1c12, EC_TIMEOUTSAFE);
56  retval += ec_SDOwrite(slave, 0x1c13, 0x00, TRUE, sizeof(map_1c13), &map_1c13, EC_TIMEOUTSAFE);
57 
58  // bug in EL7031 old firmware, CompleteAccess for reading is not supported even if the slave says it is.
60 
61  // set some motor parameters, just as example
62  u16val = 1200; // max motor current in mA
63 // retval += ec_SDOwrite(slave, 0x8010, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);
64  u16val = 150; // motor coil resistance in 0.01ohm
65 // retval += ec_SDOwrite(slave, 0x8010, 0x04, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);
66 
67  // set other nescessary parameters as needed
68  // .....
69 
70  while(EcatError) printf("%s", ec_elist2string());
71 
72  printf("EL7031 slave %d set, retval = %d\n", slave, retval);
73  return 1;
74 }
75 
77 {
78  int retval;
79  uint8 u8val;
80  uint16 u16val;
81 
82  retval = 0;
83 
84  u8val = 0;
85  retval += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
86  u16val = 0x1603;
87  retval += ec_SDOwrite(slave, 0x1c12, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM);
88  u8val = 1;
89  retval += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
90 
91  u8val = 0;
92  retval += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
93  u16val = 0x1a03;
94  retval += ec_SDOwrite(slave, 0x1c13, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM);
95  u8val = 1;
96  retval += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
97 
98  u8val = 8;
99  retval += ec_SDOwrite(slave, 0x6060, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
100 
101  // set some motor parameters, just as example
102  u16val = 1200; // max motor current in mA
103 // retval += ec_SDOwrite(slave, 0x8010, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);
104  u16val = 150; // motor coil resistance in 0.01ohm
105 // retval += ec_SDOwrite(slave, 0x8010, 0x04, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);
106 
107  // set other nescessary parameters as needed
108  // .....
109 
110  while(EcatError) printf("%s", ec_elist2string());
111 
112  printf("AEP slave %d set, retval = %d\n", slave, retval);
113  return 1;
114 }
115 
116 void simpletest(char *ifname)
117 {
118  int i, j, oloop, iloop, wkc_count, chk, slc;
119  UINT mmResult;
120 
121  needlf = FALSE;
122  inOP = FALSE;
123 
124  printf("Starting simple test\n");
125 
126  /* initialise SOEM, bind socket to ifname */
127  if (ec_init(ifname))
128  {
129  printf("ec_init on %s succeeded.\n",ifname);
130  /* find and auto-config slaves */
131 
132 
133  if ( ec_config_init(FALSE) > 0 )
134  {
135  printf("%d slaves found and configured.\n",ec_slavecount);
136 
137  if((ec_slavecount > 1))
138  {
139  for(slc = 1; slc <= ec_slavecount; slc++)
140  {
141  // beckhoff EL7031, using ec_slave[].name is not very reliable
142  if((ec_slave[slc].eep_man == 0x00000002) && (ec_slave[slc].eep_id == 0x1b773052))
143  {
144  printf("Found %s at position %d\n", ec_slave[slc].name, slc);
145  // link slave specific setup to preop->safeop hook
147  }
148  // Copley Controls EAP, using ec_slave[].name is not very reliable
149  if((ec_slave[slc].eep_man == 0x000000ab) && (ec_slave[slc].eep_id == 0x00000380))
150  {
151  printf("Found %s at position %d\n", ec_slave[slc].name, slc);
152  // link slave specific setup to preop->safeop hook
153  ec_slave[slc].PO2SOconfig = &AEPsetup;
154  }
155  }
156  }
157 
158 
160 
161  ec_configdc();
162 
163  printf("Slaves mapped, state to SAFE_OP.\n");
164  /* wait for all slaves to reach SAFE_OP state */
166 
167  oloop = ec_slave[0].Obytes;
168  if ((oloop == 0) && (ec_slave[0].Obits > 0)) oloop = 1;
169  if (oloop > 8) oloop = 8;
170  iloop = ec_slave[0].Ibytes;
171  if ((iloop == 0) && (ec_slave[0].Ibits > 0)) iloop = 1;
172  if (iloop > 8) iloop = 8;
173 
174  printf("segments : %d : %d %d %d %d\n",ec_group[0].nsegments ,ec_group[0].IOsegment[0],ec_group[0].IOsegment[1],ec_group[0].IOsegment[2],ec_group[0].IOsegment[3]);
175 
176  printf("Request operational state for all slaves\n");
177  expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
178  printf("Calculated workcounter %d\n", expectedWKC);
180  /* send one valid process data to make outputs in slaves happy*/
183 
184  /* start RT thread as periodic MM timer */
185  mmResult = timeSetEvent(1, 0, RTthread, 0, TIME_PERIODIC);
186 
187  /* request OP state for all slaves */
188  ec_writestate(0);
189  chk = 200;
190  /* wait for all slaves to reach OP state */
191  do
192  {
194  }
195  while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));
196  if (ec_slave[0].state == EC_STATE_OPERATIONAL )
197  {
198  printf("Operational state reached for all slaves.\n");
199  wkc_count = 0;
200  inOP = TRUE;
201 
202 
203  /* cyclic loop, reads data from RT thread */
204  for(i = 1; i <= 500; i++)
205  {
206  if(wkc >= expectedWKC)
207  {
208  printf("Processdata cycle %4d, WKC %d , O:", rtcnt, wkc);
209 
210  for(j = 0 ; j < oloop; j++)
211  {
212  printf(" %2.2x", *(ec_slave[0].outputs + j));
213  }
214 
215  printf(" I:");
216  for(j = 0 ; j < iloop; j++)
217  {
218  printf(" %2.2x", *(ec_slave[0].inputs + j));
219  }
220  printf(" T:%lld\r",ec_DCtime);
221  needlf = TRUE;
222  }
223  osal_usleep(50000);
224 
225  }
226  inOP = FALSE;
227  }
228  else
229  {
230  printf("Not all slaves reached operational state.\n");
231  ec_readstate();
232  for(i = 1; i<=ec_slavecount ; i++)
233  {
234  if(ec_slave[i].state != EC_STATE_OPERATIONAL)
235  {
236  printf("Slave %d State=0x%2.2x StatusCode=0x%4.4x : %s\n",
237  i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
238  }
239  }
240  }
241 
242  /* stop RT thread */
243  timeKillEvent(mmResult);
244 
245  printf("\nRequest init state for all slaves\n");
247  /* request INIT state for all slaves */
248  ec_writestate(0);
249  }
250  else
251  {
252  printf("No slaves found!\n");
253  }
254  printf("End simple test, close socket\n");
255  /* stop SOEM, close socket */
256  ec_close();
257  }
258  else
259  {
260  printf("No socket connection on %s\nExcecute as root\n",ifname);
261  }
262 }
263 
264 //DWORD WINAPI ecatcheck( LPVOID lpParam )
266 {
267  int slave;
268 
269  while(1)
270  {
271  if( inOP && ((wkc < expectedWKC) || ec_group[currentgroup].docheckstate))
272  {
273  if (needlf)
274  {
275  needlf = FALSE;
276  printf("\n");
277  }
278  /* one ore more slaves are not responding */
280  ec_readstate();
281  for (slave = 1; slave <= ec_slavecount; slave++)
282  {
283  if ((ec_slave[slave].group == currentgroup) && (ec_slave[slave].state != EC_STATE_OPERATIONAL))
284  {
286  if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))
287  {
288  printf("ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n", slave);
290  ec_writestate(slave);
291  }
292  else if(ec_slave[slave].state == EC_STATE_SAFE_OP)
293  {
294  printf("WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n", slave);
296  ec_writestate(slave);
297  }
298  else if(ec_slave[slave].state > EC_STATE_NONE)
299  {
300  if (ec_reconfig_slave(slave, EC_TIMEOUTMON))
301  {
303  printf("MESSAGE : slave %d reconfigured\n",slave);
304  }
305  }
306  else if(!ec_slave[slave].islost)
307  {
308  /* re-check state */
310  if (ec_slave[slave].state == EC_STATE_NONE)
311  {
313  printf("ERROR : slave %d lost\n",slave);
314  }
315  }
316  }
317  if (ec_slave[slave].islost)
318  {
319  if(ec_slave[slave].state == EC_STATE_NONE)
320  {
321  if (ec_recover_slave(slave, EC_TIMEOUTMON))
322  {
324  printf("MESSAGE : slave %d recovered\n",slave);
325  }
326  }
327  else
328  {
330  printf("MESSAGE : slave %d found\n",slave);
331  }
332  }
333  }
334  if(!ec_group[currentgroup].docheckstate)
335  printf("OK : all slaves resumed OPERATIONAL.\n");
336  }
337  osal_usleep(10000);
338  }
339 
340  return 0;
341 }
342 
343 char ifbuf[1024];
344 
345 int main(int argc, char *argv[])
346 {
347  ec_adaptert * adapter = NULL;
348  printf("SOEM (Simple Open EtherCAT Master)\nSimple test\n");
349 
350  if (argc > 1)
351  {
352  /* create thread to handle slave error handling in OP */
353  osal_thread_create(&thread1, 128000, &ecatcheck, (void*) &ctime);
354  strcpy(ifbuf, argv[1]);
355  /* start cyclic part */
356  simpletest(ifbuf);
357  }
358  else
359  {
360  printf("Usage: simple_test ifname1\n");
361  /* Print the list */
362  printf ("Available adapters\n");
363  adapter = ec_find_adapters ();
364  while (adapter != NULL)
365  {
366  printf ("Description : %s, Device to use for wpcap: %s\n", adapter->desc,adapter->name);
367  adapter = adapter->next;
368  }
369  }
370 
371  printf("End program\n");
372  return (0);
373 }
int ec_reconfig_slave(uint16 slave, int timeout)
char * ec_ALstatuscode2string(uint16 ALstatuscode)
void CALLBACK RTthread(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
#define EC_TIMEOUTMON
boolean islost
Definition: ethercatmain.h:229
int ec_readstate(void)
int ec_send_processdata(void)
uint16 outputsWKC
Definition: ethercatmain.h:266
#define EC_TIMEOUTSTATE
Definition: ethercattype.h:76
#define OSAL_THREAD_FUNC
int main(int argc, char *argv[])
uint32 Ibytes
Definition: ethercatmain.h:137
char name[EC_MAXLEN_ADAPTERNAME]
Definition: ethercatmain.h:46
#define EC_TIMEOUTSAFE
Definition: ethercattype.h:68
char ifbuf[1024]
uint8_t uint8
Definition: osal.h:28
char IOmap[4096]
int ec_recover_slave(uint16 slave, int timeout)
uint32 Obytes
Definition: ethercatmain.h:129
Headerfile for all ethercat headers.
ec_adaptert * next
Definition: ethercatmain.h:48
int ec_receive_processdata(int timeout)
uint16 state
Definition: ethercatmain.h:109
int ec_init(const char *ifname)
uint16_t uint16
Definition: osal.h:29
int64 ec_DCtime
Definition: ethercatmain.c:95
char * ec_elist2string(void)
#define EC_TIMEOUTRXM
Definition: ethercattype.h:74
#define TRUE
Definition: osal.h:19
int ec_config_map(void *pIOmap)
#define OSAL_THREAD_HANDLE
uint8 CoEdetails
Definition: ethercatmain.h:213
volatile int wkc
char desc[EC_MAXLEN_ADAPTERNAME]
Definition: ethercatmain.h:47
OSAL_THREAD_FUNC ecatcheck(void *lpParam)
int ec_slavecount
Definition: ethercatmain.c:69
void simpletest(char *ifname)
int osal_usleep(uint32 usec)
Definition: erika/osal.c:22
int osal_thread_create(void *thandle, int stacksize, void *func, void *param)
Definition: linux/osal.c:102
int slave
Definition: aliastool.c:44
#define FALSE
Definition: osal.h:22
int EL7031setup(uint16 slave)
boolean EcatError
Definition: ethercatmain.c:93
#define EC_TIMEOUTRET
Definition: ethercattype.h:64
boolean docheckstate
Definition: ethercatmain.h:270
int ec_writestate(uint16 slave)
#define ECT_COEDET_SDOCA
Definition: ethercatmain.h:99
int(* PO2SOconfig)(uint16 slave)
Definition: ethercatmain.h:231
boolean ec_configdc(void)
Definition: ethercatdc.c:444
OSAL_THREAD_HANDLE thread1
ec_adaptert * ec_find_adapters(void)
Definition: ethercatmain.c:131
void ec_close(void)
int AEPsetup(uint16 slave)
uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
int ec_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex, boolean CA, int psize, void *p, int Timeout)
Definition: ethercatcoe.c:1367
int ec_config_init(uint8 usetable)
volatile int rtcnt


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Sat Jun 27 2020 03:48:21