ethercat_manager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015, Jonathan Meyer
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the names of Tokyo Opensource Robotics Kyokai Association. nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 // copied from https://github.com/ros-industrial/robotiq/blob/jade-devel/robotiq_ethercat/src/ethercat_manager.cpp
29 
30 
32 
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <time.h>
36 
37 #include <boost/ref.hpp>
38 #include <boost/interprocess/sync/scoped_lock.hpp>
39 
40 #include <soem/ethercattype.h>
41 #include <soem/nicdrv.h>
42 #include <soem/ethercatbase.h>
43 #include <soem/ethercatmain.h>
44 #include <soem/ethercatdc.h>
45 #include <soem/ethercatcoe.h>
46 #include <soem/ethercatfoe.h>
47 #include <soem/ethercatconfig.h>
48 #include <soem/ethercatprint.h>
49 
50 namespace
51 {
52 static const unsigned THREAD_SLEEP_TIME = 1000; // 1 ms
53 static const unsigned EC_TIMEOUTMON = 500;
54 static const int NSEC_PER_SECOND = 1e+9;
55 void timespecInc(struct timespec &tick, int nsec)
56 {
57  tick.tv_nsec += nsec;
58  while (tick.tv_nsec >= NSEC_PER_SECOND)
59  {
60  tick.tv_nsec -= NSEC_PER_SECOND;
61  tick.tv_sec++;
62  }
63 }
64 
65 void handleErrors()
66 {
67  /* one ore more slaves are not responding */
69  ec_readstate();
70  for (int slave = 1; slave <= ec_slavecount; slave++)
71  {
72  if ((ec_slave[slave].group == 0) && (ec_slave[slave].state != EC_STATE_OPERATIONAL))
73  {
75  if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))
76  {
77  fprintf(stderr, "ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n", slave);
79  ec_writestate(slave);
80  }
81  else if(ec_slave[slave].state == EC_STATE_SAFE_OP)
82  {
83  fprintf(stderr, "WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n", slave);
85  ec_writestate(slave);
86  }
87  else if(ec_slave[slave].state > 0)
88  {
89  if (ec_reconfig_slave(slave, EC_TIMEOUTMON))
90  {
92  printf("MESSAGE : slave %d reconfigured\n",slave);
93  }
94  }
95  else if(!ec_slave[slave].islost)
96  {
97  /* re-check state */
98  ec_statecheck(slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET);
99  if (!ec_slave[slave].state)
100  {
102  fprintf(stderr, "ERROR : slave %d lost\n",slave);
103  }
104  }
105  }
106  if (ec_slave[slave].islost)
107  {
108  if(!ec_slave[slave].state)
109  {
110  if (ec_recover_slave(slave, EC_TIMEOUTMON))
111  {
113  printf("MESSAGE : slave %d recovered\n",slave);
114  }
115  }
116  else
117  {
119  printf("MESSAGE : slave %d found\n",slave);
120  }
121  }
122  }
123 }
124 
125 void cycleWorker(boost::mutex& mutex, bool& stop_flag)
126 {
127  // 1ms in nanoseconds
128  double period = THREAD_SLEEP_TIME * 1000;
129  // get curren ttime
130  struct timespec tick;
131  clock_gettime(CLOCK_REALTIME, &tick);
132  timespecInc(tick, period);
133  while (!stop_flag)
134  {
135  int expected_wkc = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
136  int sent, wkc;
137  {
138  boost::mutex::scoped_lock lock(mutex);
139  sent = ec_send_processdata();
140  wkc = ec_receive_processdata(EC_TIMEOUTRET);
141  }
142 
143  if (wkc < expected_wkc)
144  {
145  handleErrors();
146  }
147 
148  // check overrun
149  struct timespec before;
150  clock_gettime(CLOCK_REALTIME, &before);
151  double overrun_time = (before.tv_sec + double(before.tv_nsec)/NSEC_PER_SECOND) - (tick.tv_sec + double(tick.tv_nsec)/NSEC_PER_SECOND);
152  if (overrun_time > 0.0)
153  {
154  fprintf(stderr, " overrun: %f\n", overrun_time);
155  }
156  //usleep(THREAD_SLEEP_TIME);
157  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &tick, NULL);
158  timespecInc(tick, period);
159  //printf("%24.12f %14.10f [msec] %02x %02x %02x %02x\n", tick.tv_sec+double(tick.tv_nsec)/NSEC_PER_SECOND, overrun_time*1000, ec_slave[1].outputs[24], ec_slave[1].outputs[23], ec_slave[1].outputs[22], ec_slave[1].outputs[21]);
160  }
161 }
162 
163 } // end of anonymous namespace
164 
165 
166 namespace ethercat {
167 
168 EtherCatManager::EtherCatManager(const std::string& ifname)
169  : ifname_(ifname),
170  num_clients_(0),
171  stop_flag_(false)
172 {
173  if (initSoem(ifname))
174  {
175  cycle_thread_ = boost::thread(cycleWorker,
176  boost::ref(iomap_mutex_),
177  boost::ref(stop_flag_));
178  }
179  else
180  {
181  // construction failed
182  throw EtherCatError("Could not initialize SOEM");
183  }
184 }
185 
187 {
188  stop_flag_ = true;
189 
190  // Request init operational state for all slaves
192 
193  /* request init state for all slaves */
194  ec_writestate(0);
195 
196  //stop SOEM, close socket
197  ec_close();
198  cycle_thread_.join();
199 }
200 
201 #define IF_MINAS(_ec_slave) (((int)_ec_slave.eep_man == 0x066f) && ((((0xf0000000&(int)ec_slave[cnt].eep_id)>>28) == 0x5) || (((0xf0000000&(int)ec_slave[cnt].eep_id)>>28) == 0xD)))
202 bool EtherCatManager::initSoem(const std::string& ifname) {
203  // Copy string contents because SOEM library doesn't
204  // practice const correctness
205  const static unsigned MAX_BUFF_SIZE = 1024;
206  char buffer[MAX_BUFF_SIZE];
207  size_t name_size = ifname_.size();
208  if (name_size > sizeof(buffer) - 1)
209  {
210  fprintf(stderr, "Ifname %s exceeds maximum size of %u bytes\n", ifname_.c_str(), MAX_BUFF_SIZE);
211  return false;
212  }
213  std::strncpy(buffer, ifname_.c_str(), MAX_BUFF_SIZE);
214 
215  printf("Initializing etherCAT master\n");
216 
217  if (!ec_init(buffer))
218  {
219  fprintf(stderr, "Could not initialize ethercat driver\n");
220  return false;
221  }
222 
223  /* find and auto-config slaves */
224  if (ec_config_init(FALSE) <= 0)
225  {
226  fprintf(stderr, "No slaves found on %s\n", ifname_.c_str());
227  return false;
228  }
229 
230  printf("SOEM found and configured %d slaves\n", ec_slavecount);
231  for( int cnt = 1 ; cnt <= ec_slavecount ; cnt++)
232  {
233  // MINAS-A5B Serial Man = 066Fh, ID = [5/D]****[0/4/8][0-F]*
234  printf(" Man: %8.8x ID: %8.8x Rev: %8.8x %s\n", (int)ec_slave[cnt].eep_man, (int)ec_slave[cnt].eep_id, (int)ec_slave[cnt].eep_rev, IF_MINAS(ec_slave[cnt])?" MINAS Drivers":"");
235  if(IF_MINAS(ec_slave[cnt])) {
236  num_clients_++;
237  }
238  }
239  printf("Found %d MINAS Drivers\n", num_clients_);
240 
241 
242  /*
243  SET PDO maping 4 SX-DSV02470 p.52
244  Index Size(bit) Name
245  RxPDO (1603h) 6040h 00h 16 Controlword
246  6060h 00h 8 Modes of operation
247  6071h 00h 16 Target Torque
248  6072h 00h 16 Max torque
249  607Ah 00h 32 Target Position
250  6080h 00h 32 Max motor speed
251  60B8h 00h 16 Touch probe function
252  60FFh 00h 32 Target Velocity
253  TxPDO (1A03h)
254  603Fh 00h 16 Error code
255  6041h 00h 16 Statusword
256  6061h 00h 8 Modes of operation display
257  6064h 00h 32 Position actual value
258  606Ch 00h 32 Velocity actual value
259  6077h 00h 16 Torque actual value
260  60B9h 00h 16 Touch probe status
261  60BAh 00h 32 Touch probe pos1 pos val
262  60FDh 00h 32 Digital inputs
263  */
265  {
266  fprintf(stderr, "Could not set EC_STATE_PRE_OP\n");
267  return false;
268  }
269 
270  // extend PDO mapping 4 see p. 53 of SX-DSV02470
271  for( int cnt = 1 ; cnt <= ec_slavecount ; cnt++)
272  {
273  if (! IF_MINAS(ec_slave[cnt])) continue;
274  int ret = 0, l;
275  uint8_t num_entries;
276  l = sizeof(num_entries);
277  ret += ec_SDOread(cnt, 0x1603, 0x00, FALSE, &l, &num_entries, EC_TIMEOUTRXM);
278  printf("len = %d\n", num_entries);
279  num_entries = 0;
280  ret += ec_SDOwrite(cnt, 0x1603, 0x00, FALSE, sizeof(num_entries), &num_entries, EC_TIMEOUTRXM);
281  // add position offset (60B0 / 00h / I32)
282  uint32_t mapping;
283  mapping = 0x60B00020;
284  ret += ec_SDOwrite(cnt, 0x1603, 0x09, FALSE, sizeof(mapping), &mapping, EC_TIMEOUTRXM);
285  //
286  num_entries = 9;
287  ret += ec_SDOwrite(cnt, 0x1603, 0x00, FALSE, sizeof(num_entries), &num_entries, EC_TIMEOUTRXM);
288  ret += ec_SDOread(cnt, 0x1603, 0x00, FALSE, &l, &num_entries, EC_TIMEOUTRXM);
289  printf("len = %d\n", num_entries);
290  }
291 
292  // use PDO mapping 4
293  for( int cnt = 1 ; cnt <= ec_slavecount ; cnt++)
294  {
295  if (! IF_MINAS(ec_slave[cnt])) continue;
296  int ret = 0, l;
297  uint8_t num_pdo ;
298  // set 0 change PDO mapping index
299  num_pdo = 0;
300  ret += ec_SDOwrite(cnt, 0x1c12, 0x00, FALSE, sizeof(num_pdo), &num_pdo, EC_TIMEOUTRXM);
301  // set to default PDO mapping 4
302  uint16_t idx_rxpdo = 0x1603;
303  ret += ec_SDOwrite(cnt, 0x1c12, 0x01, FALSE, sizeof(idx_rxpdo), &idx_rxpdo, EC_TIMEOUTRXM);
304  // set number of assigned PDOs
305  num_pdo = 1;
306  ret += ec_SDOwrite(cnt, 0x1c12, 0x00, FALSE, sizeof(num_pdo), &num_pdo, EC_TIMEOUTRXM);
307  printf("RxPDO mapping object index %d = %04x ret=%d\n", cnt, idx_rxpdo, ret);
308 
309  // set 0 change PDO mapping index
310  num_pdo = 0;
311  ret += ec_SDOwrite(cnt, 0x1c13, 0x00, FALSE, sizeof(num_pdo), &num_pdo, EC_TIMEOUTRXM);
312  // set to default PDO mapping 4
313  uint16_t idx_txpdo = 0x1a03;
314  ret += ec_SDOwrite(cnt, 0x1c13, 0x01, FALSE, sizeof(idx_txpdo), &idx_txpdo, EC_TIMEOUTRXM);
315  // set number of assigned PDOs
316  num_pdo = 1;
317  ret += ec_SDOwrite(cnt, 0x1c13, 0x00, FALSE, sizeof(num_pdo), &num_pdo, EC_TIMEOUTRXM);
318  printf("TxPDO mapping object index %d = %04x ret=%d\n", cnt, idx_txpdo, ret);
319  }
320 
321  // configure IOMap
322  int iomap_size = ec_config_map(iomap_);
323  printf("SOEM IOMap size: %d\n", iomap_size);
324 
325  // locates dc slaves - ???
326  ec_configdc();
327 
328  // '0' here addresses all slaves
330  {
331  fprintf(stderr, "Could not set EC_STATE_SAFE_OP\n");
332  return false;
333  }
334 
335  /*
336  This section attempts to bring all slaves to operational status. It does so
337  by attempting to set the status of all slaves (ec_slave[0]) to operational,
338  then proceeding through 40 send/recieve cycles each waiting up to 50 ms for a
339  response about the status.
340  */
344 
345  ec_writestate(0);
346  int chk = 40;
347  do {
350  ec_statecheck(0, EC_STATE_OPERATIONAL, 50000); // 50 ms wait for state check
351  } while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));
352 
354  {
355  fprintf(stderr, "OPERATIONAL state not set, exiting\n");
356  return false;
357  }
358 
359  ec_readstate();
360  for( int cnt = 1 ; cnt <= ec_slavecount ; cnt++)
361  {
362  if (! IF_MINAS(ec_slave[cnt])) continue;
363  printf("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n",
364  cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits,
365  ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc);
366  if (ec_slave[cnt].hasdc) printf(" DCParentport:%d\n", ec_slave[cnt].parentport);
367  printf(" Activeports:%d.%d.%d.%d\n", (ec_slave[cnt].activeports & 0x01) > 0 ,
368  (ec_slave[cnt].activeports & 0x02) > 0 ,
369  (ec_slave[cnt].activeports & 0x04) > 0 ,
370  (ec_slave[cnt].activeports & 0x08) > 0 );
371  printf(" Configured address: %4.4x\n", ec_slave[cnt].configadr);
372  }
373 
374  for( int cnt = 1 ; cnt <= ec_slavecount ; cnt++)
375  {
376  if (! IF_MINAS(ec_slave[cnt])) continue;
377  int ret = 0, l;
378  uint16_t sync_mode;
379  uint32_t cycle_time;
380  uint32_t minimum_cycle_time;
381  uint32_t sync0_cycle_time;
382  l = sizeof(sync_mode);
383  ret += ec_SDOread(cnt, 0x1c32, 0x01, FALSE, &l, &sync_mode, EC_TIMEOUTRXM);
384  l = sizeof(cycle_time);
385  ret += ec_SDOread(cnt, 0x1c32, 0x01, FALSE, &l, &cycle_time, EC_TIMEOUTRXM);
386  l = sizeof(minimum_cycle_time);
387  ret += ec_SDOread(cnt, 0x1c32, 0x05, FALSE, &l, &minimum_cycle_time, EC_TIMEOUTRXM);
388  l = sizeof(sync0_cycle_time);
389  ret += ec_SDOread(cnt, 0x1c32, 0x0a, FALSE, &l, &sync0_cycle_time, EC_TIMEOUTRXM);
390  printf("PDO syncmode %02x, cycle time %d ns (min %d), sync0 cycle time %d ns, ret = %d\n", sync_mode, cycle_time, minimum_cycle_time, sync0_cycle_time, ret);
391  }
392 
393  printf("\nFinished configuration successfully\n");
394  return true;
395 }
396 
398 {
399  return num_clients_;
400 }
401 
402 void EtherCatManager::getStatus(int slave_no, std::string &name, int &eep_man, int &eep_id, int &eep_rev, int &obits, int &ibits, int &state, int &pdelay, int &hasdc, int &activeports, int &configadr) const
403 {
404  if (slave_no > ec_slavecount) {
405  fprintf(stderr, "ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no, ec_slavecount);
406  exit(1);
407  }
408  name = std::string(ec_slave[slave_no].name);
409  eep_man = (int)ec_slave[slave_no].eep_man;
410  eep_id = (int)ec_slave[slave_no].eep_id;
411  eep_rev = (int)ec_slave[slave_no].eep_rev;
412  obits = ec_slave[slave_no].Obits;
413  ibits = ec_slave[slave_no].Ibits;
414  state = ec_slave[slave_no].state;
415  pdelay = ec_slave[slave_no].pdelay;
416  hasdc = ec_slave[slave_no].hasdc;
417  activeports = ec_slave[slave_no].activeports;
418  configadr = ec_slave[slave_no].configadr;
419 }
420 
421 void EtherCatManager::write(int slave_no, uint8_t channel, uint8_t value)
422 {
423  boost::mutex::scoped_lock lock(iomap_mutex_);
424  ec_slave[slave_no].outputs[channel] = value;
425 }
426 
427 uint8_t EtherCatManager::readInput(int slave_no, uint8_t channel) const
428 {
429  boost::mutex::scoped_lock lock(iomap_mutex_);
430  if (slave_no > ec_slavecount) {
431  fprintf(stderr, "ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no, ec_slavecount);
432  exit(1);
433  }
434  if (channel*8 >= ec_slave[slave_no].Ibits) {
435  fprintf(stderr, "ERROR : channel(%d) is larget thatn Input bits (%d)\n", channel*8, ec_slave[slave_no].Ibits);
436  exit(1);
437  }
438  return ec_slave[slave_no].inputs[channel];
439 }
440 
441 uint8_t EtherCatManager::readOutput(int slave_no, uint8_t channel) const
442 {
443  boost::mutex::scoped_lock lock(iomap_mutex_);
444  if (slave_no > ec_slavecount) {
445  fprintf(stderr, "ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no, ec_slavecount);
446  exit(1);
447  }
448  if (channel*8 >= ec_slave[slave_no].Obits) {
449  fprintf(stderr, "ERROR : channel(%d) is larget thatn Output bits (%d)\n", channel*8, ec_slave[slave_no].Obits);
450  exit(1);
451  }
452  return ec_slave[slave_no].outputs[channel];
453 }
454 
455 template <typename T>
456 uint8_t EtherCatManager::writeSDO(int slave_no, uint16_t index, uint8_t subidx, T value) const
457 {
458  int ret;
459  ret = ec_SDOwrite(slave_no, index, subidx, FALSE, sizeof(value), &value, EC_TIMEOUTSAFE);
460  return ret;
461 }
462 
463 template <typename T>
464 T EtherCatManager::readSDO(int slave_no, uint16_t index, uint8_t subidx) const
465 {
466  int ret, l;
467  T val;
468  l = sizeof(val);
469  ret = ec_SDOread(slave_no, index, subidx, FALSE, &l, &val, EC_TIMEOUTRXM);
470  if ( ret <= 0 ) { // ret = Workcounter from last slave response
471  fprintf(stderr, "Failed to read from ret:%d, slave_no:%d, index:0x%04x, subidx:0x%02x\n", ret, slave_no, index, subidx);
472  }
473  return val;
474 }
475 
476 template uint8_t EtherCatManager::writeSDO<char> (int slave_no, uint16_t index, uint8_t subidx, char value) const;
477 template uint8_t EtherCatManager::writeSDO<int> (int slave_no, uint16_t index, uint8_t subidx, int value) const;
478 template uint8_t EtherCatManager::writeSDO<short> (int slave_no, uint16_t index, uint8_t subidx, short value) const;
479 template uint8_t EtherCatManager::writeSDO<long> (int slave_no, uint16_t index, uint8_t subidx, long value) const;
480 template uint8_t EtherCatManager::writeSDO<unsigned char> (int slave_no, uint16_t index, uint8_t subidx, unsigned char value) const;
481 template uint8_t EtherCatManager::writeSDO<unsigned int> (int slave_no, uint16_t index, uint8_t subidx, unsigned int value) const;
482 template uint8_t EtherCatManager::writeSDO<unsigned short> (int slave_no, uint16_t index, uint8_t subidx, unsigned short value) const;
483 template uint8_t EtherCatManager::writeSDO<unsigned long> (int slave_no, uint16_t index, uint8_t subidx, unsigned long value) const;
484 
485 template char EtherCatManager::readSDO<char> (int slave_no, uint16_t index, uint8_t subidx) const;
486 template int EtherCatManager::readSDO<int> (int slave_no, uint16_t index, uint8_t subidx) const;
487 template short EtherCatManager::readSDO<short> (int slave_no, uint16_t index, uint8_t subidx) const;
488 template long EtherCatManager::readSDO<long> (int slave_no, uint16_t index, uint8_t subidx) const;
489 template unsigned char EtherCatManager::readSDO<unsigned char> (int slave_no, uint16_t index, uint8_t subidx) const;
490 template unsigned int EtherCatManager::readSDO<unsigned int> (int slave_no, uint16_t index, uint8_t subidx) const;
491 template unsigned short EtherCatManager::readSDO<unsigned short> (int slave_no, uint16_t index, uint8_t subidx) const;
492 template unsigned long EtherCatManager::readSDO<unsigned long> (int slave_no, uint16_t index, uint8_t subidx) const;
493 
494 }
495 
ec_groupt ec_group[EC_MAXGROUP]
int ec_reconfig_slave(uint16 slave, int timeout)
int ec_readstate(void)
int ec_send_processdata(void)
#define EC_TIMEOUTSTATE
uint8_t writeSDO(int slave_no, uint16_t index, uint8_t subidx, T value) const
write the SDO object of the given slave no
uint16 Ibits
PACKED_END ec_slavet ec_slave[EC_MAXSLAVE]
#define EC_TIMEOUTSAFE
int32 pdelay
uint8 * inputs
int ec_recover_slave(uint16 slave, int timeout)
int ec_receive_processdata(int timeout)
bool initSoem(const std::string &ifname)
unsigned short uint16_t
uint8 * outputs
unsigned char uint8_t
#define EC_TIMEOUTRXM
#define TRUE
int ec_config_map(void *pIOmap)
uint8_t readOutput(int slave_no, uint8_t channel) const
Reads the "channel-th" output-register of the given slave no.
#define EC_TIMEOUTMON
EC_STATE_OPERATIONAL
boolean islost
int ec_init(char *ifname)
unsigned int uint32_t
boolean docheckstate
boolean hasdc
int slave
#define FALSE
void write(int slave_no, uint8_t channel, uint8_t value)
writes &#39;value&#39; to the &#39;channel-th&#39; output-register of the given &#39;slave&#39;
EC_STATE_ACK
uint16 Obits
EC_STATE_SAFE_OP
EC_STATE_PRE_OP
#define EC_TIMEOUTRET
void getStatus(int slave_no, std::string &name, int &eep_man, int &eep_id, int &eep_rev, int &obits, int &ibits, int &state, int &pdelay, int &hasdc, int &activeports, int &configadr) const
get the status of clients
int ec_writestate(uint16 slave)
int getNumClinets() const
get the number of clients
int wkc
boolean ec_configdc(void)
uint16 outputsWKC
EtherCAT exception. Currently this is only thrown in the event of a failure to construct an EtherCat ...
EtherCatManager(const std::string &ifname)
Constructs and initializes the ethercat slaves on a given network interface.
uint16 state
void ec_close(void)
int ec_SDOread(uint16 slave, uint16 index, uint8 subindex, boolean CA, int *psize, void *p, int timeout)
uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
int ec_slavecount
uint8 activeports
int ec_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex, boolean CA, int psize, void *p, int Timeout)
uint16 configadr
#define IF_MINAS(_ec_slave)
int ec_config_init(uint8 usetable)
uint8_t readInput(int slave_no, uint8_t channel) const
Reads the "channel-th" input-register of the given slave no.
EC_STATE_INIT
T readSDO(int slave_no, uint16_t index, uint8_t subidx) const
read the SDO object of the given slave no


ethercat_manager
Author(s): Jonathan Meyer
autogenerated on Mon Jun 10 2019 14:02:24