00001
00060 #include <ipa_canopen_core/canopen.h>
00061 #include <sstream>
00062 #include <cstring>
00063 #include <unordered_map>
00064
00065 namespace canopen
00066 {
00067
00068
00069
00070
00071 bool sdo_protect=false;
00072 BYTE protect_msg[8];
00073
00074 std::chrono::milliseconds syncInterval;
00075 std::string baudRate;
00076 std::map<uint8_t, Device> devices;
00077 std::map<std::string, DeviceGroup> deviceGroups;
00078 HANDLE h;
00079 std::map<SDOkey, std::function<void (uint8_t CANid, BYTE data[8])> > incomingDataHandlers { { STATUSWORD, sdo_incoming }, { DRIVERTEMPERATURE, sdo_incoming }, { MODES_OF_OPERATION_DISPLAY, sdo_incoming } };
00080 std::map<SDOkey, std::function<void (uint8_t CANid, BYTE data[8])> > incomingErrorHandlers { { ERRORWORD, errorword_incoming }, { MANUFACTURER, errorword_incoming } };
00081 std::map<SDOkey, std::function<void (uint8_t CANid, BYTE data[8])> > incomingManufacturerDetails { {MANUFACTURERHWVERSION, manufacturer_incoming}, {MANUFACTURERDEVICENAME, manufacturer_incoming}, {MANUFACTURERSOFTWAREVERSION, manufacturer_incoming} };
00082 std::map<uint16_t, std::function<void (const TPCANRdMsg m)> > incomingPDOHandlers;
00083 std::map<uint16_t, std::function<void (const TPCANRdMsg m)> > incomingEMCYHandlers;
00084 bool recover_active;
00085 bool halt_active;
00086
00087 bool halt_positive;
00088 bool halt_negative;
00089
00090 bool use_limit_switch=false;
00091
00092 uint8_t operation_mode;
00093 std::string operation_mode_param;
00094
00095 std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
00096
00097 std::chrono::duration<double> elapsed_seconds;
00098
00099
00100
00101
00102
00103
00104 bool atFirstInit = true;
00105
00106 bool openConnection(std::string devName, std::string baudrate)
00107 {
00108 h = LINUX_CAN_Open(devName.c_str(), O_RDWR);
00109 if (!h)
00110 return false;
00111
00112 errno = CAN_Init(h, baudrates[baudrate], CAN_INIT_TYPE_ST);
00113
00114 return true;
00115 }
00116
00117 void pre_init()
00118 {
00119
00120 for (auto device : (canopen::devices))
00121 {
00122
00123
00124 getErrors(device.second.getCANid());
00125
00126
00127
00128
00129 readManErrReg(device.second.getCANid());
00130
00131
00132
00133
00134 canopen::uploadSDO(device.second.getCANid(), MANUFACTURERDEVICENAME);
00135 }
00136 }
00137
00138 bool init(std::string deviceFile, std::chrono::milliseconds syncInterval)
00139 {
00140
00141 if(atFirstInit)
00142 {
00143 atFirstInit = false;
00144
00145 CAN_Close(h);
00146
00147 canopen::initDeviceManagerThread(canopen::deviceManager);
00148 std::this_thread::sleep_for(std::chrono::milliseconds(100));
00149
00150 bool connection_success;
00151 connection_success = canopen::openConnection(deviceFile, canopen::baudRate);
00152
00153 if (!connection_success)
00154 {
00155 std::cout << "Cannot open CAN device; aborting." << std::endl;
00156 exit(EXIT_FAILURE);
00157 }
00158 else
00159 {
00160
00161 canopen::initListenerThread(canopen::defaultListener);
00162
00163 canopen::pre_init();
00164
00165 while(sdo_protect)
00166 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00167
00168 std::cout << "Resetting devices " << std::endl;
00169 canopen::sendNMT(0x00, canopen::NMT_RESET_NODE);
00170
00171 for(auto device : devices)
00172 {
00173 bool nmt_init = devices[device.second.getCANid()].getNMTInit();
00174 std::cout << "Waiting for Node: " << (uint16_t)device.second.getCANid() << " to become available" << std::endl;
00175
00176 while(!nmt_init)
00177 {
00178 std::this_thread::sleep_for(std::chrono::milliseconds(1));
00179 nmt_init = devices[device.second.getCANid()].getNMTInit();
00180 }
00181 std::cout << "Node: " << (uint16_t)device.second.getCANid() << " is now available" << std::endl;
00182 }
00183
00184 canopen::sendNMT(0x00, canopen::NMT_START_REMOTE_NODE);
00185 std::this_thread::sleep_for(std::chrono::milliseconds(100));
00186 }
00187
00188 for (auto device : devices)
00189 {
00190
00191 std::cout << "Initialized the PDO mapping for Node:" << (uint16_t)device.second.getCANid() << std::endl;
00192
00193 for(int pdo_object=0; pdo_object<=3; pdo_object++)
00194 {
00195 canopen::disableTPDO(pdo_object);
00196 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00197
00198 canopen::clearTPDOMapping(pdo_object);
00199 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00200
00201 canopen::disableRPDO(pdo_object);
00202 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00203
00204 canopen::clearRPDOMapping(pdo_object);
00205 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00206 }
00207
00208
00209 if(canopen::use_limit_switch)
00210 {
00211
00212 std::vector<std::string> tpdo1_registers {"604100", "60FD00"};
00213 std::vector<int> tpdo1_sizes {0x10,0x20};
00214
00215 canopen::makeTPDOMapping(0,tpdo1_registers, tpdo1_sizes, u_int8_t(0xFF));
00216 }
00217 else
00218 {
00219 std::vector<std::string> tpdo1_registers {"604100", "606100"};
00220 std::vector<int> tpdo1_sizes {0x10,0x08};
00221
00222 canopen::makeTPDOMapping(0,tpdo1_registers, tpdo1_sizes, u_int8_t(0xFF));
00223
00224 }
00225 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00226
00227 std::vector<std::string> tpdo4_registers {"606400", "606C00"};
00228 std::vector<int> tpdo4_sizes {0x20,0x20};
00229
00230 canopen::makeTPDOMapping(3, tpdo4_registers, tpdo4_sizes, u_int8_t(0x01));
00231 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00232
00233 std::vector<std::string> rpdo1_registers {"604000"};
00234 std::vector<int> rpdo1_sizes {0x10};
00235
00236 std::vector<std::string> rpdo2_registers {"60C101"};
00237 std::vector<int> rpdo2_sizes {0x20};
00238
00239 canopen::makeRPDOMapping(0, rpdo1_registers, rpdo1_sizes, u_int8_t(0xFF));
00240 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00241 canopen::makeRPDOMapping(1, rpdo2_registers, rpdo2_sizes, u_int8_t(0x01));
00242 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00243
00244 for(int pdo_object=0; pdo_object<=3; pdo_object++)
00245 {
00246 canopen::enableTPDO(pdo_object);
00247 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00248
00249 canopen::enableRPDO(pdo_object);
00250 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00251 }
00252
00253 std::this_thread::sleep_for(std::chrono::milliseconds(20));
00254
00255 }
00256 }
00257
00258 recover_active = false;
00259 canopen::setObjects();
00260
00261
00262 for (auto device : devices)
00263 {
00264 canopen::sendSync();
00265 if(device.second.getMotorState() == MS_OPERATION_ENABLED)
00266 {
00267 std::cout << "Node" << (uint16_t)device.second.getCANid() << "is already operational" << std::endl;
00268 }
00269 else
00270 {
00271 canopen::sendSDO(device.second.getCANid(), canopen::MODES_OF_OPERATION, canopen::MODES_OF_OPERATION_INTERPOLATED_POSITION_MODE);
00272 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00273
00274 canopen::setMotorState((uint16_t)device.second.getCANid(), canopen::MS_SWITCHED_ON_DISABLED);
00275 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00276
00277 canopen::setMotorState((uint16_t)device.second.getCANid(), canopen::MS_READY_TO_SWITCH_ON);
00278 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00279
00280 canopen::setMotorState((uint16_t)device.second.getCANid(), canopen::MS_SWITCHED_ON);
00281 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00282
00283 canopen::setMotorState((uint16_t)device.second.getCANid(), canopen::MS_OPERATION_ENABLED);
00284 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00285
00286 sendSDO((uint16_t)device.second.getCANid(), canopen::IP_TIME_UNITS, (uint8_t) syncInterval.count() );
00287 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00288 sendSDO((uint16_t)device.second.getCANid(), canopen::IP_TIME_INDEX, (uint8_t)canopen::IP_TIME_INDEX_MILLISECONDS);
00289 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00290 sendSDO((uint16_t)device.second.getCANid(), canopen::SYNC_TIMEOUT_FACTOR, (uint8_t)canopen::SYNC_TIMEOUT_FACTOR_DISABLE_TIMEOUT);
00291 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00292
00293
00294 canopen::controlPDO(device.second.getCANid(), canopen::CONTROLWORD_ENABLE_MOVEMENT, 0x00);
00295 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00296
00297
00298 canopen::devices[device.second.getCANid()].setDesiredPos((double)device.second.getActualPos());
00299 canopen::devices[device.second.getCANid()].setDesiredVel(0);
00300
00301 sendPos((uint16_t)device.second.getCANid(), (double)device.second.getDesiredPos());
00302
00303 canopen::uploadSDO(device.second.getCANid(), canopen::STATUSWORD);
00304 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00305 canopen::uploadSDO(device.second.getCANid(), DRIVERTEMPERATURE);
00306 canopen::uploadSDO(device.second.getCANid(), MODES_OF_OPERATION_DISPLAY);
00307
00308 }
00309
00310 }
00311
00312 for (auto device : devices)
00313 {
00314 getErrors(device.second.getCANid());
00315 readManErrReg(device.second.getCANid());
00316 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00317
00318 if(device.second.getIPMode())
00319 {
00320 std::cout << "Concluded driver side init succesfully for Node" << (uint16_t)device.second.getCANid() << std::endl;
00321 canopen::devices[device.second.getCANid()].setInitialized(true);
00322 }
00323 else
00324 {
00325 std::cout << "Problems occured during driver side init for Node" << (uint16_t)device.second.getCANid() << std::endl;
00326 canopen::devices[device.second.getCANid()].setInitialized(false);
00327 return false;
00328 }
00329
00330 }
00331
00332 return true;
00333
00334 }
00335
00336
00337 bool recover(std::string deviceFile, std::chrono::milliseconds syncInterval)
00338 {
00339
00340 recover_active = true;
00341
00342 for (auto device : devices)
00343 {
00344
00345 if(device.second.getIPMode())
00346 {
00347 std::cout << "Node" << device.second.getCANid() << "is already operational" << std::endl;
00348 }
00349 else
00350 {
00351
00352 canopen::controlPDO(device.second.getCANid(),canopen::CONTROLWORD_HALT, 0x00);
00353 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00354
00355 canopen::controlPDO(device.second.getCANid(),canopen::CONTROLWORD_DISABLE_INTERPOLATED, 0x00);
00356 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00357
00358 canopen::controlPDO(device.second.getCANid(),canopen::CONTROL_WORD_DISABLE_VOLTAGE, 0x00);
00359 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00360
00361 canopen::controlPDO(device.second.getCANid(),canopen::CONTROLWORD_QUICKSTOP, 0x00);
00362 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00363
00364 canopen::sendSDO(device.second.getCANid(), canopen::MODES_OF_OPERATION, canopen::MODES_OF_OPERATION_INTERPOLATED_POSITION_MODE);
00365 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00366
00367 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00368
00369 canopen::setMotorState(device.second.getCANid(), canopen::MS_SWITCHED_ON_DISABLED);
00370 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00371
00372 canopen::setMotorState(device.second.getCANid(), canopen::MS_READY_TO_SWITCH_ON);
00373 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00374
00375 canopen::setMotorState(device.second.getCANid(), canopen::MS_SWITCHED_ON);
00376 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00377
00378 canopen::setMotorState(device.second.getCANid(), canopen::MS_OPERATION_ENABLED);
00379 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00380
00381 sendSDO((uint16_t)device.second.getCANid(), canopen::IP_TIME_UNITS, (uint8_t) syncInterval.count() );
00382 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00383 sendSDO((uint16_t)device.second.getCANid(), canopen::IP_TIME_INDEX, (uint8_t)canopen::IP_TIME_INDEX_MILLISECONDS);
00384 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00385 sendSDO((uint16_t)device.second.getCANid(), canopen::SYNC_TIMEOUT_FACTOR, (uint8_t)canopen::SYNC_TIMEOUT_FACTOR_DISABLE_TIMEOUT);
00386 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00387
00388 canopen::controlPDO(device.second.getCANid(), canopen::CONTROLWORD_ENABLE_MOVEMENT, 0x00);
00389 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00390
00391 canopen::uploadSDO(device.second.getCANid(), canopen::STATUSWORD);
00392 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00393 canopen::uploadSDO(device.second.getCANid(), DRIVERTEMPERATURE);
00394 canopen::uploadSDO(device.second.getCANid(), MODES_OF_OPERATION_DISPLAY);
00395
00396 getErrors(device.second.getCANid());
00397 }
00398
00399
00400 devices[device.second.getCANid()].setDesiredPos((double)device.second.getActualPos());
00401 devices[device.second.getCANid()].setDesiredVel(0);
00402
00403 }
00404 recover_active = false;
00405
00406 for (auto device : devices)
00407 {
00408
00409 if(device.second.getIPMode())
00410 {
00411 std::cout << "Concluded driver side recover succesfully" << std::endl;
00412 }
00413 else
00414 {
00415 std::cout << "Problems occured during driver side recover" << std::endl;
00416 return false;
00417 }
00418 }
00419
00420 return true;
00421
00422 }
00423
00424
00425
00426 void halt(std::string deviceFile, std::chrono::milliseconds syncInterval)
00427 {
00428 CAN_Close(h);
00429
00430 NMTmsg.ID = 0;
00431 NMTmsg.MSGTYPE = 0x00;
00432 NMTmsg.LEN = 2;
00433
00434 syncMsg.ID = 0x80;
00435 syncMsg.MSGTYPE = 0x00;
00436
00437 syncMsg.LEN = 0x00;
00438
00439 if (!canopen::openConnection(deviceFile, canopen::baudRate))
00440 {
00441 std::cout << "Cannot open CAN device; aborting." << std::endl;
00442 exit(EXIT_FAILURE);
00443 }
00444 else
00445 {
00446
00447 }
00448
00449
00450 for (auto device : devices)
00451 {
00452
00453 }
00454
00455 for (auto device : devices)
00456 {
00457
00458
00459 canopen::sendSDO(device.second.getCANid(), canopen::CONTROLWORD, canopen:: CONTROLWORD_HALT);
00460
00461 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00462
00463 canopen::sendSDO(device.second.getCANid(), canopen::CONTROLWORD, canopen:: CONTROLWORD_DISABLE_INTERPOLATED);
00464
00465 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00466
00467 canopen::sendSDO(device.second.getCANid(), canopen::CONTROLWORD, canopen:: CONTROL_WORD_DISABLE_VOLTAGE);
00468
00469 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00470
00471 canopen::sendSDO(device.second.getCANid(), canopen::CONTROLWORD, canopen::CONTROLWORD_QUICKSTOP);
00472 canopen::uploadSDO(device.second.getCANid(), canopen::STATUSWORD);
00473 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00474
00475 }
00476 }
00477
00478
00479
00480
00481
00482 void setNMTState(uint16_t CANid, std::string targetState)
00483 {
00484
00485 }
00486
00487 void setMotorState(uint16_t CANid, std::string targetState)
00488 {
00489
00490 start = std::chrono::high_resolution_clock::now();
00491
00492 while (devices[CANid].getMotorState() != targetState)
00493 {
00494 end = std::chrono::high_resolution_clock::now();
00495 std::chrono::duration<double> elapsed_seconds = end-start;
00496
00497 if(elapsed_seconds.count() > 3)
00498 return;
00499 canopen::uploadSDO(CANid, canopen::STATUSWORD);
00500 if (devices[CANid].getMotorState() == MS_FAULT)
00501 {
00502 canopen::uploadSDO(CANid, canopen::STATUSWORD);
00503 std::this_thread::sleep_for(std::chrono::milliseconds(50));
00504
00505 if(!devices[CANid].getFault())
00506 {
00507 canopen::controlPDO(CANid, canopen::CONTROLWORD_FAULT_RESET_0, 0x00);
00508 }
00509 else
00510 {
00511
00512 canopen::controlPDO(CANid, canopen::CONTROLWORD_FAULT_RESET_1, 0x00);
00513 }
00514
00515 }
00516
00517 if (devices[CANid].getMotorState() == MS_NOT_READY_TO_SWITCH_ON)
00518 {
00519 canopen::uploadSDO(CANid, canopen::STATUSWORD);
00520 canopen::controlPDO(CANid, canopen::CONTROLWORD_SHUTDOWN, 0x00);
00521 }
00522
00523 if (devices[CANid].getMotorState() == MS_SWITCHED_ON_DISABLED)
00524 {
00525
00526 canopen::controlPDO(CANid, canopen::CONTROLWORD_SHUTDOWN, 0x00);
00527 }
00528
00529 if (devices[CANid].getMotorState() == MS_READY_TO_SWITCH_ON)
00530 {
00531 if (targetState == MS_SWITCHED_ON_DISABLED){
00532 canopen::controlPDO(CANid, canopen::CONTROL_WORD_DISABLE_VOLTAGE, 0x00);
00533 }
00534 else
00535 {
00536 canopen::controlPDO(CANid, canopen::CONTROLWORD_SWITCH_ON, 0x00);
00537 }
00538 }
00539
00540 if (devices[CANid].getMotorState() == MS_SWITCHED_ON)
00541 {
00542 if (targetState == MS_SWITCHED_ON_DISABLED)
00543 {
00544 canopen::controlPDO(CANid, canopen::CONTROL_WORD_DISABLE_VOLTAGE, 0x00);
00545 }
00546 else if (targetState == MS_READY_TO_SWITCH_ON)
00547 {
00548 canopen::controlPDO(CANid, canopen::CONTROLWORD_SHUTDOWN, 0x00);
00549 }
00550 else{
00551
00552 canopen::controlPDO(CANid, canopen::CONTROLWORD_ENABLE_OPERATION, 0x00);
00553 }
00554 }
00555
00556 if (devices[CANid].getMotorState() == MS_OPERATION_ENABLED)
00557 {
00558 if (targetState == MS_SWITCHED_ON_DISABLED)
00559 {
00560 canopen::sendSDO(CANid, canopen::CONTROLWORD, canopen::CONTROL_WORD_DISABLE_VOLTAGE);
00561 }
00562 else if (targetState == MS_READY_TO_SWITCH_ON)
00563 {
00564 canopen::sendSDO(CANid, canopen::CONTROLWORD, canopen::CONTROLWORD_SHUTDOWN);
00565 }
00566 else
00567 {
00568 canopen::sendSDO(CANid, canopen::CONTROLWORD, canopen::CONTROLWORD_DISABLE_OPERATION);
00569 }
00570 }
00571
00572 }
00573 }
00574
00575
00576
00577
00578
00579 TPCANMsg NMTmsg;
00580
00581
00582
00583
00584
00585 TPCANMsg syncMsg;
00586
00587
00588
00589
00590
00591 void requestDataBlock1(uint8_t CANid)
00592 {
00593 TPCANMsg msg;
00594 std::memset(&msg, 0, sizeof(msg));
00595 msg.ID = CANid + 0x600;
00596 msg.MSGTYPE = 0x00;
00597 msg.LEN = 8;
00598 msg.DATA[0] = 0x60;
00599 msg.DATA[1] = 0x00;
00600 msg.DATA[2] = 0x00;
00601 msg.DATA[3] = 0x00;
00602 msg.DATA[4] = 0x00;
00603 msg.DATA[5] = 0x00;
00604 msg.DATA[6] = 0x00;
00605 msg.DATA[7] = 0x00;
00606 CAN_Write(h, &msg);
00607 }
00608
00609 void requestDataBlock2(uint8_t CANid)
00610 {
00611 TPCANMsg msg;
00612 std::memset(&msg, 0, sizeof(msg));
00613 msg.ID = CANid + 0x600;
00614 msg.MSGTYPE = 0x00;
00615 msg.LEN = 8;
00616 msg.DATA[0] = 0x70;
00617 msg.DATA[1] = 0x00;
00618 msg.DATA[2] = 0x00;
00619 msg.DATA[3] = 0x00;
00620 msg.DATA[4] = 0x00;
00621 msg.DATA[5] = 0x00;
00622 msg.DATA[6] = 0x00;
00623 msg.DATA[7] = 0x00;
00624 CAN_Write(h, &msg);
00625 }
00626
00627 void controlPDO(uint8_t CANid, u_int16_t control1, u_int16_t control2)
00628 {
00629 TPCANMsg msg;
00630 std::memset(&msg, 0, sizeof(msg));
00631 msg.ID = CANid + 0x200;
00632 msg.MSGTYPE = 0x00;
00633 msg.LEN = 2;
00634 msg.DATA[0] = control1;
00635 msg.DATA[1] = control2;
00636 CAN_Write(h, &msg);
00637 }
00638
00639 void uploadSDO(uint8_t CANid, SDOkey sdo)
00640 {
00641 TPCANMsg msg;
00642 std::memset(&msg, 0, sizeof(msg));
00643 msg.ID = CANid + 0x600;
00644 msg.MSGTYPE = 0x00;
00645 msg.LEN = 8;
00646 msg.DATA[0] = 0x40;
00647 msg.DATA[1] = sdo.index & 0xFF;
00648 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00649 msg.DATA[3] = sdo.subindex;
00650 msg.DATA[4] = 0x00;
00651 msg.DATA[5] = 0x00;
00652 msg.DATA[6] = 0x00;
00653 msg.DATA[7] = 0x00;
00654 CAN_Write(h, &msg);
00655 }
00656
00657 void sendSDO(uint8_t CANid, SDOkey sdo, uint32_t value)
00658 {
00659 TPCANMsg msg;
00660 std::memset(&msg, 0, sizeof(msg));
00661 msg.ID = CANid + 0x600;
00662 msg.LEN = 8;
00663 msg.DATA[0] = 0x23;
00664 msg.DATA[1] = sdo.index & 0xFF;
00665 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00666 msg.DATA[3] = sdo.subindex;
00667 msg.DATA[4] = value & 0xFF;
00668 msg.DATA[5] = (value >> 8) & 0xFF;
00669 msg.DATA[6] = (value >> 16) & 0xFF;
00670 msg.DATA[7] = (value >> 24) & 0xFF;
00671 CAN_Write(h, &msg);
00672 }
00673
00674 void sendSDO(uint8_t CANid, SDOkey sdo, int32_t value)
00675 {
00676 TPCANMsg msg;
00677 std::memset(&msg, 0, sizeof(msg));
00678 msg.ID = CANid + 0x600;
00679 msg.LEN = 8;
00680 msg.DATA[0] = 0x23;
00681 msg.DATA[1] = sdo.index & 0xFF;
00682 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00683 msg.DATA[3] = sdo.subindex;
00684 msg.DATA[4] = value & 0xFF;
00685 msg.DATA[5] = (value >> 8) & 0xFF;
00686 msg.DATA[6] = (value >> 16) & 0xFF;
00687 msg.DATA[7] = (value >> 24) & 0xFF;
00688 CAN_Write(h, &msg);
00689 }
00690
00691 void sendSDO_unknown(uint8_t CANid, SDOkey sdo, int32_t value)
00692 {
00693 TPCANMsg msg;
00694 std::memset(&msg, 0, sizeof(msg));
00695 msg.ID = CANid + 0x600;
00696 msg.LEN = 8;
00697 msg.DATA[0] = 0x22;
00698 msg.DATA[1] = sdo.index & 0xFF;
00699 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00700 msg.DATA[3] = sdo.subindex;
00701 msg.DATA[4] = value & 0xFF;
00702 msg.DATA[5] = (value >> 8) & 0xFF;
00703 msg.DATA[6] = (value >> 16) & 0xFF;
00704 msg.DATA[7] = (value >> 24) & 0xFF;
00705 CAN_Write(h, &msg);
00706 }
00707
00708 void sendSDO(uint8_t CANid, SDOkey sdo, uint8_t value)
00709 {
00710 TPCANMsg msg;
00711 std::memset(&msg, 0, sizeof(msg));
00712 msg.ID = CANid + 0x600;
00713 msg.LEN = 8;
00714 msg.DATA[0] = 0x2F;
00715 msg.DATA[1] = sdo.index & 0xFF;
00716 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00717 msg.DATA[3] = sdo.subindex;
00718 msg.DATA[4] = value & 0xFF;
00719 msg.DATA[5] = 0x00;
00720 msg.DATA[6] = 0x00;
00721 msg.DATA[7] = 0x00;
00722 CAN_Write(h, &msg);
00723
00724
00725 }
00726
00727 void sendSDO(uint8_t CANid, SDOkey sdo, uint16_t value)
00728 {
00729 TPCANMsg msg;
00730 std::memset(&msg, 0, sizeof(msg));
00731 msg.ID = CANid + 0x600;
00732 msg.LEN = 8;
00733 msg.DATA[0] = 0x2B;
00734 msg.DATA[1] = sdo.index & 0xFF;
00735 msg.DATA[2] = (sdo.index >> 8) & 0xFF;
00736 msg.DATA[3] = sdo.subindex;
00737 msg.DATA[4] = value & 0xFF;
00738 msg.DATA[5] = (value >> 8) & 0xFF;
00739 msg.DATA[6] = 0x00;
00740 msg.DATA[7] = 0x00;
00741 CAN_Write(h, &msg);
00742 }
00743
00744
00745
00746
00747
00748 void initDeviceManagerThread(std::function<void ()> const& deviceManager)
00749 {
00750 std::thread device_manager_thread(deviceManager);
00751 device_manager_thread.detach();
00752 std::this_thread::sleep_for(std::chrono::milliseconds(10));
00753 }
00754
00755 void deviceManager()
00756 {
00757 std::chrono::time_point<std::chrono::high_resolution_clock> time_start, time_end;
00758
00759 std::chrono::duration<double> elapsed_time;
00760
00761
00762 while (true)
00763 {
00764 end = std::chrono::high_resolution_clock::now();
00765 std::chrono::duration<double> elapsed_seconds = end-start;
00766
00767 auto tic = std::chrono::high_resolution_clock::now();
00768 if (!recover_active)
00769 {
00770 for (auto device : canopen::devices)
00771 {
00772 if(elapsed_seconds.count() > 2)
00773 {
00774 start = std::chrono::high_resolution_clock::now();
00775 canopen::uploadSDO(device.second.getCANid(), DRIVERTEMPERATURE);
00776 getErrors(device.second.getCANid());
00777 readManErrReg(device.second.getCANid());
00778 }
00779
00780 if (device.second.getInitialized())
00781 {
00782 devices[device.first].updateDesiredPos();
00783 sendPos((uint16_t)device.second.getCANid(), (double)device.second.getDesiredPos());
00784 }
00785 }
00786 canopen::sendSync();
00787 std::this_thread::sleep_for(syncInterval - (std::chrono::high_resolution_clock::now() - tic ));
00788 }
00789
00790 }
00791 }
00792
00793
00794 std::function< void (uint16_t CANid, double velocityValue) > sendVel;
00795 std::function< void (uint16_t CANid, double positionValue) > sendPos;
00796 std::function< void (uint16_t CANid, double positionValue, double velocityValue) > sendPosPPMode;
00797
00798 void defaultPDOOutgoing_interpolated(uint16_t CANid, double positionValue)
00799 {
00800 static const uint16_t myControlword = (CONTROLWORD_ENABLE_OPERATION | CONTROLWORD_ENABLE_IP_MODE);
00801 TPCANMsg msg;
00802 std::memset(&msg, 0, sizeof(msg));
00803 msg.ID = 0x300 + CANid;
00804 msg.MSGTYPE = 0x00;
00805 msg.LEN = 4;
00806 int32_t mdegPos = rad2mdeg(positionValue);
00807 msg.DATA[0] = mdegPos & 0xFF;
00808 msg.DATA[1] = (mdegPos >> 8) & 0xFF;
00809 msg.DATA[2] = (mdegPos >> 16) & 0xFF;
00810 msg.DATA[3] = (mdegPos >> 24) & 0xFF;
00811 CAN_Write(h, &msg);
00812 }
00813
00814 void defaultPDOOutgoing(uint16_t CANid, double positionValue)
00815 {
00816 static const uint16_t myControlword = (CONTROLWORD_ENABLE_OPERATION | CONTROLWORD_ENABLE_IP_MODE);
00817 TPCANMsg msg;
00818 std::memset(&msg, 0, sizeof(msg));
00819 msg.ID = 0x200 + CANid;
00820 msg.MSGTYPE = 0x00;
00821 msg.LEN = 8;
00822 msg.DATA[0] = myControlword & 0xFF;
00823 msg.DATA[1] = (myControlword >> 8) & 0xFF;
00824 msg.DATA[2] = 0x00;
00825 msg.DATA[3] = 0x00;
00826 int32_t mdegPos = rad2mdeg(positionValue);
00827 msg.DATA[4] = mdegPos & 0xFF;
00828 msg.DATA[5] = (mdegPos >> 8) & 0xFF;
00829 msg.DATA[6] = (mdegPos >> 16) & 0xFF;
00830 msg.DATA[7] = (mdegPos >> 24) & 0xFF;
00831 CAN_Write(h, &msg);
00832 }
00833
00834
00835
00836
00837 void defaultEMCY_incoming(uint16_t CANid, const TPCANRdMsg m)
00838 {
00839
00840
00841 uint16_t mydata_low = m.Msg.DATA[0];
00842 uint16_t mydata_high = m.Msg.DATA[1];
00843
00844
00845
00846
00847 }
00848
00849 void defaultPDO_incoming_status(uint16_t CANid, const TPCANRdMsg m)
00850 {
00851
00852 uint16_t mydata_low = m.Msg.DATA[0];
00853 uint16_t mydata_high = m.Msg.DATA[1];
00854
00855 int8_t mode_display = m.Msg.DATA[2];
00856
00857 if(canopen::use_limit_switch)
00858 {
00859
00860
00861 uint16_t limit_switch_ = m.Msg.DATA[2];
00862
00863 bool hardware_limit_positive = limit_switch_ & 0x02;
00864 bool hardware_limit_negative = limit_switch_ & 0x01;
00865
00866 devices[CANid].setNegativeLimit(hardware_limit_negative);
00867 devices[CANid].setPositiveLimit(hardware_limit_positive);
00868 }
00869
00870 bool ready_switch_on = mydata_low & 0x01;
00871 bool switched_on = mydata_low & 0x02;
00872 bool op_enable = mydata_low & 0x04;
00873 bool fault = mydata_low & 0x08;
00874
00875 bool volt_enable = mydata_low & 0x10;
00876 bool quick_stop = mydata_low & 0x20;
00877 bool switch_on_disabled = mydata_low & 0x40;
00878 bool warning = mydata_low & 0x80;
00879
00880 bool mode_specific = mydata_high & 0x01;
00881 bool remote = mydata_high & 0x02;
00882 bool target_reached = mydata_high & 0x04;
00883 bool internal_limit = mydata_high & 0x08;
00884 bool op_specific = mydata_high & 0x10;
00885 bool op_specific1 = mydata_high & 0x20;
00886 bool man_specific1 = mydata_high & 0x40;
00887 bool man_specific2 = mydata_high & 0x80;
00888
00889 bool ip_mode = ready_switch_on & switched_on & op_enable & volt_enable;
00890
00891
00892 if(!ready_switch_on)
00893 {
00894 if(fault)
00895 {
00896 devices[CANid].setMotorState(canopen::MS_FAULT);
00897 }
00898 else if(switch_on_disabled)
00899 {
00900 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON_DISABLED);
00901 }
00902 else
00903 devices[CANid].setMotorState(canopen::MS_NOT_READY_TO_SWITCH_ON);
00904 }
00905
00906 else
00907 {
00908 if(switched_on)
00909 {
00910 if(op_enable)
00911 {
00912
00913
00914
00915 devices[CANid].setMotorState(canopen::MS_OPERATION_ENABLED);
00916
00917
00918 }
00919 else
00920 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON);
00921 }
00922 else if(!quick_stop)
00923 devices[CANid].setMotorState(canopen::MS_QUICK_STOP_ACTIVE);
00924
00925 else
00926 devices[CANid].setMotorState(canopen::MS_READY_TO_SWITCH_ON);
00927
00928 }
00929
00930 if(fault & op_enable & switched_on & ready_switch_on)
00931 devices[CANid].setMotorState(canopen::MS_FAULT_REACTION_ACTIVE);
00932
00933
00934 devices[CANid].setFault(fault);
00935 devices[CANid].setIPMode(ip_mode);
00936 devices[CANid].setHoming(op_specific);
00937 devices[CANid].setOpSpec0(op_specific);
00938 devices[CANid].setOpSpec1(op_specific1);
00939 devices[CANid].setManSpec1(man_specific1);
00940 devices[CANid].setManSpec2(man_specific2);
00941 devices[CANid].setInternalLimits(internal_limit);
00942 devices[CANid].setTargetReached(target_reached);
00943 devices[CANid].setRemote(remote);
00944 devices[CANid].setModeSpec(mode_specific);
00945 devices[CANid].setWarning(warning);
00946 devices[CANid].setSwitchOnDisable(switch_on_disabled);
00947 devices[CANid].setQuickStop(quick_stop);
00948 devices[CANid].setOpEnable(op_enable);
00949 devices[CANid].setVoltageEnabled(volt_enable);
00950 devices[CANid].setReadySwitchON(ready_switch_on);
00951 devices[CANid].setSwitchON(switched_on);
00952
00953 devices[CANid].setCurrentModeofOperation(mode_display);
00954
00955
00956
00957
00958 }
00959
00960 void defaultPDO_incoming_pos(uint16_t CANid, const TPCANRdMsg m)
00961 {
00962 double newPos = mdeg2rad(m.Msg.DATA[0] + (m.Msg.DATA[1] << 8) + (m.Msg.DATA[2] << 16) + (m.Msg.DATA[3] << 24));
00963 double newVel = mdeg2rad(m.Msg.DATA[4] + (m.Msg.DATA[5] << 8) + (m.Msg.DATA[6] << 16) + (m.Msg.DATA[7] << 24));
00964
00965
00966
00967
00968 if (devices[CANid].getTimeStamp_msec() != std::chrono::milliseconds(0) || devices[CANid].getTimeStamp_usec() != std::chrono::microseconds(0))
00969 {
00970 auto deltaTime_msec = std::chrono::milliseconds(m.dwTime) - devices[CANid].getTimeStamp_msec();
00971 auto deltaTime_usec = std::chrono::microseconds(m.wUsec) - devices[CANid].getTimeStamp_usec();
00972 double deltaTime_double = static_cast<double>(deltaTime_msec.count()*1000 + deltaTime_usec.count()) * 0.000001;
00973 double result = (newPos - devices[CANid].getActualPos()) / deltaTime_double;
00974 devices[CANid].setActualVel(result);
00975 if (! devices[CANid].getInitialized())
00976 {
00977 devices[CANid].setDesiredPos(newPos);
00978 }
00979
00980 }
00981
00982 devices[CANid].setActualPos(newPos);
00983
00984
00985 devices[CANid].setTimeStamp_msec(std::chrono::milliseconds(m.dwTime));
00986 devices[CANid].setTimeStamp_usec(std::chrono::microseconds(m.wUsec));
00987
00988 }
00989 void defaultPDO_incoming(uint16_t CANid, const TPCANRdMsg m)
00990 {
00991 double newPos = mdeg2rad(m.Msg.DATA[4] + (m.Msg.DATA[5] << 8) + (m.Msg.DATA[6] << 16) + (m.Msg.DATA[7] << 24) );
00992
00993 if (devices[CANid].getTimeStamp_msec() != std::chrono::milliseconds(0) || devices[CANid].getTimeStamp_usec() != std::chrono::microseconds(0))
00994 {
00995 auto deltaTime_msec = std::chrono::milliseconds(m.dwTime) - devices[CANid].getTimeStamp_msec();
00996 auto deltaTime_usec = std::chrono::microseconds(m.wUsec) - devices[CANid].getTimeStamp_usec();
00997 double deltaTime_double = static_cast<double>(deltaTime_msec.count()*1000 + deltaTime_usec.count()) * 0.000001;
00998 double result = (newPos - devices[CANid].getActualPos()) / deltaTime_double;
00999 devices[CANid].setActualVel(result);
01000 if (! devices[CANid].getInitialized())
01001 {
01002 devices[CANid].setDesiredPos(newPos);
01003 }
01004
01005 }
01006
01007
01008 devices[CANid].setActualPos(newPos);
01009 devices[CANid].setTimeStamp_msec(std::chrono::milliseconds(m.dwTime));
01010 devices[CANid].setTimeStamp_usec(std::chrono::microseconds(m.wUsec));
01011
01012 uint16_t mydata_low = m.Msg.DATA[0];
01013 uint16_t mydata_high = m.Msg.DATA[1];
01014
01015 bool ready_switch_on = mydata_low & 0x01;
01016 bool switched_on = mydata_low & 0x02;
01017 bool op_enable = mydata_low & 0x04;
01018 bool fault = mydata_low & 0x08;
01019
01020 bool volt_enable = mydata_low & 0x10;
01021 bool quick_stop = mydata_low & 0x20;
01022 bool switch_on_disabled = mydata_low & 0x40;
01023 bool warning = mydata_low & 0x80;
01024
01025 bool mode_specific = mydata_high & 0x01;
01026 bool remote = mydata_high & 0x02;
01027 bool target_reached = mydata_high & 0x04;
01028 bool internal_limit = mydata_high & 0x08;
01029 bool op_specific = mydata_high & 0x10;
01030 bool op_specific1 = mydata_high & 0x20;
01031 bool man_specific1 = mydata_high & 0x40;
01032 bool man_specific2 = mydata_high & 0x80;
01033
01034 bool ip_mode = ready_switch_on & switched_on & op_enable & volt_enable;
01035
01036
01037 if(!ready_switch_on)
01038 {
01039 if(fault)
01040 {
01041 devices[CANid].setMotorState(canopen::MS_FAULT);
01042 }
01043 else if(switch_on_disabled)
01044 {
01045 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON_DISABLED);
01046 }
01047 else
01048 devices[CANid].setMotorState(canopen::MS_NOT_READY_TO_SWITCH_ON);
01049 }
01050
01051 else
01052 {
01053 if(switched_on)
01054 {
01055 if(op_enable)
01056 {
01057
01058
01059
01060 devices[CANid].setMotorState(canopen::MS_OPERATION_ENABLED);
01061
01062
01063 }
01064 else
01065 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON);
01066 }
01067 else if(!quick_stop)
01068 devices[CANid].setMotorState(canopen::MS_QUICK_STOP_ACTIVE);
01069
01070 else
01071 devices[CANid].setMotorState(canopen::MS_READY_TO_SWITCH_ON);
01072
01073 }
01074
01075 if(fault & op_enable & switched_on & ready_switch_on)
01076 devices[CANid].setMotorState(canopen::MS_FAULT_REACTION_ACTIVE);
01077
01078
01079 devices[CANid].setFault(fault);
01080 devices[CANid].setIPMode(ip_mode);
01081 devices[CANid].setHoming(op_specific);
01082 devices[CANid].setOpSpec0(op_specific);
01083 devices[CANid].setOpSpec1(op_specific1);
01084 devices[CANid].setManSpec1(man_specific1);
01085 devices[CANid].setManSpec2(man_specific2);
01086 devices[CANid].setInternalLimits(internal_limit);
01087 devices[CANid].setTargetReached(target_reached);
01088 devices[CANid].setRemote(remote);
01089 devices[CANid].setModeSpec(mode_specific);
01090 devices[CANid].setWarning(warning);
01091 devices[CANid].setSwitchOnDisable(switch_on_disabled);
01092 devices[CANid].setQuickStop(quick_stop);
01093 devices[CANid].setOpEnable(op_enable);
01094 devices[CANid].setVoltageEnabled(volt_enable);
01095 devices[CANid].setReadySwitchON(ready_switch_on);
01096 devices[CANid].setSwitchON(switched_on);
01097
01098
01099
01100
01101 }
01102
01103
01104
01105
01106
01107 void initListenerThread(std::function<void ()> const& listener)
01108 {
01109 std::thread listener_thread(listener);
01110 listener_thread.detach();
01111 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01112
01113 }
01114
01115 void defaultListener()
01116 {
01117 while(true)
01118 {
01119
01120 TPCANRdMsg m;
01121 errno = LINUX_CAN_Read(h, &m);
01122 if (errno)
01123 perror("LINUX_CAN_Read() error");
01124
01125
01126 else if (m.Msg.ID == 0x080)
01127 {
01128
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 else if (m.Msg.ID == 0x100)
01141 {
01142
01143 }
01144
01145
01146 else if (m.Msg.ID >= 0x180 && m.Msg.ID <= 0x4FF)
01147 {
01148
01149
01150 if (incomingPDOHandlers.find(m.Msg.ID) != incomingPDOHandlers.end())
01151 incomingPDOHandlers[m.Msg.ID](m);
01152 }
01153
01154
01155 else if (m.Msg.ID >= 0x580 && m.Msg.ID <= 0x5FF)
01156 {
01157
01158 SDOkey sdoKey(m);
01159 if(sdo_protect)
01160 {
01161 std::copy(std::begin(m.Msg.DATA), std::end(m.Msg.DATA), std::begin(protect_msg));
01162 sdo_protect = false;
01163 }
01164 else
01165 {
01166 if (incomingErrorHandlers.find(sdoKey) != incomingErrorHandlers.end())
01167 incomingErrorHandlers[sdoKey](m.Msg.ID - 0x580, m.Msg.DATA);
01168 else if (incomingDataHandlers.find(sdoKey) != incomingDataHandlers.end())
01169 incomingDataHandlers[sdoKey](m.Msg.ID - 0x580, m.Msg.DATA);
01170 else if (incomingManufacturerDetails.find(sdoKey) != incomingManufacturerDetails.end())
01171 incomingManufacturerDetails[sdoKey](m.Msg.ID - 0x580, m.Msg.DATA);
01172 }
01173 }
01174
01175
01176 else if (m.Msg.ID >= 0x700 && m.Msg.ID <= 0x7FF)
01177 {
01178 uint16_t CANid = (uint16_t)(m.Msg.ID - 0x700);
01179
01180 if (m.Msg.DATA[0] == 0x00)
01181 {
01182 std::cout << "Bootup received. Node-ID = " << CANid << std::endl;
01183 std::map<uint8_t,Device>::const_iterator search = devices.find(CANid);
01184 if(search != devices.end())
01185 {
01186 std::cout << "Found " << (u_int16_t)search->first << "\n";
01187 std::cout << "Initializing..." << "\n";
01188 devices[CANid].setNMTInit(true);
01189 }
01190 else
01191 {
01192 std::cout << "Not found" << std::endl;
01193 std::cout << "Ignoring" << std::endl;
01194 }
01195
01196 }
01197 else
01198 {
01199 std::cout << "NMT error control received: " << (uint16_t)(m.Msg.ID - 0x700) << " " << (uint16_t)m.Msg.DATA[0] << std::endl;
01200 }
01201 }
01202 else
01203 {
01204
01205 }
01206 }
01207 }
01208
01209
01210
01211
01212 void getErrors(uint16_t CANid)
01213 {
01214 canopen::uploadSDO(CANid, canopen::ERRORWORD);
01215 }
01216
01217 void manufacturer_incoming(uint8_t CANid, BYTE data[8])
01218 {
01219 sdo_protect = true;
01220
01221 if(data[1]+(data[2]<<8) == 0x1008)
01222 {
01223 std::vector<char> manufacturer_device_name = canopen::obtainManDevName(CANid, data[4]);
01224
01225 devices[CANid].setManufacturerDevName(manufacturer_device_name);
01226 }
01227
01228
01229
01230
01231
01232
01233 }
01234
01235 void errorword_incoming(uint8_t CANid, BYTE data[8])
01236 {
01237 std::stringstream str_stream;
01238
01239 if(data[1]+(data[2]<<8) == 0x1001)
01240 {
01241 uint16_t error_register;
01242 error_register = data[4];
01243
01244 str_stream << "error_register=0x" << std::hex << (int)error_register << ", categories:";
01245
01246 if ( error_register & canopen::EMC_k_1001_GENERIC )
01247 str_stream << " generic,";
01248 if ( error_register & canopen::EMC_k_1001_CURRENT)
01249 str_stream << " current,";
01250 if ( error_register & canopen::EMC_k_1001_VOLTAGE )
01251 str_stream << " voltage,";
01252 if ( error_register & canopen::EMC_k_1001_TEMPERATURE )
01253 str_stream << " temperature,";
01254 if ( error_register & canopen::EMC_k_1001_COMMUNICATION )
01255 str_stream << " communication,";
01256 if ( error_register & canopen::EMC_k_1001_DEV_PROF_SPEC )
01257 str_stream << " device profile specific,";
01258 if ( error_register & canopen::EMC_k_1001_RESERVED )
01259 str_stream << " reserved,";
01260 if ( error_register & canopen::EMC_k_1001_MANUFACTURER)
01261 str_stream << " manufacturer specific";
01262 str_stream << "\n";
01263
01264 devices[CANid].setErrorRegister(str_stream.str());
01265 }
01266 else if(data[1]+(data[2]<<8) == 0x1002)
01267 {
01268 uint16_t code = data[4];
01269 uint16_t classification = data[5];
01270
01271 str_stream << "manufacturer_status_register=0x" << std::hex << int(classification) << int(code) <<
01272 ": code=0x" << std::hex << int( code ) << " (" << errorsCode[int(code)] << "),"
01273 << ", classification=0x" << std::hex << int( classification ) << std::dec;
01274 if ( classification == 0x88 )
01275 str_stream << " (CMD_ERROR)";
01276 if ( classification == 0x89 )
01277 str_stream << " (CMD_WARNING)";
01278 if ( classification == 0x8a )
01279 str_stream << " (CMD_INFO)";
01280 str_stream << "\n";
01281
01282 devices[CANid].setManufacturerErrorRegister(str_stream.str());
01283 }
01284 }
01285
01286 void readManErrReg(uint16_t CANid)
01287 {
01288 canopen::uploadSDO(CANid, canopen::MANUFACTURER);
01289 }
01290
01291 void readErrorsRegister(uint16_t CANid, std::shared_ptr<TPCANRdMsg> m)
01292 {
01293 canopen::uploadSDO(CANid, canopen::STATUSWORD);
01294 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01295 canopen::processSingleSDO(CANid, m);
01296
01297 canopen::uploadSDO(CANid, canopen::ERRORWORD);
01298 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01299 canopen::processSingleSDO(CANid, m);
01300
01301 uint16_t error_register;
01302 error_register = m->Msg.DATA[4];
01303
01304 std::cout << "error_register=0x" << std::hex << (int)error_register << ", categories:";
01305
01306 if ( error_register & canopen::EMC_k_1001_GENERIC )
01307 std::cout << " generic,";
01308 if ( error_register & canopen::EMC_k_1001_CURRENT)
01309 std::cout << " current,";
01310 if ( error_register & canopen::EMC_k_1001_VOLTAGE )
01311 std::cout << " voltage,";
01312 if ( error_register & canopen::EMC_k_1001_TEMPERATURE )
01313 std::cout << " temperature,";
01314 if ( error_register & canopen::EMC_k_1001_COMMUNICATION )
01315 std::cout << " communication,";
01316 if ( error_register & canopen::EMC_k_1001_DEV_PROF_SPEC )
01317 std::cout << " device profile specific,";
01318 if ( error_register & canopen::EMC_k_1001_RESERVED )
01319 std::cout << " reserved,";
01320 if ( error_register & canopen::EMC_k_1001_MANUFACTURER)
01321 std::cout << " manufacturer specific";
01322 std::cout << "\n";
01323 }
01324
01325 std::vector<uint16_t> obtainVendorID(uint16_t CANid)
01326 {
01327 canopen::uploadSDO(CANid, canopen::IDENTITYVENDORID);
01328 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01329 }
01330
01331 std::vector<uint16_t> obtainProdCode(uint16_t CANid, std::shared_ptr<TPCANRdMsg> m)
01332 {
01333 canopen::uploadSDO(CANid, canopen::IDENTITYPRODUCTCODE);
01334 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01335
01336 std::vector<uint16_t> product_code;
01337
01338 canopen::processSingleSDO(CANid, m);
01339
01340 uint16_t id4 = m->Msg.DATA[4];
01341 uint16_t id3 = m->Msg.DATA[5];
01342 uint16_t id2 = m->Msg.DATA[6];
01343 uint16_t id1 = m->Msg.DATA[7];
01344
01345 product_code.push_back(id1);
01346 product_code.push_back(id2);
01347 product_code.push_back(id3);
01348 product_code.push_back(id4);
01349
01350 return product_code;
01351
01352 }
01353
01354 uint16_t obtainRevNr(uint16_t CANid, std::shared_ptr<TPCANRdMsg> m)
01355 {
01356 canopen::uploadSDO(CANid, canopen::IDENTITYREVNUMBER);
01357 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01358
01359
01360 canopen::processSingleSDO(CANid, m);
01361
01362 uint16_t rev_number = m->Msg.DATA[4];
01363
01364 return rev_number;
01365
01366 }
01367
01368 std::vector<char> obtainManDevName(uint16_t CANid, int size_name)
01369 {
01370
01371 std::vector<char> manufacturer_device_name;
01372
01373 canopen::requestDataBlock1(CANid);
01374 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01375 for (auto it : protect_msg)
01376 {
01377 if(manufacturer_device_name.size() <= size_name)
01378 manufacturer_device_name.push_back(it);
01379 }
01380
01381 return manufacturer_device_name;
01382
01383 }
01384
01385
01386
01387
01388 std::vector<char> obtainManHWVersion(uint16_t CANid, std::shared_ptr<TPCANRdMsg> m)
01389 {
01390 canopen::uploadSDO(CANid, canopen::MANUFACTURERHWVERSION);
01391 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01392
01393 std::vector<char> manufacturer_hw_version;
01394
01395 canopen::processSingleSDO(CANid, m);
01396
01397 int size = m->Msg.DATA[4];
01398
01399 canopen::requestDataBlock1(CANid);
01400 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01401
01402 canopen::processSingleSDO(CANid, m);
01403
01404
01405 for (auto it : m->Msg.DATA)
01406 {
01407 if(manufacturer_hw_version.size() <= size)
01408 manufacturer_hw_version.push_back(it);
01409 }
01410
01411
01412 canopen::requestDataBlock2(CANid);
01413 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01414
01415 canopen::processSingleSDO(CANid, m);
01416
01417
01418 for (auto it : m->Msg.DATA)
01419 {
01420 if(manufacturer_hw_version.size() <= size)
01421 manufacturer_hw_version.push_back(it);
01422 }
01423
01424 return manufacturer_hw_version;
01425 }
01426
01427 std::vector<char> obtainManSWVersion(uint16_t CANid, std::shared_ptr<TPCANRdMsg> m)
01428 {
01429 std::vector<char> manufacturer_sw_version;
01430
01431 canopen::uploadSDO(CANid, canopen::MANUFACTURERSOFTWAREVERSION);
01432 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01433
01434 canopen::processSingleSDO(CANid, m);
01435
01436 int size = (uint8_t)m->Msg.DATA[4];
01437
01438 canopen::requestDataBlock1(CANid);
01439 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01440
01441 canopen::processSingleSDO(CANid, m);
01442
01443
01444 for (auto it : m->Msg.DATA)
01445 {
01446 if(manufacturer_sw_version.size() <= size)
01447 manufacturer_sw_version.push_back(it);
01448 }
01449
01450
01451 canopen::requestDataBlock2(CANid);
01452 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01453
01454 canopen::processSingleSDO(CANid, m);
01455
01456
01457 for (auto it : m->Msg.DATA)
01458 {
01459 if(manufacturer_sw_version.size() <= size)
01460 manufacturer_sw_version.push_back(it);
01461 }
01462
01463 canopen::requestDataBlock1(CANid);
01464 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01465
01466 canopen::processSingleSDO(CANid, m);
01467
01468
01469 for (auto it : m->Msg.DATA)
01470 {
01471 if(manufacturer_sw_version.size() <= size)
01472 manufacturer_sw_version.push_back(it);
01473 }
01474
01475 canopen::requestDataBlock2(CANid);
01476 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01477
01478 canopen::processSingleSDO(CANid, m);
01479
01480
01481 for (auto it : m->Msg.DATA)
01482 {
01483 if(manufacturer_sw_version.size() <= size)
01484 manufacturer_sw_version.push_back(it);
01485 }
01486
01487 return manufacturer_sw_version;
01488
01489 }
01490
01491
01492
01493 void sdo_incoming(uint8_t CANid, BYTE data[8])
01494 {
01495
01496 if(data[1]+(data[2]<<8) == 0x6041)
01497 {
01498 uint16_t mydata_low = data[4];
01499 uint16_t mydata_high = data[5];
01500
01501 bool ready_switch_on = mydata_low & 0x01;
01502 bool switched_on = mydata_low & 0x02;
01503 bool op_enable = mydata_low & 0x04;
01504 bool fault = mydata_low & 0x08;
01505 bool volt_enable = mydata_low & 0x10;
01506 bool quick_stop = mydata_low & 0x20;
01507 bool switch_on_disabled = mydata_low & 0x40;
01508 bool warning = mydata_low & 0x80;
01509
01510 bool mode_specific = mydata_high & 0x01;
01511 bool remote = mydata_high & 0x02;
01512 bool target_reached = mydata_high & 0x04;
01513 bool internal_limit = mydata_high & 0x08;
01514 bool op_specific = mydata_high & 0x10;
01515 bool op_specific1 = mydata_high & 0x20;
01516 bool man_specific1 = mydata_high & 0x40;
01517 bool man_specific2 = mydata_high & 0x80;
01518
01519
01520 bool ip_mode = ready_switch_on & switched_on & op_enable & volt_enable;
01521
01522
01523 if(!ready_switch_on)
01524 {
01525 if(fault)
01526 {
01527 devices[CANid].setMotorState(canopen::MS_FAULT);
01528 }
01529 else if(switch_on_disabled)
01530 {
01531 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON_DISABLED);
01532 }
01533 else
01534 devices[CANid].setMotorState(canopen::MS_NOT_READY_TO_SWITCH_ON);
01535 }
01536
01537 else
01538 {
01539 if(switched_on)
01540 {
01541 if(op_enable)
01542 {
01543
01544
01545
01546 devices[CANid].setMotorState(canopen::MS_OPERATION_ENABLED);
01547
01548
01549 }
01550 else
01551 devices[CANid].setMotorState(canopen::MS_SWITCHED_ON);
01552 }
01553 else if(!quick_stop)
01554 devices[CANid].setMotorState(canopen::MS_QUICK_STOP_ACTIVE);
01555
01556 else
01557 devices[CANid].setMotorState(canopen::MS_READY_TO_SWITCH_ON);
01558
01559 }
01560
01561 if(fault & op_enable & switched_on & ready_switch_on)
01562 devices[CANid].setMotorState(canopen::MS_FAULT_REACTION_ACTIVE);
01563
01564
01565
01566 devices[CANid].setFault(fault);
01567 devices[CANid].setHoming(op_specific);
01568 devices[CANid].setOpSpec0(op_specific);
01569 devices[CANid].setOpSpec1(op_specific1);
01570 devices[CANid].setManSpec1(man_specific1);
01571 devices[CANid].setManSpec2(man_specific2);
01572 devices[CANid].setInternalLimits(internal_limit);
01573 devices[CANid].setTargetReached(target_reached);
01574 devices[CANid].setRemote(remote);
01575 devices[CANid].setModeSpec(mode_specific);
01576 devices[CANid].setWarning(warning);
01577 devices[CANid].setSwitchOnDisable(switch_on_disabled);
01578 devices[CANid].setQuickStop(quick_stop);
01579 devices[CANid].setOpEnable(op_enable);
01580 devices[CANid].setVoltageEnabled(volt_enable);
01581 devices[CANid].setReadySwitchON(ready_switch_on);
01582 devices[CANid].setSwitchON(switched_on);
01583
01584
01585 }
01586
01587 else if(data[1]+(data[2]<<8) == 0x22A2)
01588 {
01589 devices[CANid].setDriverTemperature(data[4]);
01590 }
01591
01592 else if(data[1]+(data[2]<<8) == 0x6061)
01593 {
01594 devices[CANid].setCurrentModeofOperation(data[4]);
01595 }
01596
01597 }
01598
01599 void processSingleSDO(uint8_t CANid, std::shared_ptr<TPCANRdMsg> message)
01600 {
01601 message->Msg.ID = 0x00;
01602
01603 while (message->Msg.ID != (0x580+CANid))
01604 {
01605 LINUX_CAN_Read(canopen::h, message.get());
01606 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01607 }
01608 }
01609
01610 void pdoChanged()
01611 {
01612 for (auto device : devices)
01613 {
01614 TPCANMsg* mes;
01616 mes->ID =device.second.getCANid() + 0x600;
01617 mes->MSGTYPE = 0x00;
01618 mes->LEN = 8;
01619 mes->DATA[0] = 0x2F;
01620 mes->DATA[1] = 0x20;
01621 mes->DATA[2] = 0x2F;
01622 mes->DATA[3] = 0x04;
01623 mes->DATA[4] = 0x00;
01624 mes->DATA[5] = 0x00;
01625 mes->DATA[6] = 0x00;
01626 mes->DATA[7] = 0x01;
01627 CAN_Write(canopen::h, mes);
01628
01629 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01630 }
01631 }
01632
01633 void disableRPDO(int object)
01634 {
01635 for (auto device : devices)
01636 {
01637 if(object == 0)
01638 {
01639 int32_t data = (canopen::RPDO1_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01640 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01641 }
01642 else if(object == 1)
01643 {
01644 int32_t data = (canopen::RPDO2_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01645 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01646
01647 }
01648
01649 else if(object == 2)
01650 {
01651 int32_t data = (canopen::RPDO3_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01652 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01653 }
01654
01655 else if(object == 3)
01656
01657 {
01658 int32_t data = (canopen::RPDO4_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01659 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01660 }
01661
01662 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01663
01665
01666 }
01667 }
01668
01669 void setObjects()
01670 {
01671 for (auto device : devices)
01672 {
01673 int32_t data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01674 sendSDO_unknown(device.second.getCANid(), SDOkey(0x6081,0x00), data);
01675 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01676
01677 data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01678 sendSDO_unknown(device.second.getCANid(), SDOkey(0x607f,0x00), data);
01679 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01680
01681 data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01682 sendSDO_unknown(device.second.getCANid(), SDOkey(0x6083,0x00), data);
01683 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01684
01685 data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01686 sendSDO_unknown(device.second.getCANid(), SDOkey(0x60c5,0x00), data);
01687 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01688
01689 data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01690 sendSDO_unknown(device.second.getCANid(), SDOkey(0x60c6,0x00), data);
01691 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01692
01693 data = 0x1388 + (0x00 << 16) + (0x00 << 24);
01694 sendSDO_unknown(device.second.getCANid(), SDOkey(0x6082,0x00), data);
01695 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01696
01697 }
01698 }
01699
01700 void clearRPDOMapping(int object)
01701 {
01702 for (auto device : devices)
01703 {
01704 int32_t data = (0x00 << 16) + (0x80 << 24);
01705
01706 sendSDO_unknown(device.second.getCANid(), SDOkey(RPDO_map.index+object,0x00), data);
01707
01708 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01709 }
01710 }
01711
01712 void makeRPDOMapping(int object, std::vector<std::string> registers, std::vector<int> sizes , u_int8_t sync_type)
01713 {
01714 for (auto device : devices)
01715 {
01716 int ext_counter=0;
01717 for(int counter=0; counter < registers.size();counter++)
01718 {
01720 int index_data;
01721
01722 std::stringstream str_stream;
01723 str_stream << registers[counter];
01724 str_stream >> std::hex >> index_data;
01725
01726 str_stream.str( std::string() );
01727 str_stream.clear();
01728
01732 int32_t data = (sizes[counter]) + (index_data << 8);
01733
01734 sendSDO(device.second.getCANid(), SDOkey(RPDO_map.index+object,counter+1), data);
01735
01736 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01737
01738 ext_counter++;
01739 }
01742
01743 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x02), u_int8_t(sync_type));
01744
01745 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01750 sendSDO(device.second.getCANid(), SDOkey(RPDO_map.index+object,0x00), u_int8_t(ext_counter));
01751
01752 }
01753 }
01754
01755 void enableRPDO(int object)
01756 {
01757 for (auto device : devices)
01758 {
01759 if(object ==0)
01760 {
01761 int32_t data = (canopen::RPDO1_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01762
01763 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01764 }
01765 else if(object == 1)
01766 {
01767 int32_t data = (canopen::RPDO2_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01768
01769 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01770 }
01771 else if(object == 2)
01772 {
01773 int32_t data = (canopen::RPDO3_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01774
01775 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01776 }
01777 else if(object == 3)
01778 {
01779 int32_t data = (canopen::RPDO4_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01780
01781 sendSDO(device.second.getCANid(), SDOkey(RPDO.index+object,0x01), data);
01782 }
01783
01784 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01785
01787 }
01788 }
01789
01790
01791
01792
01793
01794
01795
01796 void disableTPDO(int object)
01797 {
01798
01799 for(auto device : devices)
01800 {
01801
01803
01804 if(object == 0)
01805 {
01806 int32_t data = (canopen::TPDO1_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01807 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01808 }
01809 else if(object == 1)
01810 {
01811 int32_t data = (canopen::TPDO2_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01812 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01813
01814 }
01815
01816 else if(object == 2)
01817 {
01818 int32_t data = (canopen::TPDO3_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01819 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01820 }
01821
01822 else if(object == 3)
01823
01824 {
01825 int32_t data = (canopen::TPDO4_msg + device.second.getCANid()) + (0x00 << 16) + (0x80 << 24);
01826 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01827 }
01828
01829 else
01830 std::cout << "Incorrect object for mapping" << std::endl;
01831
01832
01833
01834 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01835
01837 }
01838
01839
01840 }
01841
01842 void clearTPDOMapping(int object)
01843 {
01844 for (auto device : devices)
01845 {
01848
01849 sendSDO(device.second.getCANid(), SDOkey(TPDO_map.index+object,0x00), u_int8_t(0x00));
01850
01851 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01852 }
01853 }
01854
01855 void makeTPDOMapping(int object, std::vector<std::string> registers, std::vector<int> sizes, u_int8_t sync_type)
01856 {
01857 for (auto device : devices)
01858 {
01863 int ext_counter=0;
01864 for(int counter=0; counter < registers.size();counter++)
01865 {
01867 int index_data;
01868
01869 std::stringstream str_stream;
01870 str_stream << registers[counter];
01871 str_stream >> std::hex >> index_data;
01872
01873 str_stream.str( std::string() );
01874 str_stream.clear();
01875
01879 int32_t data = (sizes[counter]) + (index_data << 8);
01880
01881 sendSDO(device.second.getCANid(), SDOkey(TPDO_map.index+object,counter+1), data);
01882
01883 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01884
01885 ext_counter++;
01886 }
01889
01890 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x02), u_int8_t(sync_type));
01891
01892 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01897 sendSDO(device.second.getCANid(), SDOkey(TPDO_map.index+object,0x00), u_int8_t(ext_counter));
01898 }
01899
01900 }
01901
01902 void enableTPDO(int object)
01903 {
01904 for (auto device : devices)
01905 {
01909 if(object ==0)
01910 {
01911 int32_t data = (canopen::TPDO1_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01912
01913 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01914 }
01915 else if(object == 1)
01916 {
01917 int32_t data = (canopen::TPDO2_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01918
01919 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01920 }
01921 else if(object == 2)
01922 {
01923 int32_t data = (canopen::TPDO3_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01924
01925 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01926 }
01927 else if(object == 3)
01928 {
01929 int32_t data = (canopen::TPDO4_msg + device.second.getCANid()) + (0x00 << 16) + (0x00 << 24);
01930
01931 sendSDO(device.second.getCANid(), SDOkey(TPDO.index+object,0x01), data);
01932 }
01933
01934 std::this_thread::sleep_for(std::chrono::milliseconds(10));
01935
01936 }
01938 }
01939
01940
01941
01942
01943 }