37 #include <boost/ref.hpp> 38 #include <boost/interprocess/sync/scoped_lock.hpp> 41 #include <soem/nicdrv.h> 52 static const unsigned THREAD_SLEEP_TIME = 1000;
54 static const int NSEC_PER_SECOND = 1e+9;
55 void timespecInc(
struct timespec &tick,
int nsec)
58 while (tick.tv_nsec >= NSEC_PER_SECOND)
60 tick.tv_nsec -= NSEC_PER_SECOND;
72 if ((ec_slave[slave].group == 0) && (ec_slave[slave].state != EC_STATE_OPERATIONAL))
75 if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))
77 fprintf(stderr,
"ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n", slave);
81 else if(ec_slave[slave].state == EC_STATE_SAFE_OP)
83 fprintf(stderr,
"WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n", slave);
87 else if(ec_slave[slave].state > 0)
92 printf(
"MESSAGE : slave %d reconfigured\n",slave);
95 else if(!ec_slave[slave].islost)
99 if (!ec_slave[slave].state)
102 fprintf(stderr,
"ERROR : slave %d lost\n",slave);
106 if (ec_slave[slave].islost)
108 if(!ec_slave[slave].state)
113 printf(
"MESSAGE : slave %d recovered\n",slave);
119 printf(
"MESSAGE : slave %d found\n",slave);
125 void cycleWorker(boost::mutex& mutex,
bool& stop_flag)
128 double period = THREAD_SLEEP_TIME * 1000;
130 struct timespec tick;
131 clock_gettime(CLOCK_REALTIME, &tick);
132 timespecInc(tick, period);
138 boost::mutex::scoped_lock lock(mutex);
143 if (wkc < expected_wkc)
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)
154 fprintf(stderr,
" overrun: %f\n", overrun_time);
157 clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &tick, NULL);
158 timespecInc(tick, period);
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))) 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)
210 fprintf(stderr,
"Ifname %s exceeds maximum size of %u bytes\n",
ifname_.c_str(), MAX_BUFF_SIZE);
213 std::strncpy(buffer,
ifname_.c_str(), MAX_BUFF_SIZE);
215 printf(
"Initializing etherCAT master\n");
219 fprintf(stderr,
"Could not initialize ethercat driver\n");
226 fprintf(stderr,
"No slaves found on %s\n",
ifname_.c_str());
230 printf(
"SOEM found and configured %d slaves\n",
ec_slavecount);
266 fprintf(stderr,
"Could not set EC_STATE_PRE_OP\n");
276 l =
sizeof(num_entries);
278 printf(
"len = %d\n", num_entries);
283 mapping = 0x60B00020;
289 printf(
"len = %d\n", num_entries);
307 printf(
"RxPDO mapping object index %d = %04x ret=%d\n", cnt, idx_rxpdo, ret);
318 printf(
"TxPDO mapping object index %d = %04x ret=%d\n", cnt, idx_txpdo, ret);
323 printf(
"SOEM IOMap size: %d\n", iomap_size);
331 fprintf(stderr,
"Could not set EC_STATE_SAFE_OP\n");
355 fprintf(stderr,
"OPERATIONAL state not set, exiting\n");
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",
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);
382 l =
sizeof(sync_mode);
384 l =
sizeof(cycle_time);
386 l =
sizeof(minimum_cycle_time);
388 l =
sizeof(sync0_cycle_time);
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);
393 printf(
"\nFinished configuration successfully\n");
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 405 fprintf(stderr,
"ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no,
ec_slavecount);
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;
431 fprintf(stderr,
"ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no,
ec_slavecount);
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);
445 fprintf(stderr,
"ERROR : slave_no(%d) is larger than ec_slavecount(%d)\n", slave_no,
ec_slavecount);
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);
455 template <
typename T>
463 template <
typename T>
471 fprintf(stderr,
"Failed to read from ret:%d, slave_no:%d, index:0x%04x, subidx:0x%02x\n", ret, slave_no, index, subidx);
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;
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;
ec_groupt ec_group[EC_MAXGROUP]
int ec_reconfig_slave(uint16 slave, int timeout)
int ec_send_processdata(void)
uint8_t writeSDO(int slave_no, uint16_t index, uint8_t subidx, T value) const
write the SDO object of the given slave no
PACKED_END ec_slavet ec_slave[EC_MAXSLAVE]
boost::mutex iomap_mutex_
int ec_recover_slave(uint16 slave, int timeout)
int ec_receive_processdata(int timeout)
bool initSoem(const std::string &ifname)
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.
int ec_init(char *ifname)
void write(int slave_no, uint8_t channel, uint8_t value)
writes 'value' to the 'channel-th' output-register of the given 'slave'
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)
boost::thread cycle_thread_
int getNumClinets() const
get the number of clients
boolean ec_configdc(void)
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.
const std::string ifname_
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_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex, boolean CA, int psize, void *p, int Timeout)
#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.
T readSDO(int slave_no, uint16_t index, uint8_t subidx) const
read the SDO object of the given slave no