canopen.cpp
Go to the documentation of this file.
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 //                      define global variables and functions
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 //              define init and recover sequence
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         //              Manufacturer specific errors register
00128         /***************************************************************/
00129         readManErrReg(device.second.getCANid());
00130 
00131         /**************************
00132        * Hardware and Software Information
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             //Necessary otherwise sometimes Schunk devices complain for Position Track Error
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         // std::cout << "Connection to CAN bus established (recover)" << std::endl;
00447     }
00448 
00449 
00450     for (auto device : devices)
00451     {
00452         //std::cout << "Module with CAN-id " << (uint16_t)device.second.getCANid() << " connected (recover)" << std::endl;
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 //              define state machine functions
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                 //std::this_thread::sleep_for(std::chrono::milliseconds(50));
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             //canopen::sendSDO(CANid, canopen::CONTROLWORD, canopen::CONTROLWORD_SHUTDOWN);
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                 //canopen::sendSDO(CANid, canopen::CONTROLWORD, canopen::CONTROLWORD_ENABLE_OPERATION);
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 //                      define NMT variables
00577 /***************************************************************/
00578 
00579 TPCANMsg NMTmsg;
00580 
00581 /***************************************************************/
00582 //                      define SYNC variables
00583 /***************************************************************/
00584 
00585 TPCANMsg syncMsg;
00586 
00587 /***************************************************************/
00588 //              define SDO protocol functions
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 //              define PDO protocol functions
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     // std::cout << "EMCY" << (uint16_t)CANid << " is: " << (uint16_t)m.Msg.DATA[0] << std::endl;
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     // std::cout << "fault PDO" << fault << std::endl;
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                 //if(volt_enable)
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     // std::cout << "Motor State of Device with CANid " << (uint16_t)CANid << " is: " << devices[CANid].getMotorState() << std::endl;
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     //newPos = devices[CANid].getConversionFactor()*newPos; //TODO: conversion from yaml file
00966     //newVel = devices[CANid].getConversionFactor()*newVel;
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         //std::cout << "actualPos: " << devices[CANid].getActualPos() << "  desiredPos: " << devices[CANid].getDesiredPos() << std::endl;
00980     }
00981 
00982     devices[CANid].setActualPos(newPos);
00983     //devices[CANid].setActualVel(newVel);
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         //std::cout << "actualPos: " << devices[CANid].getActualPos() << "  desiredPos: " << devices[CANid].getDesiredPos() << std::endl;
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     // std::cout << "fault PDO" << fault << std::endl;
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                 //if(volt_enable)
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     // std::cout << "Motor State of Device with CANid " << (uint16_t)CANid << " is: " << devices[CANid].getMotorState() << std::endl;
01099 
01100 
01101 }
01102 
01103 /***************************************************************/
01104 //              define functions for receiving data
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     //std::cout << "Listener thread initialized" << std::endl;
01113 }
01114 
01115 void defaultListener()
01116 {
01117     while(true)
01118     {
01119         //std::cout << "Reading incoming data" << std::endl;
01120         TPCANRdMsg m;
01121         errno = LINUX_CAN_Read(h, &m);
01122         if (errno)
01123             perror("LINUX_CAN_Read() error");
01124 
01125         // incoming SYNC
01126         else if (m.Msg.ID == 0x080)
01127         {
01128             // std::cout << std::hex << "SYNC received:  " << (uint16_t)m.Msg.ID << "  " << (uint16_t)m.Msg.DATA[0] << " " << (uint16_t)m.Msg.DATA[1] << " " << (uint16_t)m.Msg.DATA[2] << " " << (uint16_t)m.Msg.DATA[3] << " " << (uint16_t)m.Msg.DATA[4] << " " << (uint16_t)m.Msg.DATA[5] << " " << (uint16_t)m.Msg.DATA[6] << " " << (uint16_t)m.Msg.DATA[7] << std::endl;
01129         }
01130 
01131         // incoming EMCY
01132         //else if (m.Msg.ID >= 0x081 && m.Msg.ID <= 0x0FF)
01133         //{
01134          //   std::cout << std::hex << "EMCY received:  " << (uint16_t)m.Msg.ID << "  " << (uint16_t)m.Msg.DATA[0] << " " << (uint16_t)m.Msg.DATA[1] << " " << (uint16_t)m.Msg.DATA[2] << " " << (uint16_t)m.Msg.DATA[3] << " " << (uint16_t)m.Msg.DATA[4] << " " << (uint16_t)m.Msg.DATA[5] << " " << (uint16_t)m.Msg.DATA[6] << " " << (uint16_t)m.Msg.DATA[7] << std::endl;
01135           //  if (incomingEMCYHandlers.find(m.Msg.ID) != incomingEMCYHandlers.end())
01136            //     incomingEMCYHandlers[m.Msg.ID](m);
01137         //}
01138 
01139         // incoming TIME
01140         else if (m.Msg.ID == 0x100)
01141         {
01142             // std::cout << std::hex << "TIME received:  " << (uint16_t)m.Msg.ID << "  " << (uint16_t)m.Msg.DATA[0] << " " << (uint16_t)m.Msg.DATA[1] << " " << (uint16_t)m.Msg.DATA[2] << " " << (uint16_t)m.Msg.DATA[3] << " " << (uint16_t)m.Msg.DATA[4] << " " << (uint16_t)m.Msg.DATA[5] << " " << (uint16_t)m.Msg.DATA[6] << " " << (uint16_t)m.Msg.DATA[7] << std::endl;
01143         }
01144 
01145         // incoming PD0
01146         else if (m.Msg.ID >= 0x180 && m.Msg.ID <= 0x4FF)
01147         {
01148             //std::cout << std::hex << "PDO received:  " << (m.Msg.ID - 0x180) << "  " << m.Msg.DATA[0] << " " << m.Msg.DATA[1] << " " << m.Msg.DATA[2] << " " << m.Msg.DATA[3] << " " << m.Msg.DATA[4] << " " << m.Msg.DATA[5] << " " << m.Msg.DATA[6] << " " <<  m.Msg.DATA[7] << " " << std::endl;
01149             //std::cout << std::hex << "PDO received:  " << (uint16_t)(m.Msg.ID - 0x180) << "  " << (uint16_t)m.Msg.DATA[0] << " " << (uint16_t)m.Msg.DATA[1] << " " << (uint16_t)m.Msg.DATA[2] << " " << (uint16_t)m.Msg.DATA[3] << " " << (uint16_t)m.Msg.DATA[4] << " " << (uint16_t)m.Msg.DATA[5] << " " << (uint16_t)m.Msg.DATA[6] << " " <<  (uint16_t)m.Msg.DATA[7] << " " << std::endl;
01150             if (incomingPDOHandlers.find(m.Msg.ID) != incomingPDOHandlers.end())
01151                 incomingPDOHandlers[m.Msg.ID](m);
01152         }
01153 
01154         // incoming SD0
01155         else if (m.Msg.ID >= 0x580 && m.Msg.ID <= 0x5FF)
01156         {
01157             //std::cout << std::hex << "SDO received:  " << (uint16_t)m.Msg.ID << "  " << (uint16_t)m.Msg.DATA[0] << " " << (uint16_t)m.Msg.DATA[1] << " " << (uint16_t)m.Msg.DATA[2] << " " << (uint16_t)m.Msg.DATA[3] << " " << (uint16_t)m.Msg.DATA[4] << " " << (uint16_t)m.Msg.DATA[5] << " " << (uint16_t)m.Msg.DATA[6] << " " << (uint16_t)m.Msg.DATA[7] << std::endl;
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         // incoming NMT error control
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             //std::cout << "Received unknown message" << std::endl;
01205         }
01206     }
01207 }
01208 
01209 /******************************************************************************
01210  * Define get errors function
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     else if(data[1]+(data[2]<<8) == 0x1009)
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     { //The incoming message is a result from a statusWord Request
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                     //if(volt_enable)
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         //std::cout << "Motor State of Device with CANid " << (uint16_t)CANid << " is: " << devices[CANid].getMotorState() << std::endl;
01585     }
01586 
01587     else if(data[1]+(data[2]<<8) == 0x22A2)
01588     { //This is a result from a temperature register request
01589         devices[CANid].setDriverTemperature(data[4]);
01590     }
01591 
01592     else if(data[1]+(data[2]<<8) == 0x6061)
01593     { //Incoming message is a mode of operation display
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  * Mapping for PDO1
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         //int32_t data = (0x00 << 16) + (0x00 << 24);
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 }


ipa_canopen_core
Author(s): Tobias Sing, Thiago de Freitas
autogenerated on Mon Oct 6 2014 00:59:25