CanDriveHarmonica.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <assert.h>
20 #include <unistd.h>
21 
22 //-----------------------------------------------
24 {
25  // Parameter
27  m_Param.dCanTimeout = 6;
28 
29  // Variables
30  m_pCanCtrl = NULL;
31 
32  m_iStatusCtrl = 0;
36 
38 
39  m_bLimSwLeft = false;
40  m_bLimSwRight = false;
41 
42  m_bLimitSwitchEnabled = false;
43 
45 
47  m_bCurrentLimitOn = false;
48 
50 
53 
54  m_bOutputOfFailure = false;
55 
56  m_bIsInitialized = false;
57 
58 
59  ElmoRec = new ElmoRecorder(this);
60 
61 }
62 
63 //-----------------------------------------------
64 void CanDriveHarmonica::setCanOpenParam( int iTxPDO1, int iTxPDO2, int iRxPDO2, int iTxSDO, int iRxSDO )
65 {
66  m_ParamCanOpen.iTxPDO1 = iTxPDO1;
67  m_ParamCanOpen.iTxPDO2 = iTxPDO2;
68  m_ParamCanOpen.iRxPDO2 = iRxPDO2;
69  m_ParamCanOpen.iTxSDO = iTxSDO;
70  m_ParamCanOpen.iRxSDO = iRxSDO;
71 
72 }
73 
74 //-----------------------------------------------
76 {
77  bool bRet = false;
78  int iDigIn;
79  int iFailure;
80  int iPara;
81 
82  int iHomeDigIn = 0x0001; // 0x0001 for CoB3 steering drive homing input; 0x0400 for Scara
83  int iTemp1, iTemp2;
84 
85  m_CanMsgLast = msg;
86 
87  //-----------------------
88  // eval answers from PDO1 - transmitted on SYNC msg
89  if (msg.m_iID == m_ParamCanOpen.iTxPDO1)
90  {
91  iTemp1 = (msg.getAt(3) << 24) | (msg.getAt(2) << 16)
92  | (msg.getAt(1) << 8) | (msg.getAt(0) );
93 
95  PosMotIncrToPosGearRad(iTemp1);
96 
97  iTemp2 = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
98  | (msg.getAt(5) << 8) | (msg.getAt(4) );
99 
101  VelMotIncrPeriodToVelGearRadS(iTemp2);
102 
104 
105  bRet = true;
106  }
107 
108  //-----------------------
109  // eval answers from binary interpreter
110  if (msg.m_iID == m_ParamCanOpen.iTxPDO2)
111  {
112  if( (msg.getAt(0) == 'P') && (msg.getAt(1) == 'X') ) // current pos
113  {
114  }
115 
116  else if( (msg.getAt(0) == 'P') && (msg.getAt(1) == 'A') ) // position absolute
117  {
118  }
119 
120  else if( (msg.getAt(0) == 'J') && (msg.getAt(1) == 'V') ) // current velocity
121  {
122  }
123 
124  else if( (msg.getAt(0) == 'B') && (msg.getAt(1) == 'G') ) // begin motion
125  {
126  }
127 
128  else if( (msg.getAt(0) == 'U') && (msg.getAt(1) == 'M') ) // user mode
129  {
130  iDigIn = 0x1FFFFF & ( (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
131  | (msg.getAt(5) << 8) | (msg.getAt(4)) );
132  }
133 
134  else if( (msg.getAt(0) == 'I') && (msg.getAt(1) == 'P') ) // digital in == limit switches
135  {
136  iDigIn = 0x1FFFFF & ( (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
137  | (msg.getAt(5) << 8) | (msg.getAt(4)) );
138  iDigIn = 0x1FFFFF & ( (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
139  | (msg.getAt(5) << 8) | (msg.getAt(4)) );
140 
141  if( (iDigIn & iHomeDigIn) != 0x0000 )
142  {
143  m_bLimSwRight = true;
144  }
145  }
146 
147  else if( (msg.getAt(0) == 'S') && (msg.getAt(1) == 'R') ) // status
148  {
149  m_iStatusCtrl = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
150  | (msg.getAt(5) << 8) | (msg.getAt(4) );
151 
154 
155  }
156 
157  else if( (msg.getAt(0) == 'M') && (msg.getAt(1) == 'F') ) // motor failure
158  {
159  iFailure = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
160  | (msg.getAt(5) << 8) | (msg.getAt(4) );
161 
162  evalMotorFailure(iFailure);
163  }
164 
165  // debug eval
166  else if( (msg.getAt(0) == 'U') && (msg.getAt(1) == 'M') )
167  {
168  iPara = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
169  | (msg.getAt(5) << 8) | (msg.getAt(4) );
170 
171  std::cout << "um " << iPara << std::endl;
172  }
173 
174  else if( (msg.getAt(0) == 'P') && (msg.getAt(1) == 'M') )
175  {
176  iPara = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
177  | (msg.getAt(5) << 8) | (msg.getAt(4) );
178 
179  std::cout << "pm " << iPara << std::endl;
180  }
181 
182  else if( (msg.getAt(0) == 'A') && (msg.getAt(1) == 'C') )
183  {
184  iPara = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
185  | (msg.getAt(5) << 8) | (msg.getAt(4) );
186 
187  std::cout << "ac " << iPara << std::endl;
188  }
189 
190  else if( (msg.getAt(0) == 'D') && (msg.getAt(1) == 'C') )
191  {
192  iPara = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
193  | (msg.getAt(5) << 8) | (msg.getAt(4) );
194 
195  std::cout << "dc " << iPara << std::endl;
196  }
197  else if( (msg.getAt(0) == 'H') && (msg.getAt(1) == 'M') )
198  {
199  // status message (homing armed = 1 / disarmed = 0) is encoded in 5th byte
200  if(msg.getAt(4) == 0)
201  {
202  // if 0 received: elmo disarmed homing after receiving the defined event
203  m_bLimSwRight = true;
204  }
205  }
206  else if( (msg.getAt(0) == 'I') && (msg.getAt(1) == 'Q') )
207  {
208  int iVal=0;
209  iVal = (msg.getAt(7) << 24) | (msg.getAt(6) << 16)
210  | (msg.getAt(5) << 8) | (msg.getAt(4) );
211  float* pfVal;
212  pfVal=(float*)&iVal;
213  m_dMotorCurr = *pfVal;
214  }
215 
216  else
217  {
218  }
219 
221 
222  bRet = true;
223  }
224 
225  //-----------------------
226  // eval answer from SDO
227  if (msg.m_iID == m_ParamCanOpen.iTxSDO)
228  {
230 
231  if( (msg.getAt(0) >> 5) == 0) { //Received Upload SDO Segment (scs = 0)
232  //std::cout << "SDO Upload Segment received" << std::endl;
234 
235  } else if( (msg.getAt(0) & 0xE2) == 0x40) { //Received Initiate SDO Upload, that is not expedited -> start segmented upload (scs = 2 AND expedited flag = 0)
236  //std::cout << "SDO Initiate Segmented Upload received, Object ID: " << (msg.getAt(1) | (msg.getAt(2) << 8) ) << std::endl;
238 
239  } else if( (msg.getAt(0) >> 5) == 4) { // Received an Abort SDO Transfer message, cs = 4
240  unsigned int iErrorNum = (msg.getAt(4) | msg.getAt(5) << 8 | msg.getAt(6) << 16 | msg.getAt(7) << 24);
241  receivedSDOTransferAbort(iErrorNum);
242  }
243 
244  bRet = true;
245  }
246 
247  return bRet;
248 }
249 
250 //-----------------------------------------------
252 {
253  int iCnt, iPosCnt;
254  bool bRet = true;
255  CanMsg Msg;
256 
258 
259 
260  // Set Values for Modulo-Counting. Neccessary to preserve absolute position for homed motors (after encoder overflow)
261  int iIncrRevWheel = int( (double)m_DriveParam.getGearRatio() * (double)m_DriveParam.getBeltRatio()
262  * (double)m_DriveParam.getEncIncrPerRevMot() * 3 );
263  IntprtSetInt(8, 'M', 'O', 0, 0);
264  usleep(20000);
265  IntprtSetInt(8, 'X', 'M', 2, iIncrRevWheel * 5000);
266  usleep(20000);
267  IntprtSetInt(8, 'X', 'M', 1, -iIncrRevWheel * 5000);
268  usleep(20000);
269 
270 
272  // ---------- set position counter to zero
273  IntprtSetInt(8, 'P', 'X', 0, 0);
274 
275  iCnt = 0;
276  while(true)
277  {
278  m_pCanCtrl->receiveMsg(&Msg);
279 
280  if( (Msg.getAt(0) == 'P') && (Msg.getAt(1) == 'X') )
281  {
282  iPosCnt = (Msg.getAt(7) << 24) | (Msg.getAt(6) << 16)
283  | (Msg.getAt(5) << 8) | (Msg.getAt(4) );
284 
287  break;
288  }
289 
290  if ( iCnt > 300 )
291  {
292  std::cout << "CanDriveHarmonica: initial position not set" << std::endl;
293  bRet = false;
294  break;
295  }
296 
297  usleep(10000);
298  iCnt++;
299  }
300 
301  // ---------- set PDO mapping
302  // Mapping of TPDO1:
303  // - position
304  // - velocity
305 
306  // stop all emissions of TPDO1
307  sendSDODownload(0x1A00, 0, 0);
308 
309  // position 4 byte of TPDO1
310  sendSDODownload(0x1A00, 1, 0x60640020);
311 
312  // velocity 4 byte of TPDO1
313  sendSDODownload(0x1A00, 2, 0x60690020);
314 
315  // transmission type "synch"
316  sendSDODownload(0x1800, 2, 1);
317 
318  // activate mapped objects
319  sendSDODownload(0x1A00, 0, 2);
320 
321  m_bWatchdogActive = false;
322 
323  if( bRet )
324  m_bIsInitialized = true;
325 
326  return bRet;
327 }
328 //-----------------------------------------------
330 {
331  bool bRet = true;
332  // motor off
333  IntprtSetInt(8, 'M', 'O', 0, 0);
334  usleep(20000);
335  return bRet;
336 }
337 //-----------------------------------------------
339 {
340  // motor on
341  IntprtSetInt(8, 'M', 'O', 0, 1);
342  usleep(20000);
343 
344  // ------------------- request status
345  int iCnt;
346  bool bRet = true;
347  int iStatus;
348  CanMsg Msg;
349 
350  // clear the can buffer
351  do
352  {
353  bRet = m_pCanCtrl->receiveMsg(&Msg);
354  }
355  while(bRet == true);
356 
357  // send request
358  IntprtSetInt(4, 'S', 'R', 0, 0);
359 
360  iCnt = 0;
361  while(true)
362  {
363  m_pCanCtrl->receiveMsg(&Msg);
364 
365  if( (Msg.getAt(0) == 'S') && (Msg.getAt(1) == 'R') )
366  {
367  iStatus = (Msg.getAt(7) << 24) | (Msg.getAt(6) << 16)
368  | (Msg.getAt(5) << 8) | (Msg.getAt(4) );
369 
370  bRet = evalStatusRegister(iStatus);
371  break;
372  }
373 
374  if ( iCnt > 300 )
375  {
376  std::cout << "CanDriveHarmonica::enableMotor(): No answer on status request" << std::endl;
377  bRet = false;
378  break;
379  }
380 
381  usleep(10000);
382  iCnt++;
383  }
384 
385  // ------------------- start watchdog timer
387  m_SendTime.SetNow();
388 
389  return bRet;
390 }
391 
392 //-----------------------------------------------
394 {
395  // repeat initialization
396 
397  // start network
398  CanMsg msg;
399  msg.m_iID = 0;
400  msg.m_iLen = 2;
401  msg.set(1,0,0,0,0,0,0,0);
402  m_pCanCtrl->transmitMsg(msg);
403 
404  // init and start
405  bool bRet = init();
406  bRet |= start();
407 
408  return bRet;
409 }
410 //-----------------------------------------------
412 {
413  std::cout << "shutdown drive " << m_DriveParam.getDriveIdent() << std::endl;
414 
415  IntprtSetInt(8, 'M', 'O', 0, 0);
416 
417  return true;
418 }
419 
420 //-----------------------------------------------
422 {
423  if (bStarted == true)
424  {
425  //save Watchdog state into member variable
426  m_bWatchdogActive = true;
427  // ------- init watchdog
428  // Harmonica checks PC hearbeat
429  // note: the COB-ID for a heartbeat message = 0x700 + Device ID
430 
431  const int c_iHeartbeatTimeMS = 1000;
432  const int c_iNMTNodeID = 0x00;
433 
434  // consumer (PC) heartbeat time
435  sendSDODownload(0x1016, 1, (c_iNMTNodeID << 16) | c_iHeartbeatTimeMS);
436 
437  // error behavior after failure: 0=pre-operational, 1=no state change, 2=stopped"
438  sendSDODownload(0x1029, 1, 2);
439 
440  // motor behavior after heartbeat failre: "quick stop"
441  sendSDODownload(0x6007, 0, 3);
442 
443  // acivate emergency events: "heartbeat event"
444  // Object 0x2F21 = "Emergency Events" which cause an Emergency Message
445  // Bit 3 is responsible for Heartbeart-Failure.--> Hex 0x08
446  sendSDODownload(0x2F21, 0, 0x08);
447  usleep(20000);
448 
449  }
450  else
451  {
452  //save Watchdog state into member variable
453  m_bWatchdogActive = false;
454 
455  //Motor action after Hearbeat-Error: No Action
456  sendSDODownload(0x6007, 0, 0);
457 
458  //Error Behavior: No state change
459  sendSDODownload(0x1029, 1, 1);
460 
461  // Deacivate emergency events: "heartbeat event"
462  // Object 0x2F21 = "Emergency Events" which cause an Emergency Message
463  // Bit 3 is responsible for Heartbeart-Failure.
464  sendSDODownload(0x2F21, 0, 0x00);
465  usleep(25000);
466 
467 
468  }
469 
470  return true;
471 }
472 
473 //-----------------------------------------------
475 {
476  return true;
477 }
478 
479 //-----------------------------------------------
481 {
483 
484  return m_CurrentTime - m_WatchdogTime;
485 }
486 //-----------------------------------------------
488 {
489  return m_bLimSwRight;
490 }
491 //-----------------------------------------------
493 {
494  const int c_iPosRef = m_DriveParam.getEncOffset();
495 
496  // 1. make sure that, if on elmo controller still a pending homing from a previous startup is running (in case of warm-start without switching of the whole robot), this old sequence is disabled
497  // disarm homing process
498  IntprtSetInt(8, 'H', 'M', 1, 0);
499 
500  // always give can and controller some time to understand the command
501  usleep(20000);
502 
503  /* THIS is needed for head_axis on cob3-2!
504 
505  //set input logic to 'general purpose'
506  IntprtSetInt(8, 'I', 'L', 2, 7);
507  usleep(20000);
508  */
509 
510  // 2. configure the homing sequence
511  // 2.a set the value to which the increment counter shall be reseted as soon as the homing event occurs
512  // value to load at homing event
513  IntprtSetInt(8, 'H', 'M', 2, c_iPosRef);
514  usleep(20000);
515 
516  // 2.b choose the chanel/switch on which the controller listens for a change or defined logic level (the homing event) (high/low/falling/rising)
517  // home event
518  // iHomeEvent = 5 : event according to defined FLS switch (for scara arm)
519  // iHomeEvent = 9 : event according to definded DIN1 switch (for full steerable wheels COb3)
520  // iHomeEvent =11 : event according to ?? (for COb3 Head-Axis)
521  IntprtSetInt(8, 'H', 'M', 3, m_DriveParam.getHomingDigIn());
522  //IntprtSetInt(8, 'H', 'M', 3, 11); //cob3-2
523  usleep(20000);
524 
525 
526  // 2.c choose the action that the controller shall perform after the homing event occured
527  // HM[4] = 0 : after Event stop immediately
528  // HM[4] = 2 : Do nothing!
529  IntprtSetInt(8, 'H', 'M', 4, 2);
530  usleep(20000);
531 
532  // 2.d choose the setting of the position counter (i.e. to the value defined in 2.a) after the homing event occured
533  // HM[5] = 0 : absolute setting of position counter: PX = HM[2]
534  IntprtSetInt(8, 'H', 'M', 5, 0);
535  usleep(20000);
536 
537  // 3. let the motor turn some time to give him the possibility to escape the approximation sensor if accidently in home position already at the beginning of the sequence (done in CanCtrlPltf...)
538 
539  return true;
540 }
541 
542 
543 //-----------------------------------------------
544 bool CanDriveHarmonica::execHoming() //not used by CanCtrlPltf, that has its own homing implementation
545 {
546 
547  int iCnt;
548  CanMsg Msg;
549  bool bRet = true;
550 
551  int iNrDrive = m_DriveParam.getDriveIdent();
552 
553  // 4. arm the homing process -> as soon as the approximation sensor is reached and the homing event occurs the commands set in 2. take effect
554  // arm homing process
555  IntprtSetInt(8, 'H', 'M', 1, 1);
556 
557  // 5. clear the can buffer to get rid of all uneccessary and potentially disturbing commands still floating through the wires
558  do
559  {
560  // read from can
561  bRet = m_pCanCtrl->receiveMsg(&Msg);
562  }
563  while(bRet == true);
564 
565  // 6. now listen for status of homing, to synchronize program flow -> proceed only after homing was succesful (homing disarmed by elmo) or timeout occured
566 
567  // set timeout counter to zero
568  iCnt = 0;
569 
570  do
571  {
572  // 6.a ask for status of homing process (armed/disarmed)
573  // ask for first byte in Homing Configuration
574  IntprtSetInt(4, 'H', 'M', 1, 0);
575 
576  // 6.b read message from can
577  m_pCanCtrl->receiveMsgRetry(&Msg, 10);
578 
579  // 6.c see if received message is answer of request and if so what is the status
580  if( (Msg.getAt(0) == 'H') && (Msg.getAt(1) == 'M') )
581  {
582  // status message (homing armed = 1 / disarmed = 0) is encoded in 5th byte
583  if(Msg.getAt(4) == 0)
584  {
585  // if 0 received: elmo disarmed homing after receiving the defined event
586  std::cout << "Got Homing-Signal " << std::endl;
587  m_bLimSwRight = true;
588  break;
589  }
590  }
591 
592  // increase count for timeout
593  usleep(10000);
594  iCnt++;
595 
596  }
597  while((m_bLimSwRight == false) && (iCnt<2000)); // wait some time
598 
599  // 7. see why finished (homed or timeout) and log out
600  if(iCnt>=2000)
601  {
602  std::cout << "Homing failed - limit switch " << iNrDrive << " not reached" << std::endl;
603  bRet = false;
604  }
605  else
606  {
607  std::cout << "Homing successful - limit switch " << iNrDrive << " ok" << std::endl;
608  bRet = true;
609  }
610  //IntprtSetInt(8, 'I', 'L', 2, 9); //cob3-2 | -----------------------------------------------------------------------------------
611  //usleep(20000);
612 
613  return bRet;
614 }
615 //-----------------------------------------------
616 void CanDriveHarmonica::setGearPosVelRadS(double dPosGearRad, double dVelGearRadS)
617 {
618  int iPosEncIncr;
619  int iVelEncIncrPeriod;
620 
621  m_DriveParam.PosVelRadToIncr(dPosGearRad, dVelGearRadS, &iPosEncIncr, &iVelEncIncrPeriod);
622 
623  if(iVelEncIncrPeriod > m_DriveParam.getVelMax())
624  {
625  iVelEncIncrPeriod = (int)m_DriveParam.getVelMax();
626  }
627 
628  if(iVelEncIncrPeriod < -m_DriveParam.getVelMax())
629  {
630  iVelEncIncrPeriod = (int)-m_DriveParam.getVelMax();
631  }
632 
634  {
635  //new: set VELOCITY for PTP Motion
636  IntprtSetInt(8, 'S', 'P', 0, iVelEncIncrPeriod);
637 
638  // Position Relativ ("PR") , because of positioning of driving wheel
639  // which is not initialized to zero on a specific position
640  // only when command is for homed steering wheel set absolute
641  if (m_DriveParam.getIsSteer() == true)
642  IntprtSetInt(8, 'P', 'A', 0, iPosEncIncr);
643  else
644  IntprtSetInt(8, 'P', 'R', 0, iPosEncIncr);
645 
646  IntprtSetInt(4, 'B', 'G', 0, 0);
647 
648  }
649 
651  {
652  iVelEncIncrPeriod *= m_DriveParam.getSign();
653  IntprtSetInt(8, 'J', 'V', 0, iVelEncIncrPeriod);
654  IntprtSetInt(4, 'B', 'G', 0, 0);
655  }
656 
657  // request pos and vel by TPDO1, triggered by SYNC msg
658  // (to request pos by SDO usesendSDOUpload(0x6064, 0) )
659  CanMsg msg;
660  msg.m_iID = 0x80;
661  msg.m_iLen = 0;
662  msg.set(0,0,0,0,0,0,0,0);
663  m_pCanCtrl->transmitMsg(msg);
664 }
665 
666 //-----------------------------------------------
667 void CanDriveHarmonica::setGearVelRadS(double dVelGearRadS)
668 {
669  int iVelEncIncrPeriod;
670 
671  // calc motor velocity from joint velocity
672  iVelEncIncrPeriod = m_DriveParam.getSign() * m_DriveParam.VelGearRadSToVelMotIncrPeriod(dVelGearRadS);
673 
674  if(iVelEncIncrPeriod > m_DriveParam.getVelMax())
675  {
676  std::cout << "SteerVelo asked for " << iVelEncIncrPeriod << " EncIncrements" << std::endl;
677  iVelEncIncrPeriod = (int)m_DriveParam.getVelMax();
678  }
679 
680  if(iVelEncIncrPeriod < -m_DriveParam.getVelMax())
681  {
682  std::cout << "SteerVelo asked for " << iVelEncIncrPeriod << " EncIncrements" << std::endl;
683  iVelEncIncrPeriod = -1 * (int)m_DriveParam.getVelMax();
684  }
685 
686  IntprtSetInt(8, 'J', 'V', 0, iVelEncIncrPeriod);
687  IntprtSetInt(4, 'B', 'G', 0, 0);
688 
689  // request pos and vel by TPDO1, triggered by SYNC msg
690  // (to request pos by SDO use sendSDOUpload(0x6064, 0) )
691  // sync msg is: iID 0x80 with msg (0,0,0,0,0,0,0,0)
692  CanMsg msg;
693  msg.m_iID = 0x80;
694  msg.m_iLen = 0;
695  msg.set(0,0,0,0,0,0,0,0);
696  m_pCanCtrl->transmitMsg(msg);
697 
698  // send heartbeat to keep watchdog inactive
699  msg.m_iID = 0x700;
700  msg.m_iLen = 5;
701  msg.set(0x00,0,0,0,0,0,0,0);
702  m_pCanCtrl->transmitMsg(msg);
703 
705  double dt = m_CurrentTime - m_SendTime;
706  if ((dt > 1.0) && m_bWatchdogActive)
707  {
708  std::cout << "Time between send velocity of motor " << m_DriveParam.getDriveIdent()
709  << " is too large: " << dt << " s" << std::endl;
710  }
711  m_SendTime.SetNow();
712 
713 
714  // request status
717  {
718  requestStatus();
719  m_iCountRequestDiv = 0;
720  }
721 }
722 
723 //-----------------------------------------------
724 void CanDriveHarmonica::getGearPosRad(double* dGearPosRad)
725 {
726  *dGearPosRad = m_dPosGearMeasRad;
727 }
728 
729 //-----------------------------------------------
730 void CanDriveHarmonica::getGearPosVelRadS(double* pdAngleGearRad, double* pdVelGearRadS)
731 {
732  *pdAngleGearRad = m_dPosGearMeasRad;
733  *pdVelGearRadS = m_dVelGearMeasRadS;
734 }
735 
736 //-----------------------------------------------
737 void CanDriveHarmonica::getGearDeltaPosVelRadS(double* pdAngleGearRad, double* pdVelGearRadS)
738 {
739  *pdAngleGearRad = m_dPosGearMeasRad - m_dAngleGearRadMem;
740  *pdVelGearRadS = m_dVelGearMeasRadS;
741  m_dAngleGearRadMem = m_dPosGearMeasRad;
742 }
743 
744 //-----------------------------------------------
745 void CanDriveHarmonica::getData(double* pdPosGearRad, double* pdVelGearRadS,
746  int* piTorqueCtrl, int* piStatusCtrl)
747 {
748  *pdPosGearRad = m_dPosGearMeasRad;
749  *pdVelGearRadS = m_dVelGearMeasRadS;
750  *piTorqueCtrl = m_iTorqueCtrl;
751  *piStatusCtrl = m_iStatusCtrl;
752 }
753 
754 //-----------------------------------------------
756 {
757  // request pos and vel by TPDO1, triggered by SYNC msg
758  CanMsg msg;
759  msg.m_iID = 0x80;
760  msg.m_iLen = 0;
761  msg.set(0,0,0,0,0,0,0,0);
762  m_pCanCtrl->transmitMsg(msg);
763  // (to request pos by SDO use sendSDOUpload(0x6064, 0) )
764 }
765 
766 //-----------------------------------------------
768 {
769  CanMsg msg;
770  msg.m_iID = 0x700;
771  msg.m_iLen = 5;
772  msg.set(0x00,0,0,0,0,0,0,0);
773  m_pCanCtrl->transmitMsg(msg);
774 }
775 
776 //-----------------------------------------------
778 {
779  IntprtSetInt(4, 'S', 'R', 0, 0);
780 }
781 
782 //-----------------------------------------------
784 {
785  // send command for requesting motor current:
786  IntprtSetInt(4, 'I', 'Q', 0, 0); // active current
787  //IntprtSetInt(4, 'I', 'D', 0, 0); // reactive current
788 }
789 
790 //-----------------------------------------------
792 {
794  {
795  // Check timeout of can communication
796  double dWatchTime = getTimeToLastMsg();
797 
798  if (dWatchTime>m_Param.dCanTimeout)
799  {
800  if ( m_bOutputOfFailure == false)
801  {
802  std::cout << "Motor " << m_DriveParam.getDriveIdent() <<
803  " has no can communication for " << dWatchTime << " s." << std::endl;
804  }
805 
808  }
809 
810  }
811 
812  return (m_iMotorState == ST_MOTOR_FAILURE);
813 }
814 //-----------------------------------------------
816 {
817  int iMaxAcc = int(m_DriveParam.getMaxAcc());
818  int iMaxDcc = int(m_DriveParam.getMaxDec());
819  CanMsg Msg;
820 
821  if (iType == MOTIONTYPE_POSCTRL)
822  {
823  // 1.) Switch to UnitMode = 5 (Single Loop Position Control) //
824 
825  // switch off Motor to change Unit-Mode
826  IntprtSetInt(8, 'M', 'O', 0, 0);
827  usleep(20000);
828  // switch Unit-Mode
829  IntprtSetInt(8, 'U', 'M', 0, 5);
830 
831  // set Target Radius to X Increments
832  IntprtSetInt(8, 'T', 'R', 1, 15);
833  // set Target Time to X ms
834  IntprtSetInt(8, 'T', 'R', 2, 100);
835 
836  // set maximum Acceleration to X Incr/s^2
837  IntprtSetInt(8, 'A', 'C', 0, iMaxAcc);
838  // set maximum decceleration to X Incr/s^2
839  IntprtSetInt(8, 'D', 'C', 0, iMaxDcc);
840  usleep(100000);
841 
842 
843  }
844  else if (iType == MOTIONTYPE_TORQUECTRL)
845  {
846  // Switch to TorqueControll-Mode
847  // switch off Motor to change Unit-Mode
848  IntprtSetInt(8, 'M', 'O', 0, 0);
849  usleep(50000);
850  // switch Unit-Mode 1: Torque Controlled
851  IntprtSetInt(8, 'U', 'M', 0, 1);
852  // disable external compensation input
853  // to avoid noise from that input pin
854  IntprtSetInt(8, 'R', 'M', 0, 0);
855 
856  // debugging:
857  std::cout << "Motor"<<m_DriveParam.getDriveIdent()<<" Unit Mode switched to: TORQUE controlled" << std::endl;
858  usleep(100000);
859  }
860  else
861  {
862  //Default Motion Type = VelocityControled
863  // switch off Motor to change Unit-Mode
864  IntprtSetInt(8, 'M', 'O', 0, 0);
865  // switch Unit-Mode
866  IntprtSetInt(8, 'U', 'M', 0, 2);
867  // set profiler Mode (only if Unit Mode = 2)
868  IntprtSetInt(8, 'P', 'M', 0, 1);
869 
870  // set maximum Acceleration to X Incr/s^2
871  IntprtSetInt(8, 'A', 'C', 0, iMaxAcc);
872  // set maximum decceleration to X Incr/s^2
873  IntprtSetInt(8, 'D', 'C', 0, iMaxDcc);
874  usleep(100000);
875  }
876 
877  m_iTypeMotion = iType;
878  return true;
879 }
880 
881 
882 //-----------------------------------------------
883 void CanDriveHarmonica::IntprtSetInt(int iDataLen, char cCmdChar1, char cCmdChar2, int iIndex, int iData)
884 {
885  char cIndex[2];
886  char cInt[4];
887  CanMsg CMsgTr;
888 
889  CMsgTr.m_iID = m_ParamCanOpen.iRxPDO2;
890  CMsgTr.m_iLen = iDataLen;
891 
892  cIndex[0] = iIndex;
893  cIndex[1] = (iIndex >> 8) & 0x3F; // The two MSB must be 0. Cf. DSP 301 Implementation guide p. 39.
894 
895  cInt[0] = iData;
896  cInt[1] = iData >> 8;
897  cInt[2] = iData >> 16;
898  cInt[3] = iData >> 24;
899 
900  CMsgTr.set(cCmdChar1, cCmdChar2, cIndex[0], cIndex[1], cInt[0], cInt[1], cInt[2], cInt[3]);
901  m_pCanCtrl->transmitMsg(CMsgTr);
902 }
903 
904 //-----------------------------------------------
905 void CanDriveHarmonica::IntprtSetFloat(int iDataLen, char cCmdChar1, char cCmdChar2, int iIndex, float fData)
906 {
907  char cIndex[2];
908  char cFloat[4];
909  CanMsg CMsgTr;
910  char* pTempFloat = NULL;
911 
912  CMsgTr.m_iID = m_ParamCanOpen.iRxPDO2;
913  CMsgTr.m_iLen = iDataLen;
914 
915  cIndex[0] = iIndex;
916  // for sending float values bit 6 has to be zero and bit 7 one (according to Elmo Implementation guide)
917  cIndex[1] = (iIndex >> 8) & 0x3F; // setting bit 6 to zero with mask 0b10111111->0xBF
918  cIndex[1] = cIndex[1] | 0x80; // setting bit 7 to one with mask 0b10000000 ->0x80
919 
920  pTempFloat = (char*)&fData;
921  for( int i=0; i<4; i++ )
922  cFloat[i] = pTempFloat[i];
923 
924  CMsgTr.set(cCmdChar1, cCmdChar2, cIndex[0], cIndex[1], cFloat[0], cFloat[1], cFloat[2], cFloat[3]);
925  m_pCanCtrl->transmitMsg(CMsgTr);
926 }
927 
928 //-----------------------------------------------
929 // SDO Communication Protocol, most functions are used for general SDO Segmented Transfer
930 //-----------------------------------------------
931 
932 //-----------------------------------------------
933 void CanDriveHarmonica::sendSDOAbort(int iObjIndex, int iObjSubIndex, unsigned int iErrorCode)
934 {
935  CanMsg CMsgTr;
936  const int ciAbortTransferReq = 0x04 << 5;
937 
938  CMsgTr.m_iLen = 8;
939  CMsgTr.m_iID = m_ParamCanOpen.iRxSDO;
940 
941  unsigned char cMsg[8];
942 
943  cMsg[0] = ciAbortTransferReq;
944  cMsg[1] = iObjIndex;
945  cMsg[2] = iObjIndex >> 8;
946  cMsg[3] = iObjSubIndex;
947  cMsg[4] = iErrorCode;
948  cMsg[5] = iErrorCode >> 8;
949  cMsg[6] = iErrorCode >> 16;
950  cMsg[7] = iErrorCode >> 24;
951 
952  CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
953  m_pCanCtrl->transmitMsg(CMsgTr);
954 }
955 
956 //-----------------------------------------------
957 void CanDriveHarmonica::receivedSDOTransferAbort(unsigned int iErrorCode){
958  std::cout << "SDO Abort Transfer received with error code: " << iErrorCode;
960 }
961 
962 //-----------------------------------------------
963 void CanDriveHarmonica::sendSDOUpload(int iObjIndex, int iObjSubIndex)
964 {
965  CanMsg CMsgTr;
966  const int ciInitUploadReq = 0x40;
967 
968  CMsgTr.m_iLen = 8;
969  CMsgTr.m_iID = m_ParamCanOpen.iRxSDO;
970 
971  unsigned char cMsg[8];
972 
973  cMsg[0] = ciInitUploadReq;
974  cMsg[1] = iObjIndex;
975  cMsg[2] = iObjIndex >> 8;
976  cMsg[3] = iObjSubIndex;
977  cMsg[4] = 0x00;
978  cMsg[5] = 0x00;
979  cMsg[6] = 0x00;
980  cMsg[7] = 0x00;
981 
982  CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
983  m_pCanCtrl->transmitMsg(CMsgTr);
984 }
985 
986 //-----------------------------------------------
987 void CanDriveHarmonica::sendSDODownload(int iObjIndex, int iObjSubIndex, int iData)
988 {
989  CanMsg CMsgTr;
990 
991  const int ciInitDownloadReq = 0x20;
992  const int ciNrBytesNoData = 0x00;
993  const int ciExpedited = 0x02;
994  const int ciDataSizeInd = 0x01;
995 
996  CMsgTr.m_iLen = 8;
997  CMsgTr.m_iID = m_ParamCanOpen.iRxSDO;
998 
999  unsigned char cMsg[8];
1000 
1001  cMsg[0] = ciInitDownloadReq | (ciNrBytesNoData << 2) | ciExpedited | ciDataSizeInd;
1002  cMsg[1] = iObjIndex;
1003  cMsg[2] = iObjIndex >> 8;
1004  cMsg[3] = iObjSubIndex;
1005  cMsg[4] = iData;
1006  cMsg[5] = iData >> 8;
1007  cMsg[6] = iData >> 16;
1008  cMsg[7] = iData >> 24;
1009 
1010  CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
1011  m_pCanCtrl->transmitMsg(CMsgTr);
1012 }
1013 
1014 //-----------------------------------------------
1015 void CanDriveHarmonica::evalSDO(CanMsg& CMsg, int* pIndex, int* pSubindex)
1016 {
1017  *pIndex = (CMsg.getAt(2) << 8) | CMsg.getAt(1);
1018  *pSubindex = CMsg.getAt(3);
1019 }
1020 
1021 //-----------------------------------------------
1023 {
1024  int iData = (CMsg.getAt(7) << 24) | (CMsg.getAt(6) << 16) |
1025  (CMsg.getAt(5) << 8) | CMsg.getAt(4);
1026 
1027  return iData;
1028 }
1029 
1030 //-----------------------------------------------
1032 
1033  if(seg_Data.statusFlag == segData::SDO_SEG_FREE || seg_Data.statusFlag == segData::SDO_SEG_WAITING) { //only accept new SDO Segmented Upload if seg_Data is free
1036 
1037  //read out objectIDs
1039 
1040  //data in byte 4 to 7 contain the number of bytes to be uploaded (if Size indicator flag is set)
1041  if( (msg.getAt(0) & 0x01) == 1) {
1042  seg_Data.numTotalBytes = msg.getAt(7) << 24 | msg.getAt(6) << 16 | msg.getAt(5) << 8 | msg.getAt(4);
1043  } else seg_Data.numTotalBytes = 0;
1044 
1046  }
1047 
1048  return 0;
1049 
1050 }
1051 
1052 //-----------------------------------------------
1054 
1055  int numEmptyBytes = 0;
1056 
1057  //Read SDO Upload Protocol:
1058  //Byte 0: SSS T NNN C | SSS=Cmd-Specifier, T=ToggleBit, NNN=num of empty bytes, C=Finished
1059  //Byte 1 to 7: Data
1060 
1061  if( (msg.getAt(0) & 0x10) != (seg_Data.toggleBit << 4) ) {
1062  std::cout << "Toggle Bit error, send Abort SDO with \"Toggle bit not alternated\" error" << std::endl;
1063  sendSDOAbort(seg_Data.objectID, seg_Data.objectSubID, 0x05030000); //Send SDO Abort with error code Toggle-Bit not alternated
1064  return 1;
1065  }
1066 
1067  if( (msg.getAt(0) & 0x01) == 0x00) { //Is finished-bit not set?
1069  } else {
1070  //std::cout << "SDO Segmented Transfer finished bit found!" << std::endl;
1072  };
1073 
1074  numEmptyBytes = (msg.getAt(0) >> 1) & 0x07;
1075  //std::cout << "NUM empty bytes in SDO :" << numEmptyBytes << std::endl;
1076 
1077  for(int i=1; i<=7-numEmptyBytes; i++) {
1078  seg_Data.data.push_back(msg.getAt(i));
1079  }
1080 
1083  } else {
1086  }
1087 
1088  return 0;
1089 }
1090 
1091 //-----------------------------------------------
1093 
1094  CanMsg CMsgTr;
1095  int iConfirmSegment = 0x60; //first three bits must be css = 3 : 011 00000
1096  iConfirmSegment = iConfirmSegment | (toggleBit << 4); //fourth bit is toggle bit: 011T0000
1097 
1098  CMsgTr.m_iLen = 8;
1099  CMsgTr.m_iID = m_ParamCanOpen.iRxSDO;
1100 
1101  unsigned char cMsg[8];
1102 
1103  cMsg[0] = iConfirmSegment;
1104  cMsg[1] = 0x00;
1105  cMsg[2] = 0x00;
1106  cMsg[3] = 0x00;
1107  cMsg[4] = 0x00;
1108  cMsg[5] = 0x00;
1109  cMsg[6] = 0x00;
1110  cMsg[7] = 0x00;
1111 
1112  CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
1113  m_pCanCtrl->transmitMsg(CMsgTr);
1114 }
1115 
1116 //-----------------------------------------------
1119 
1120  if( (seg_Data.data.size() != seg_Data.numTotalBytes) & (seg_Data.numTotalBytes != 0) ) {
1121  std::cout << "WARNING: SDO tranfer finished but number of collected bytes "
1122  << seg_Data.data.size() << " != expected number of bytes: " << seg_Data.numTotalBytes << std::endl;
1123  //abort processing?
1124  }
1125 
1126  if(seg_Data.objectID == 0x2030) {
1128  }
1129 }
1130 
1131 //-----------------------------------------------
1132 double CanDriveHarmonica::estimVel(double dPos)
1133 {
1134  double dVel;
1135  double dt;
1136 
1138 
1140 
1141  dVel = (dPos - m_dOldPos)/dt;
1142 
1143  m_dOldPos = dPos;
1144  m_VelCalcTime.SetNow();
1145 
1146  return dVel;
1147 }
1148 //-----------------------------------------------
1150 {
1151  bool bNoError;
1152 
1153  // --------- Error status
1154  if( isBitSet(iStatus, 0) )
1155  {
1156  // ------------ Error
1157  if ( m_bOutputOfFailure == false )
1158  {
1159  std::cout << "Error of drive: " << m_DriveParam.getDriveIdent() << std::endl;
1160 
1161  if( (iStatus & 0x0000000E) == 2)
1162  std::cout << "- drive error under voltage" << std::endl;
1163 
1164  if( (iStatus & 0x0000000E) == 4)
1165  std::cout << "- drive error over voltage" << std::endl;
1166 
1167  if( (iStatus & 0x0000000E) == 10)
1168  std::cout << "- drive error short circuit" << std::endl;
1169 
1170  if( (iStatus & 0x0000000E) == 12)
1171  std::cout << "- drive error overheating" << std::endl;
1172 
1173  // Request detailed description of failure
1174  IntprtSetInt(4, 'M', 'F', 0, 0);
1175  }
1176 
1178 
1179  bNoError = false;
1180  }
1181  else if ( isBitSet(iStatus, 6) )
1182  {
1183  // General failure
1184  if ( m_bOutputOfFailure == false )
1185  {
1186  std::cout << "Motor " << m_DriveParam.getDriveIdent() << " failure latched" << std::endl;
1187 
1188  // Request detailed description of failure
1189  IntprtSetInt(4, 'M', 'F', 0, 0);
1190 
1192  }
1194 
1195  bNoError = false;
1196  }
1197  else
1198  {
1199  // ---------- No error
1200  bNoError = true;
1201 
1202  // Clear flag for failure output only if at least one
1203  // status message without error has been received.
1204  // Printing an error message on recovery is avoided.
1205  m_bOutputOfFailure = false;
1206 
1207  // --------- General status bits
1208  // check if Bit 4 (-> Motor is ON) ist set
1209  if( isBitSet(iStatus, 4) )
1210  {
1212  {
1213  std::cout << "Motor " << m_DriveParam.getDriveIdent() << " operation enabled" << std::endl;
1215  }
1216 
1218  }
1219  else
1220  {
1222  {
1223  std::cout << "Motor " << m_DriveParam.getDriveIdent() << " operation disabled" << std::endl;
1224  }
1225 
1227  }
1228 
1229  // Current limit
1230  if( isBitSet(iStatus, 13) )
1231  {
1232  if (m_bCurrentLimitOn == false)
1233  std::cout << "Motor " << m_DriveParam.getDriveIdent() << "current limit on" << std::endl;
1234 
1235  m_bCurrentLimitOn = true;
1236  }
1237  else
1238  m_bCurrentLimitOn = false;
1239  }
1240 
1241  // Change state
1243 
1245  m_bOutputOfFailure = true;
1246 
1247  return bNoError;
1248 }
1249 
1250 //-----------------------------------------------
1252 {
1253 
1254  std::cout << "Motor " << m_DriveParam.getDriveIdent() << " has a failure: " << iFailure << std::endl;
1255 
1256  if( isBitSet(iFailure, 2) )
1257  {
1258  std::cout << "- feedback loss" << std::endl;
1259  }
1260 
1261  if( isBitSet(iFailure, 3) )
1262  {
1263  std::cout << "- peak current excced" << std::endl;
1264  }
1265 
1266  if( isBitSet(iFailure, 7) )
1267  {
1268  std::cout << "- speed track error" << std::endl;
1269  }
1270 
1271  if( isBitSet(iFailure, 8) )
1272  {
1273  std::cout << "- position track error" << std::endl;
1274  }
1275 
1276  if( isBitSet(iFailure, 17) )
1277  {
1278  std::cout << "- speed limit exceeded" << std::endl;
1279  }
1280 
1281  if( isBitSet(iFailure, 21) )
1282  {
1283  std::cout << "- motor stuck" << std::endl;
1284  }
1285 }
1286 
1287 //-----------------------------------------------
1289 {
1290  // convert commanded motor current into amperes
1291  float fMotCurr = m_DriveParam.getSign() * dTorqueNm / m_DriveParam.getCurrToTorque();
1292 
1293  // check for limitations
1294  if (fMotCurr > m_DriveParam.getCurrMax())
1295  {
1296  fMotCurr = m_DriveParam.getCurrMax();
1297  std::cout << "Torque command too high: " << fMotCurr << " Nm. Torque has been limitited." << std::endl;
1298  }
1299  if (fMotCurr < -m_DriveParam.getCurrMax())
1300  {
1301  fMotCurr = -m_DriveParam.getCurrMax();
1302  std::cout << "Torque command too high: " << fMotCurr << " Nm. Torque has been limitited." << std::endl;
1303  }
1304 
1305  // send Command
1306  IntprtSetFloat(8, 'T', 'C', 0, fMotCurr);
1307 
1308  // request pos and vel by TPDO1, triggered by SYNC msg
1309  CanMsg msg;
1310  msg.m_iID = 0x80;
1311  msg.m_iLen = 0;
1312  msg.set(0,0,0,0,0,0,0,0);
1313  m_pCanCtrl->transmitMsg(msg);
1314 
1315  // send heartbeat to keep watchdog inactive
1316  sendHeartbeat();
1317 
1319  double dt = m_CurrentTime - m_SendTime;
1320  if (dt > 1.0)
1321  {
1322  std::cout << "Time between send current/torque of motor " << m_DriveParam.getDriveIdent()
1323  << " is too large: " << dt << " s" << std::endl;
1324  }
1325  m_SendTime.SetNow();
1326 
1327 
1328  // request status
1331  {
1332  requestStatus();
1333  m_iCountRequestDiv = 0;
1334  }
1335 
1336 }
1337 
1338 //-----------------------------------------------
1339 void CanDriveHarmonica::getMotorTorque(double* dTorqueNm)
1340 {
1341  // With motor sign:
1343 
1344 }
1345 
1346 
1347 
1348 //----------------
1349 //----------------
1350 //Function, that proceeds (Elmo-) recorder readout
1351 
1352 //-----------------------------------------------
1353 int CanDriveHarmonica::setRecorder(int iFlag, int iParam, std::string sParam) {
1354 
1355  switch(iFlag) {
1356  case 0: //Configure Elmo Recorder for new Record, param = iRecordingGap, which specifies every which time quantum (4*90usec) a new data point is recorded
1357  if(iParam < 1) iParam = 1;
1358  ElmoRec->isInitialized(true);
1359  ElmoRec->configureElmoRecorder(iParam, m_DriveParam.getDriveIdent()); //int startImmediately is default = 1
1360  return 0;
1361 
1362  case 1: //Query upload of previous recorded data, data is being proceeded after complete upload, param = recorded ID, filename
1363  if(!ElmoRec->isInitialized(false)) return 1;
1364 
1366  if( (iParam != 1) && (iParam != 2) && (iParam != 10) && (iParam != 16) ) {
1367  iParam = 1;
1368  std::cout << "Changed the Readout object to #1 as your selected object hasn't been recorded!" << std::endl;
1369  }
1370  ElmoRec->setLogFilename(sParam);
1372  ElmoRec->readoutRecorderTry(iParam); //as subindex, give the recorded variable
1373  return 0;
1374  } else {
1375  std::cout << "Previous transmission not finished or colected data hasn't been proceeded yet" << std::endl;
1376  return 2;
1377  }
1378 
1379  break;
1380 
1381  case 2: //request status, still collecting data during ReadOut process?
1383  //std::cout << "Transmission of data is still in progress" << std::endl;
1384  return 2;
1386  //std::cout << "Transmission of data finished, data not proceeded yet" << std::endl;
1387  return 2;
1389  //std::cout << "Still waiting for transmission to begin" << std::endl;
1390  return 2;
1391  } else { //finished transmission and finished proceeding
1392  return 0;
1393  }
1394 
1395  break;
1396 
1397  case 99: //Abort ongoing SDO data Transmission and clear collected data
1398  sendSDOAbort(0x2030, 0x00, 0x08000020); //send general error abort
1400  return 0;
1401  }
1402 
1403  return 0;
1404 }
double getCurrToTorque()
Definition: DriveParam.h:361
int objectID
Definition: SDOSegmented.h:76
void resetTransferData()
Definition: SDOSegmented.h:53
bool isInitialized(bool initNow)
std::vector< unsigned char > data
Definition: SDOSegmented.h:96
void receivedSDOTransferAbort(unsigned int iErrorCode)
bool evalStatusRegister(int iStatus)
void evalSDO(CanMsg &CMsg, int *pIndex, int *pSubindex)
int getDriveIdent()
Definition: DriveParam.h:187
bool getIsSteer()
Definition: DriveParam.h:346
int getEncOffset()
Definition: DriveParam.h:337
void getMotorTorque(double *dTorqueNm)
bool toggleBit
Definition: SDOSegmented.h:86
int objectSubID
Definition: SDOSegmented.h:81
double getGearRatio()
Definition: DriveParam.h:320
double estimVel(double dPos)
int processData(segData &SDOData)
bool isBitSet(int iVal, int iNrBit)
double getVelMax()
Definition: DriveParam.h:203
void evalMotorFailure(int iFailure)
int getEncIncrPerRevMot()
Definition: DriveParam.h:354
ElmoRecorder * ElmoRec
int setRecorder(int iFlag, int iParam=0, std::string sParam="/home/MyLog_")
int m_iLen
bool disableBrake(bool bDisabled)
void sendSDODownload(int iObjIndex, int iObjSub, int iData)
void SetNow()
int VelGearRadSToVelMotIncrPeriod(double dVelGearRadS)
Conversions of gear velocity in rad/s to encoder increments per measurment period.
Definition: DriveParam.h:251
void setGearVelRadS(double dVelEncRadS)
void setCanOpenParam(int iTxPDO1, int iTxPDO2, int iRxPDO2, int iTxSDO, int iRxSDO)
unsigned int numTotalBytes
Definition: SDOSegmented.h:91
void getGearPosVelRadS(double *pdAngleGearRad, double *pdVelGearRadS)
void setGearPosVelRadS(double dPosRad, double dVelRadS)
void getGearDeltaPosVelRadS(double *pdDeltaAngleGearRad, double *pdVelGearRadS)
void IntprtSetFloat(int iDataLen, char cCmdChar1, char cCmdChar2, int iIndex, float fData)
ParamCanOpenType m_ParamCanOpen
int receivedSDODataSegment(CanMsg &msg)
void sendSDOUploadSegmentConfirmation(bool toggleBit)
int configureElmoRecorder(int iRecordingGap, int driveID, int startImmediately=1)
int readoutRecorderTryStatus(int iStatusReg, segData &SDOData)
void IntprtSetInt(int iDataLen, char cCmdChar1, char cCmdChar2, int iIndex, int iData)
int setLogFilename(std::string sLogFileprefix)
double PosMotIncrToPosGearRad(int iPosIncr)
Conversions of encoder increments to gear position in radians.
Definition: DriveParam.h:245
int receivedSDOSegmentedInitiation(CanMsg &msg)
virtual bool receiveMsg(CanMsg *pCMsg)=0
virtual bool receiveMsgRetry(CanMsg *pCMsg, int iNrOfRetry)=0
void sendSDOUpload(int iObjIndex, int iObjSub)
double getCurrMax()
Definition: DriveParam.h:368
int m_iID
void set(BYTE Data0=0, BYTE Data1=0, BYTE Data2=0, BYTE Data3=0, BYTE Data4=0, BYTE Data5=0, BYTE Data6=0, BYTE Data7=0)
void sendSDOAbort(int iObjIndex, int iObjSubIndex, unsigned int iErrorCode)
double getMaxAcc()
Definition: DriveParam.h:275
void getData(double *pdPosGearRad, double *pdVelGearRadS, int *piTorqueCtrl, int *piStatusCtrl)
int getSDODataInt32(CanMsg &CMsg)
void getGearPosRad(double *pdPosGearRad)
int statusFlag
Definition: SDOSegmented.h:71
double getMaxDec()
Definition: DriveParam.h:293
double getBeltRatio()
Definition: DriveParam.h:328
TimeStamp m_FailureStartTime
void PosVelRadToIncr(double dPosRad, double dVelRadS, int *piPosIncr, int *piVelIncrPeriod)
Definition: DriveParam.h:215
int getHomingDigIn()
Definition: DriveParam.h:375
bool setTypeMotion(int iType)
int getSign()
Definition: DriveParam.h:195
int readoutRecorderTry(int iObjSubIndex)
bool startWatchdog(bool bStarted)
virtual bool transmitMsg(CanMsg CMsg, bool bBlocking=true)=0
int getAt(int iNr)
void setMotorTorque(double dTorqueNm)


cob_canopen_motor
Author(s): Christian Connette
autogenerated on Wed Apr 7 2021 02:11:53