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


ipa_canopen_core
Author(s): Tobias Sing, Thiago de Freitas
autogenerated on Thu Aug 27 2015 13:32:20