EthercatMasterWithoutThread.cpp
Go to the documentation of this file.
1 /****************************************************************
2  *
3  * Copyright (c) 2011
4  * All rights reserved.
5  *
6  * Hochschule Bonn-Rhein-Sieg
7  * University of Applied Sciences
8  * Computer Science Department
9  *
10  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11  *
12  * Author:
13  * Jan Paulus, Nico Hochgeschwender, Michael Reckhaus, Azamat Shakhimardanov
14  * Supervised by:
15  * Gerhard K. Kraetzschmar
16  *
17  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18  *
19  * This sofware is published under a dual-license: GNU Lesser General Public
20  * License LGPL 2.1 and BSD license. The dual-license implies that users of this
21  * code may choose which terms they prefer.
22  *
23  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions are met:
27  *
28  * * Redistributions of source code must retain the above copyright
29  * notice, this list of conditions and the following disclaimer.
30  * * Redistributions in binary form must reproduce the above copyright
31  * notice, this list of conditions and the following disclaimer in the
32  * documentation and/or other materials provided with the distribution.
33  * * Neither the name of the Hochschule Bonn-Rhein-Sieg nor the names of its
34  * contributors may be used to endorse or promote products derived from
35  * this software without specific prior written permission.
36  *
37  * This program is free software: you can redistribute it and/or modify
38  * it under the terms of the GNU Lesser General Public License LGPL as
39  * published by the Free Software Foundation, either version 2.1 of the
40  * License, or (at your option) any later version or the BSD license.
41  *
42  * This program is distributed in the hope that it will be useful,
43  * but WITHOUT ANY WARRANTY; without even the implied warranty of
44  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  * GNU Lesser General Public License LGPL and the BSD license for more details.
46  *
47  * You should have received a copy of the GNU Lesser General Public
48  * License LGPL and BSD license along with this program.
49  *
50  ****************************************************************/
51 extern "C" {
53 #include "nicdrv.h"
60 }
63 
64 namespace youbot {
65 
66 EthercatMasterWithoutThread::EthercatMasterWithoutThread(const std::string& configFile, const std::string& configFilePath) {
67  // Bouml preserved body begin 000D1AF1
68 
69  this->ethercatConnectionEstablished = false;
70  ethernetDevice = "eth0";
71  mailboxTimeout = 4000; //micro sec
72  ethercatTimeout = 500; //micro sec
73  configfile = NULL;
74  this->configFileName = configFile;
75  this->configFilepath = configFilePath;
76 
77  //initialize to zero
78  for (unsigned int i = 0; i < 4096; i++) {
79  IOmap_[i] = 0;
80  }
81  //read ethercat parameters form config file
83 
84  // configfile.setSection("EtherCAT");
85  configfile->readInto(ethernetDevice, "EtherCAT", "EthernetDevice");
86  configfile->readInto(ethercatTimeout, "EtherCAT", "EtherCATTimeout_[usec]");
87  configfile->readInto(mailboxTimeout, "EtherCAT", "MailboxTimeout_[usec]");
88 
89  this->initializeEthercat();
90 
91  // Bouml preserved body end 000D1AF1
92 }
93 
95  // Bouml preserved body begin 000D1BF1
96  this->closeEthercat();
97  if (configfile != NULL)
98  delete configfile;
99  // Bouml preserved body end 000D1BF1
100 }
101 
103  // Bouml preserved body begin 000E6B71
104  return false;
105  // Bouml preserved body end 000E6B71
106 }
107 
110  // Bouml preserved body begin 000D1D71
111  return this->nrOfSlaves;
112  // Bouml preserved body end 000D1D71
113 }
114 
115 void EthercatMasterWithoutThread::AutomaticSendOn(const bool enableAutomaticSend) {
116  // Bouml preserved body begin 000D1DF1
117  LOG(trace) << "automatic send is not possible if the EtherCAT master has no thread";
118 
119  return;
120  // Bouml preserved body end 000D1DF1
121 }
122 
123 void EthercatMasterWithoutThread::AutomaticReceiveOn(const bool enableAutomaticReceive) {
124  // Bouml preserved body begin 000D1E71
125  LOG(trace) << "automatic receive is not possible if the EtherCAT master has no thread";
126  return;
127  // Bouml preserved body end 000D1E71
128 }
129 
132 void EthercatMasterWithoutThread::getEthercatDiagnosticInformation(std::vector<ec_slavet>& ethercatSlaveInfos) {
133  // Bouml preserved body begin 000D1EF1
134  ethercatSlaveInfos = this->ethercatSlaveInfo;
135  for (unsigned int i = 0; i < ethercatSlaveInfos.size(); i++) {
136  ethercatSlaveInfos[i].inputs = NULL;
137  ethercatSlaveInfos[i].outputs = NULL;
138  }
139  // Bouml preserved body end 000D1EF1
140 }
141 
145  // Bouml preserved body begin 000D2471
146 
147  for (unsigned int i = 0; i < processDataBuffer.size(); i++) {
148  //fill output buffer (send data)
149  *(ethercatOutputBufferVector[i]) = (processDataBuffer[i]).stctOutput;
150  }
151 
152  //send data to ethercat
153  if (ec_send_processdata() == 0) {
154  return false;
155  }
156 
157  return true;
158 
159  // Bouml preserved body end 000D2471
160 }
161 
165  // Bouml preserved body begin 000D5D71
166 
167  //receive data from ethercat
168  if (ec_receive_processdata(this->ethercatTimeout) == 0) {
169  return false;
170  }
171 
172  for (unsigned int i = 0; i < processDataBuffer.size(); i++) {
173  //fill input buffer (receive data)
174  (processDataBuffer[i]).stctInput = *(ethercatInputBufferVector[i]);
175  }
176 
177  return true;
178 
179  // Bouml preserved body end 000D5D71
180 }
181 
185  // Bouml preserved body begin 000D5DF1
186 
187  return ec_iserror();
188 
189  // Bouml preserved body end 000D5DF1
190 }
191 
193  // Bouml preserved body begin 000F77F1
194  return this->ethercatConnectionEstablished;
195  // Bouml preserved body end 000F77F1
196 }
197 
198 void EthercatMasterWithoutThread::registerJointLimitMonitor(JointLimitMonitor* object, const unsigned int JointNumber) {
199  // Bouml preserved body begin 000FB0F1
200 
201  // Bouml preserved body end 000FB0F1
202 }
203 
206  // Bouml preserved body begin 000D1F71
207 
208  /* initialise SOEM, bind socket to ifname */
209  if (ec_init(const_cast<char*>(ethernetDevice.c_str()))) {
210  LOG(info) << "Initializing EtherCAT on " << ethernetDevice << " without communication thread";
211  /* find and auto-config slaves */
212  if (ec_config(TRUE, &IOmap_) > 0) {
213 
214  LOG(trace) << ec_slavecount << " EtherCAT slaves found and configured.";
215 
216  /* wait for all slaves to reach Pre OP state */
217  /*ec_statecheck(0, EC_STATE_PRE_OP, EC_TIMEOUTSTATE);
218  if (ec_slave[0].state != EC_STATE_PRE_OP ){
219  LOG(debug) << "Not all slaves reached pre operational state.";
220  ec_readstate();
221  //If not all slaves operational find out which one
222  for(int i = 1; i<=ec_slavecount ; i++){
223  if(ec_slave[i].state != EC_STATE_PRE_OP){
224  printf("Slave %d State=%2x StatusCode=%4x : %s\n",
225  i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
226  }
227  }
228  }
229  */
230 
231  /* distributed clock is not working
232  //Configure distributed clock
233  if(!ec_configdc()){
234  LOG(warning) << "no distributed clock is available";
235  }else{
236 
237  uint32 CyclTime = 4000000;
238  uint32 CyclShift = 0;
239  for (int i = 1; i <= ec_slavecount; i++) {
240  ec_dcsync0(i, true, CyclTime, CyclShift);
241  }
242 
243  }
244  */
245 
246  /* wait for all slaves to reach SAFE_OP state */
247  ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE);
248  if (ec_slave[0].state != EC_STATE_SAFE_OP) {
249  LOG(warning) << "Not all EtherCAT slaves reached safe operational state.";
250  ec_readstate();
251  //If not all slaves operational find out which one
252  for (int i = 1; i <= ec_slavecount; i++) {
253  if (ec_slave[i].state != EC_STATE_SAFE_OP) {
254  LOG(info) << "Slave " << i << " State=" << ec_slave[i].state << " StatusCode=" << ec_slave[i].ALstatuscode << " : " << ec_ALstatuscode2string(ec_slave[i].ALstatuscode);
255 
256  }
257  }
258  }
259 
260 
261  //Read the state of all slaves
262  //ec_readstate();
263 
264  LOG(trace) << "Request operational state for all EtherCAT slaves";
265 
266  ec_slave[0].state = EC_STATE_OPERATIONAL;
267  // request OP state for all slaves
268  /* send one valid process data to make outputs in slaves happy*/
269  ec_send_processdata();
270  ec_receive_processdata(EC_TIMEOUTRET);
271  /* request OP state for all slaves */
272  ec_writestate(0);
273  // wait for all slaves to reach OP state
274 
275  ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);
276  if (ec_slave[0].state == EC_STATE_OPERATIONAL) {
277  LOG(trace) << "Operational state reached for all EtherCAT slaves.";
278  } else {
279  throw std::runtime_error("Not all EtherCAT slaves reached operational state.");
280 
281  }
282 
283  } else {
284  throw std::runtime_error("No EtherCAT slaves found!");
285  }
286 
287  } else {
288  throw std::runtime_error("No socket connection on " + ethernetDevice + "\nExcecute as root");
289  }
290 
291 
292 
293  std::string baseJointControllerName = "TMCM-174";
294  std::string baseJointControllerNameAlternative = "TMCM-1632";
295  std::string manipulatorJointControllerName = "TMCM-174";
296  std::string ManipulatorJointControllerNameAlternative = "TMCM-1610";
297  std::string actualSlaveName;
298  nrOfSlaves = 0;
299  YouBotSlaveMsg emptySlaveMsg;
300 
301 
302  configfile->readInto(baseJointControllerName, "BaseJointControllerName");
303  configfile->readInto(baseJointControllerNameAlternative, "BaseJointControllerNameAlternative");
304  configfile->readInto(manipulatorJointControllerName, "ManipulatorJointControllerName");
305  configfile->readInto(ManipulatorJointControllerNameAlternative, "ManipulatorJointControllerNameAlternative");
306 
307  //reserve memory for all slave with a input/output buffer
308  for (int cnt = 1; cnt <= ec_slavecount; cnt++) {
309  LOG(trace) << "Slave: " << cnt << " Name: " << ec_slave[cnt].name << " Output size: " << ec_slave[cnt].Obits
310  << "bits Input size: " << ec_slave[cnt].Ibits << "bits State: " << ec_slave[cnt].state
311  << " delay: " << ec_slave[cnt].pdelay; //<< " has dclock: " << (bool)ec_slave[cnt].hasdc;
312 
313  ethercatSlaveInfo.push_back(ec_slave[cnt]);
314 
315  actualSlaveName = ec_slave[cnt].name;
316  if ((actualSlaveName == baseJointControllerName || actualSlaveName == baseJointControllerNameAlternative ||
317  actualSlaveName == manipulatorJointControllerName || actualSlaveName == ManipulatorJointControllerNameAlternative
318  ) && ec_slave[cnt].Obits > 0 && ec_slave[cnt].Ibits > 0) {
319  nrOfSlaves++;
320  processDataBuffer.push_back(emptySlaveMsg);
321  ethercatOutputBufferVector.push_back((SlaveMessageOutput*) (ec_slave[cnt].outputs));
322  ethercatInputBufferVector.push_back((SlaveMessageInput*) (ec_slave[cnt].inputs));
323  YouBotSlaveMailboxMsg emptyMailboxSlaveMsg(cnt);
324  firstMailboxBufferVector.push_back(emptyMailboxSlaveMsg);
325  }
326  }
327 
328 
329 
330  if (nrOfSlaves > 0) {
331  LOG(info) << nrOfSlaves << " EtherCAT slaves found";
332  this->ethercatConnectionEstablished = true;
333  } else {
334  throw std::runtime_error("No EtherCAT slave could be found");
335  return;
336  }
337 
338 
339  return;
340  // Bouml preserved body end 000D1F71
341 }
342 
345  // Bouml preserved body begin 000D2071
346 
347  this->ethercatConnectionEstablished = false;
348  // Request safe operational state for all slaves
349  ec_slave[0].state = EC_STATE_SAFE_OP;
350 
351  /* request SAFE_OP state for all slaves */
352  ec_writestate(0);
353 
354  //stop SOEM, close socket
355  ec_close();
356 
357  return true;
358  // Bouml preserved body end 000D2071
359 }
360 
364 void EthercatMasterWithoutThread::setMsgBuffer(const YouBotSlaveMsg& msgBuffer, const unsigned int jointNumber) {
365  // Bouml preserved body begin 000D20F1
366 
367  processDataBuffer[jointNumber - 1].stctOutput = msgBuffer.stctOutput;
368 
369  // Bouml preserved body end 000D20F1
370 }
371 
375 void EthercatMasterWithoutThread::getMsgBuffer(const unsigned int jointNumber, YouBotSlaveMsg& returnMsg) {
376  // Bouml preserved body begin 000D2171
377 
378  returnMsg = processDataBuffer[jointNumber - 1];
379 
380  // Bouml preserved body end 000D2171
381 }
382 
386 void EthercatMasterWithoutThread::setMailboxMsgBuffer(const YouBotSlaveMailboxMsg& msgBuffer, const unsigned int jointNumber) {
387  // Bouml preserved body begin 000D21F1
388 
389  firstMailboxBufferVector[jointNumber - 1].stctOutput = msgBuffer.stctOutput;
391  return;
392  // Bouml preserved body end 000D21F1
393 }
394 
398 bool EthercatMasterWithoutThread::getMailboxMsgBuffer(YouBotSlaveMailboxMsg& mailboxMsg, const unsigned int jointNumber) {
399  // Bouml preserved body begin 000D2271
400  bool returnvalue = receiveMailboxMessage(firstMailboxBufferVector[jointNumber - 1]);
401  mailboxMsg.stctInput = firstMailboxBufferVector[jointNumber - 1].stctInput;
402  return returnvalue;
403  // Bouml preserved body end 000D2271
404 }
405 
409  // Bouml preserved body begin 000D22F1
412  mailboxBufferSend[2] = mailboxMsg.stctOutput.typeNumber;
413  mailboxBufferSend[3] = mailboxMsg.stctOutput.motorNumber;
414  mailboxBufferSend[4] = mailboxMsg.stctOutput.value >> 24;
415  mailboxBufferSend[5] = mailboxMsg.stctOutput.value >> 16;
416  mailboxBufferSend[6] = mailboxMsg.stctOutput.value >> 8;
417  mailboxBufferSend[7] = mailboxMsg.stctOutput.value & 0xff;
418  if (ec_mbxsend(mailboxMsg.slaveNumber, &mailboxBufferSend, mailboxTimeout)) {
419  return true;
420  } else {
421  return false;
422  }
423  // Bouml preserved body end 000D22F1
424 }
425 
429  // Bouml preserved body begin 000D2371
430  if (ec_mbxreceive(mailboxMsg.slaveNumber, &mailboxBufferReceive, mailboxTimeout)) {
431  mailboxMsg.stctInput.replyAddress = (int) mailboxBufferReceive[0];
432  mailboxMsg.stctInput.moduleAddress = (int) mailboxBufferReceive[1];
433  mailboxMsg.stctInput.status = (int) mailboxBufferReceive[2];
434  mailboxMsg.stctInput.commandNumber = (int) mailboxBufferReceive[3];
435  mailboxMsg.stctInput.value = (mailboxBufferReceive[4] << 24 | mailboxBufferReceive[5] << 16 | mailboxBufferReceive[6] << 8 | mailboxBufferReceive[7]);
436  return true;
437  }
438  return false;
439  // Bouml preserved body end 000D2371
440 }
441 
443  // Bouml preserved body begin 000D24F1
444  std::stringstream errorMessageStream;
445  errorMessageStream << " ";
446  std::string errorMessage;
447  errorMessage = errorMessageStream.str();
448 
449 
450  if (messageBuffer.stctInput.errorFlags & OVER_CURRENT) {
451  LOG(error) << errorMessage << "got over current";
452  // throw JointErrorException(errorMessage + "got over current");
453  }
454 
455  if (messageBuffer.stctInput.errorFlags & UNDER_VOLTAGE) {
456  LOG(error) << errorMessage << "got under voltage";
457  // throw JointErrorException(errorMessage + "got under voltage");
458  }
459 
460  if (messageBuffer.stctInput.errorFlags & OVER_VOLTAGE) {
461  LOG(error) << errorMessage << "got over voltage";
462  // throw JointErrorException(errorMessage + "got over voltage");
463  }
464 
465  if (messageBuffer.stctInput.errorFlags & OVER_TEMPERATURE) {
466  LOG(error) << errorMessage << "got over temperature";
467  // throw JointErrorException(errorMessage + "got over temperature");
468  }
469 
470  if (messageBuffer.stctInput.errorFlags & MOTOR_HALTED) {
471  // LOG(info) << errorMessage << "is halted";
472  // throw JointErrorException(errorMessage + "is halted");
473  }
474 
475  if (messageBuffer.stctInput.errorFlags & HALL_SENSOR_ERROR) {
476  LOG(error) << errorMessage << "got hall sensor problem";
477  // throw JointErrorException(errorMessage + "got hall sensor problem");
478  }
479 
480  // if (messageBuffer.stctInput.errorFlags & ENCODER_ERROR) {
481  // LOG(error) << errorMessage << "got encoder problem";
482  // // throw JointErrorException(errorMessage + "got encoder problem");
483  // }
484  //
485  // if (messageBuffer.stctInput.errorFlags & INITIALIZATION_ERROR) {
486  // LOG(error) << errorMessage << "got inizialization problem";
487  // // throw JointErrorException(errorMessage + "got motor winding problem");
488  // }
489 
490 // if (messageBuffer.stctInput.errorFlags & PWM_MODE_ACTIVE) {
491  // LOG(error) << errorMessage << "has PWM mode active";
492  // throw JointErrorException(errorMessage + "the cycle time is violated");
493 // }
494 
495  if (messageBuffer.stctInput.errorFlags & VELOCITY_MODE) {
496  // LOG(info) << errorMessage << "has velocity mode active";
497  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
498  }
499 
500  if (messageBuffer.stctInput.errorFlags & POSITION_MODE) {
501  // LOG(info) << errorMessage << "has position mode active";
502  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
503  }
504 
505  if (messageBuffer.stctInput.errorFlags & TORQUE_MODE) {
506  // LOG(info) << errorMessage << "has torque mode active";
507  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
508  }
509 
510  // if (messageBuffer.stctInput.errorFlags & EMERGENCY_STOP) {
511  // LOG(info) << errorMessage << "has emergency stop active";
512  // // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
513  // }
514  //
515  // if (messageBuffer.stctInput.errorFlags & FREERUNNING) {
516  // // LOG(info) << errorMessage << "has freerunning active";
517  // // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
518  // }
519 
520  if (messageBuffer.stctInput.errorFlags & POSITION_REACHED) {
521  // LOG(info) << errorMessage << "has position reached";
522  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
523  }
524 
525  if (messageBuffer.stctInput.errorFlags & INITIALIZED) {
526  // LOG(info) << errorMessage << "is initialized";
527  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
528  }
529 
530  if (messageBuffer.stctInput.errorFlags & TIMEOUT) {
531  LOG(error) << errorMessage << "has a timeout";
532  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
533  }
534 
535  if (messageBuffer.stctInput.errorFlags & I2T_EXCEEDED) {
536  LOG(error) << errorMessage << "exceeded I2t";
537  // throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
538  }
539 
540  // Bouml preserved body end 000D24F1
541 }
542 
544 
546 
547 
548 } // namespace youbot
Headerfile for ethercatdc.c.
void registerJointLimitMonitor(JointLimitMonitor *object, const unsigned int JointNumber)
#define EC_TIMEOUTSTATE
Definition: ethercattype.h:102
unsigned int getNumberOfSlaves() const
return the quantity of ethercat slave which have an input/output buffer
Output part from the EtherCat message of the youBot EtherCat slaves.
std::vector< YouBotSlaveMailboxMsg > firstMailboxBufferVector
bool closeEthercat()
closes the ethercat connection
Reads and writes a configuration file.
Definition: ConfigFile.hpp:125
void setMsgBuffer(const YouBotSlaveMsg &msgBuffer, const unsigned int jointNumber)
void AutomaticSendOn(const bool enableAutomaticSend)
General typedefs and defines for EtherCAT.
Headerfile for ethercatcoe.c.
#define TRUE
Definition: osal.h:28
EthercatMasterWithoutThread(const std::string &configFile, const std::string &configFilePath)
bool receiveMailboxMessage(YouBotSlaveMailboxMsg &mailboxMsg)
std::vector< SlaveMessageInput * > ethercatInputBufferVector
#define LOG(level)
Definition: Logger.hpp:102
bool sendMailboxMessage(const YouBotSlaveMailboxMsg &mailboxMsg)
bool readInto(T &var, const string &key) const
Definition: ConfigFile.hpp:317
It monitors the joint position and will decelerate and stop the joint if it is close the limits...
EtherCAT mailbox message of the youBot slaves.
void setMailboxMsgBuffer(const YouBotSlaveMailboxMsg &msgBuffer, const unsigned int jointNumber)
void initializeEthercat()
establishes the ethercat connection
SlaveMessageInput stctInput
#define EC_TIMEOUTRET
Definition: ethercattype.h:90
Input part from the EtherCat message of the youBot EtherCat slaves.
std::vector< SlaveMessageOutput * > ethercatOutputBufferVector
void parseYouBotErrorFlags(const YouBotSlaveMsg &messageBuffer)
Headerfile for ethercatbase.c.
SlaveMessageOutput stctOutput
Headerfile for ethercatmain.c.
void getEthercatDiagnosticInformation(std::vector< ec_slavet > &ethercatSlaveInfos)
bool getMailboxMsgBuffer(YouBotSlaveMailboxMsg &mailboxMsg, const unsigned int jointNumber)
void AutomaticReceiveOn(const bool enableAutomaticReceive)
EtherCat message of the youBot EtherCat slaves.
Headerfile for ethercatconfig.c.
Headerfile for ethercatprint.c.
char * ec_ALstatuscode2string(uint16 ALstatuscode)
void getMsgBuffer(const unsigned int jointNumber, YouBotSlaveMsg &returnMsg)


youbot_driver
Author(s): Jan Paulus
autogenerated on Mon Jun 10 2019 15:46:24