CANOpen_driver.cpp
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2010
00004  *
00005  * Fraunhofer Institute for Manufacturing Engineering   
00006  * and Automation (IPA)
00007  *
00008  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00009  *
00010  * Project name: 
00011  * ROS stack name: 
00012  * ROS package name: 
00013  * Description:
00014  *                                                              
00015  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00016  *                      
00017  * Author: 
00018  * Supervised by: 
00019  *
00020  * Date of creation: Jan 2010
00021  * ToDo:
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00034  *       Engineering and Automation (IPA) nor the names of its
00035  *       contributors may be used to endorse or promote products derived from
00036  *       this software without specific prior written permission.
00037  *
00038  * This program is free software: you can redistribute it and/or modify
00039  * it under the terms of the GNU Lesser General Public License LGPL as 
00040  * published by the Free Software Foundation, either version 3 of the 
00041  * License, or (at your option) any later version.
00042  * 
00043  * This program is distributed in the hope that it will be useful,
00044  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00045  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00046  * GNU Lesser General Public License LGPL for more details.
00047  * 
00048  * You should have received a copy of the GNU Lesser General Public 
00049  * License LGPL along with this program. 
00050  * If not, see <http://www.gnu.org/licenses/>.
00051  *
00052  ****************************************************************/
00053 
00054 //##################
00055 //#### includes ####
00056 
00057 // header
00058 #include <CANOpen_driver.h>
00059 
00060 // standard includes
00061 #include <stdlib.h> 
00062 
00063 /* ============================================================== */    
00064 /* ======================= public =============================== */    
00065 /* ============================================================== */    
00066 
00067 // Constructor
00068 CANOpenMaster::CANOpenMaster()
00069 {               
00070         //can_itf = new CANPeakSysUSB("/home/tim/git/care-o-bot/schunk_modular_robotics/CANOpen_driver/CanCtrl.ini");       
00071         CANObj = new CANOpenCiA401ObjDirectory();
00072         
00073         m_CanBaseAddress = 0x0c;
00074 
00075         TxSDO = 0x580 + m_CanBaseAddress;
00076         RxSDO = 0x600 + m_CanBaseAddress;
00077         TxPDO1 = 0x180 + m_CanBaseAddress;
00078         RxPDO1 = 0x200 + m_CanBaseAddress;
00079         TxPDO2 = 0x280 + m_CanBaseAddress;
00080         RxPDO2 = 0x300 + m_CanBaseAddress;
00081         TxPDO3 = 0x380 + m_CanBaseAddress;
00082         RxPDO3 = 0x400 + m_CanBaseAddress;
00083         TxPDO4 = 0x480 + m_CanBaseAddress;
00084         RxPDO4 = 0x500 + m_CanBaseAddress;      
00085         SYNC = 0x080; 
00086         EMCY = 0x080 + m_CanBaseAddress; 
00087         NMT = 0x000; 
00088         HEARTBEAT = 0x700 + m_CanBaseAddress; 
00089         
00090         NodeState = 0x05; 
00091         ControlerState = 0; 
00092         
00093         // motorcommands
00094         SWITCH_ON = 0x07; 
00095         SHUTDOWN = 0x06; 
00096         DISABLE_VOLTAGE = 0x00; 
00097         QUICKSTOP = 0x02;
00098         DISABLE_OPERATION = 0x07;
00099         ENABLE_OPERATION = 0x0F; 
00100         FAULT_RESET = 0x0080;  
00101         
00102         // motorstates
00103         Not_Ready_To_Switch_On = 0x0000;
00104         Switch_On_Disabled = 0x0040;
00105         Ready_To_Switch_On = 0x0021;
00106         Switched_On = 0x0023; 
00107         Operation_Enable = 0x0027; 
00108         Fault = 0x0008; 
00109         Fault_Reaction_Active = 0x000F;
00110         Quick_Stop_Active = 0x0007;     
00111         
00112         // statusvariables for state mashine
00113         IS_HOMED = false; 
00114         FAULT_WAS_ACTIVE = true; 
00115         
00116         // variabels for CAN-msg download header
00117         const int ciInitDownloadReq = 0x20;
00118         const int ciNrBytesNoData = 0x00;
00119         const int ciExpedited = 0x02;
00120         const int ciDataSizeInd = 0x01;
00121 
00122         CANDownloadHeader = ciInitDownloadReq | (ciNrBytesNoData << 2) | ciExpedited | ciDataSizeInd;
00123 
00124         Lin_Axis_max_speed = 83; //m/s
00125 }
00126 
00127 /*---------------------------------------------------------------*/
00128 // Destructor
00129 CANOpenMaster::~CANOpenMaster() 
00130 {
00131         delete can_itf; 
00132         delete CANObj;
00133 }
00134 
00135 /*---------------------------------------------------------------*/
00136 // Inits the CanOpen interface to the linear axis
00137 int CANOpenMaster::Init()
00138 {       
00139         
00140         usleep(500000);
00141         // wait for inital heardbeat (not neccessary for Schunk) 
00142 /*      while (timer<=timeout){if (WaitForHeartbeat()==0){break;} timer++;}
00143         if (timer==timeout){ROS_INFO("timeout on initial heardbeat of linear axis");  
00144                 return -1;
00145         } 
00146 */      
00147         //reset CAN-node 
00148         SendNMT(m_CanBaseAddress,0x01);         
00149 
00150         usleep(500000);
00151 
00152         // set COB_ID SYNC
00153 //      if (WriteObject(&CANObj->COB_ID_SYNC, CANObj->SYNC_CONSUMER + m_CanBaseAddress)!=0){return -1;}
00154         usleep(100000);
00155         
00156         // set COB_ID EMCY
00157 //      if (WriteObject(&CANObj->COB_ID_EMCY, CANObj->EMCY_EXIST + m_CanBaseAddress)!=0){return -2;}
00158         usleep(100000);
00159         
00160 
00161                 /* configure TPDO1 */
00162 /*      
00163                 // disable COB_ID TPDO1
00164                 WriteObject(&CANObj->COB_ID_TPDO1[1], 0x80000000 + TxPDO1);
00165                 usleep(200000);
00166                         
00167                 // disable mapping on TPDO1
00168                 if (WriteObject(&CANObj->PDO_MAP_TPDO1[0],0x0)!=0){return -5;}
00169                 usleep(200000); 
00170 
00171                 // map status to TPDO1
00172                 if (WriteObject(&CANObj->PDO_MAP_TPDO1[1],((CANObj->controlword.Index << 16) + (CANObj->controlword.SubIndex << 8) + 16 /*Lenght 16 Bit))!=0){return -6;}
00173                 usleep(200000);
00174 
00175                 // map interpolation_data_record to RPDO1
00176                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[2],0x60C10120)!=0){return -7;}
00177                 usleep(200000);
00178 
00179                 // enable mapping on RPDO1
00180                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[0],0x02)!=0){return -8;}
00181                 usleep(200000);
00182                 
00183                 // enable COB_ID TPDO1
00184                 WriteObject(&CANObj->COB_ID_TPDO1[1], TxPDO1);
00185                 usleep(200000);
00186 */
00187 
00188         /* configure RPDO1 */
00189 /*      
00190                 // disable COB_ID RPDO1
00191                 WriteObject(&CANObj->COB_ID_RPDO1[1], 0x80000000 + RxPDO1);
00192                 usleep(500000);
00193                         
00194                 // disable mapping on RPDO1
00195                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[0],0x0)!=0){return -5;}
00196                 usleep(500000); 
00197 
00198                 // map controlword to RPDO1
00199                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[1],((CANObj->controlword.Index << 16) + (CANObj->controlword.SubIndex << 8) + 16 /*Lenght 16 Bit))!=0){return -6;}
00200                 usleep(500000);
00201 
00202                 // map interpolation_data_record to RPDO1
00203                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[2],0x60C10120)!=0){return -7;}
00204                 usleep(200000);
00205 
00206                 // enable mapping on RPDO1
00207                 if (WriteObject(&CANObj->PDO_MAP_RPDO1[0],0x02)!=0){return -8;}
00208                 usleep(200000);
00209                 
00210                 // enable COB_ID RPDO1
00211                 if (WriteObject(&CANObj->COB_ID_RPDO1[1], RxPDO1)!=0){return -9;}
00212                 usleep(200000);
00213 */
00214         // set COB_ID TPDO2 and disable CH
00215 //      if (WriteObject(&CANObj->COB_ID_TPDO2[1],0x80000000 + TxPDO1)!=0){return -10;}
00216         usleep(100000);
00217 
00218         // set transmission type of RPDO2
00219 //      if (WriteObject(&CANObj->COB_ID_TPDO1[2], 0xFF)!=0){return -9;} // asynchronous
00220         usleep(100000);
00221 
00222 /* not implemented yet in PowerBall controller
00223 
00224         // set COB_ID TPDO3 and disable CH
00225 //      if (WriteObject(&CANObj->COB_ID_TPDO3[1],0x80000000 + TxPDO3)!=0){return -10;}
00226         usleep(100000);
00227 
00228         // set COB_ID RPDO3 and disable CH
00229 //      if (WriteObject(&CANObj->COB_ID_RPDO3[1],0x80000000 + RxPDO3)!=0){return -11;}
00230         usleep(100000);
00231 
00232         // set COB_ID TPDO4 and disable CH
00233 //      if (WriteObject(&CANObj->COB_ID_TPDO4[1],0x80000000 + TxPDO4)!=0){return -12;}
00234         usleep(100000);
00235 
00236         // set COB_ID RPDO4 and disable CH
00238         usleep(100000);
00239  */
00240         
00241         // set GIT to 10 ms
00242 //      if (WriteObject(&CANObj->Communication_cycle_period,0x00002710)!=0){return -26;}
00243         usleep(100000);
00244 /*      
00245         // set ip_sync_definition
00246         if (WriteObject(&CANObj->ip_sync_definition[1],0x00)!=0){return -27;} //general sync
00247         usleep(100000);
00248         
00249         // set ip_sync_definition
00250         if (WriteObject(&CANObj->ip_sync_definition[2],0x01)!=0){return -28;} //sync every event
00251         usleep(100000);
00252         
00253         // set ip_data_configuration
00254         if (WriteObject(&CANObj->ip_data_configuration[3],0x00)!=0){return -29;} //FIFO-buffer
00255         usleep(100000);
00256 
00257         // set ip_data_configuration
00258         if (WriteObject(&CANObj->ip_data_configuration[5],0x01)!=0){return -30;} //1 pos value
00259         usleep(100000);
00260 */      
00261         //initiate CAN-node (set in operational mode s.CiA301) 
00262         SendNMT(m_CanBaseAddress,0x01);         
00263         
00264         usleep(100000);
00265         
00266         return 0; 
00267 }
00268 
00269 /*---------------------------------------------------------------*/
00270 // home axis
00271 int CANOpenMaster::Homing()
00272 {       
00273         int timer = 0; 
00274         int referenced = 0; 
00275 
00276         // get mode of operation 
00277         try{std::cout << "mode: " << ReadObject(&CANObj->mode_of_operation_display) << std::endl;}
00278                         catch(int error) 
00279                         {ROS_INFO("Error on reading: %i",       error);return -1;}
00280         
00281         usleep(500000);
00282         
00283         // set mode of operation to homing
00284         if (WriteObject(&CANObj->mode_of_operation, CANObj->HOMING_MODE)!=0){return -2;}
00285 
00286         usleep(500000);
00287 
00288         // get mode of operation 
00289         try{std::cout << "mode: " << ReadObject(&CANObj->mode_of_operation_display) << std::endl;}
00290                         catch(int error) 
00291                         {ROS_INFO("Error on reading: %i",       error);return -3;}
00292 
00293 
00294         // wait for activating homing mode 
00295         while(timer<50)
00296         {       
00297                 try{
00298                         referenced = ReadObject(&CANObj->mode_of_operation_display); 
00299                         }
00300                         catch(int error) 
00301                         {ROS_INFO("Error on reading: %i",       error);return -4;}
00302                 
00303                 if(referenced == CANObj->HOMING_MODE){break;}
00304                 
00305                 timer++;
00306                 usleep(10000);
00307         }
00308 
00309         // start homing with sending controlword
00310         if (WriteObject(&CANObj->controlword, SHUTDOWN)!=0){return -5;}
00311         usleep(200000);
00312         // start homing with sending controlword
00313         if (WriteObject(&CANObj->controlword, SWITCH_ON)!=0){return -6;}
00314         usleep(200000);
00315         // start homing with sending controlword
00316         if (WriteObject(&CANObj->controlword, ENABLE_OPERATION)!=0){return -7;}
00317         usleep(200000);
00318         // start homing with sending controlword
00319         if (WriteObject(&CANObj->controlword, (0x0010 | ENABLE_OPERATION))!=0){return -8;}
00320         
00321         ROS_INFO("Homing Start");
00322         
00323         // wait finishing homing 
00324         while(timer<100)
00325         {       
00326                 try{
00327                         referenced = ReadObject(&CANObj->statusword); 
00328                         }
00329                         catch(int error) 
00330                         {ROS_INFO("Error on reading: %i",       error);return -9;}
00331                 
00332                 if((referenced & 0x1000) == 0x1000)
00333                 {       
00334                         break; 
00335                 }
00336                 
00337                 timer++;
00338                 usleep(100000);
00339         }
00340 
00341         // set mode of operation to IP-mode
00342         if (WriteObject(&CANObj->mode_of_operation, CANObj->IP_MODE)!=0){return -10;}
00343         
00344         // wait for activating IP mode 
00345         while(timer<500)
00346         {       
00347                 try{
00348                         referenced = ReadObject(&CANObj->mode_of_operation_display); 
00349                         }
00350                         catch(int error) 
00351                         {ROS_INFO("Error on reading: %i",       error);return -11;}
00352                 
00353                 if(referenced == CANObj->IP_MODE)
00354                 {
00355                         // get mode of operation 
00356                         try{std::cout << "mode: " << ReadObject(&CANObj->mode_of_operation_display) << std::endl;}
00357                         catch(int error) 
00358                         {ROS_INFO("Error on reading: %i",       error);return -12;}
00359                         
00360                         // start homing with sending controlword
00361                         if (WriteObject(&CANObj->controlword, ( FAULT_RESET | 0x0010 | ENABLE_OPERATION))!=0){return -13;}
00362                         usleep(500000);
00363 
00364                         std::cout << "Status: " << (ReadObject(&CANObj->statusword)) << std::endl; 
00365 
00366                         return 0;
00367                 }
00368                 
00369                 timer++;
00370                 usleep(1000);
00371         }
00372         
00373         return -14; 
00374         
00375 }
00376 
00377 /*---------------------------------------------------------------*/
00378 // send SYNC msg
00379 void CANOpenMaster::SendSYNC()
00380 {       
00381         CanMsg CMsgTr;
00382         
00383         CMsgTr.m_iLen = 0;
00384         CMsgTr.m_iID = SYNC;
00385 
00386         can_itf->transmitMsg(CMsgTr);
00387         
00388         //if(can_itf->receiveMsg(&CMsgTr)!=0)
00389         //{CMsgTr.print();}
00390 }
00391 
00392 /*---------------------------------------------------------------*/
00393 // set speed
00394 int CANOpenMaster::SetSpeed(int SpeedCmdMS)
00395 {       // Limit speed
00396         if (SpeedCmdMS > Lin_Axis_max_speed){SpeedCmdMS = Lin_Axis_max_speed;}
00397         if (SpeedCmdMS < -Lin_Axis_max_speed){SpeedCmdMS = -Lin_Axis_max_speed;}
00398         
00399         if (WriteObject(&CANObj->target_velocity, SpeedCmdMS)!=0){return -1;}
00400         return 0;
00401 }
00402 
00403 /*---------------------------------------------------------------*/
00404 // get speed
00405 int CANOpenMaster::GetSpeed()
00406 {       
00407         int SpeedMS; 
00408         try{SpeedMS = ReadObject(&CANObj->velocity_actual_value);}
00409         catch(int error){ROS_INFO("Error on reading: %i",error);return -1;}
00410         return SpeedMS;
00411 }
00412 
00413 /*---------------------------------------------------------------*/
00414 // get digital inputs
00415 int CANOpenMaster::GetDIn()
00416 {       
00417         int DIn; 
00418         try{DIn = ReadObject(&CANObj->digital_inputs);}
00419         catch(int error){ROS_INFO("Error on reading: %i",error);return -1;}
00420         return DIn;
00421 }
00422 
00423 /*---------------------------------------------------------------*/
00424 // recover from errors
00425 int CANOpenMaster::Recover()
00426 {       
00427         int nErr = 0, timer=0; 
00428         // read status
00429         EvaluateControlerState();
00430         
00431         while((ControlerState == Fault) || (ControlerState == Fault_Reaction_Active) || (ControlerState == Quick_Stop_Active))
00432         {       
00433                 // reset faults (positive edge of bit 7)
00434                 if (WriteObject(&CANObj->controlword, 0x00)!=0){return -1;}
00435                 usleep(500000);
00436         
00437                 if (WriteObject(&CANObj->controlword, FAULT_RESET)!=0){return -1;}
00438                 usleep(500000);
00439         
00440                 // read status
00441                 EvaluateControlerState();
00442                 
00443                 // timeout watchdog
00444                 if (timer>10)
00445                 {return -1;}
00446                 else 
00447                 {timer++;}
00448         }
00449                 
00450         if (ControlerState != Switch_On_Disabled)
00451         {ROS_INFO("error on transition to Switch_On_Disabled.Controllerstate = %i",ControlerState); 
00452                 try{
00453                 nErr = (0x0000FF00 & ReadObject(&CANObj->pre_defined_error_field[0])); 
00454                 }
00455                 catch(int error) 
00456                 {       std::cout << "Error on reading: " << error << std::endl;}
00457                 if (nErr != 0) 
00458                 {       std::cout << "There are Errors: " << std::endl; 
00459                         for (int i=0;i<nErr;i++)
00460                         {       try{std::cout << "Error" << i <<": " << ReadObject(&CANObj->pre_defined_error_field[i]) << std::endl;} 
00461                                 catch(int error) 
00462                                 {std::cout << "Error on reading: " << error << std::endl; return -1;}
00463                         }
00464                 }else{std::cout << "No Errors saved" << std::endl;}
00465                 return -1;
00466         }
00467         
00468         usleep(100000);
00469         
00470         // go to ready_to_switch_on
00471         if (WriteObject(&CANObj->controlword, SHUTDOWN)!=0){return -1;}
00472         
00473         usleep(100000);
00474         
00475         // read status
00476         if(EvaluateControlerState()!=0){return -1;} 
00477         if (ControlerState != Ready_To_Switch_On)
00478         {ROS_INFO("error on transition to Ready_To_Switch_On. Controllerstate = %i",ControlerState); return -1;}
00479         
00480         usleep(100000);
00481                 
00482         // go to Switched_On
00483         WriteObject(&CANObj->controlword, SWITCH_ON);
00484         
00485         usleep(100000);
00486         
00487         // read status
00488         if(EvaluateControlerState()!=0){return -1;} 
00489         if (ControlerState != Switched_On)
00490         {ROS_INFO("error on transition to Switched_On.Controllerstate = %i",ControlerState); return -1;}
00491         
00492         usleep(200000);
00493                 
00494         // go to Operation_Enable
00495         WriteObject(&CANObj->controlword, ENABLE_OPERATION);
00496         
00497         usleep(500000);
00498         
00499         // read status
00500         EvaluateControlerState(); 
00501         if (ControlerState != Operation_Enable)
00502         {ROS_INFO("error on transition to Operation_Enable."); return -1;}
00503         
00504         FAULT_WAS_ACTIVE = false; 
00505         
00506         return 0; 
00507 }
00508 
00509 /*---------------------------------------------------------------*/
00510 // get Nodestate
00511 int CANOpenMaster::GetNodeState()
00512 {       
00513         unsigned int status; 
00514         
00515         try{status = ReadObject(&CANObj->manufacturer_status_register);} 
00516         catch(int error){ std::cout << "Error: " << error << std::endl; return -1;}
00517         
00518         // print state  
00519                 // Bit 0 
00520                 if ((status & 1)==1)
00521                         {       std::cout << "Homing active" << std::endl; }
00522                 // Bit 1 
00523                 if ((status & 2)==2)
00524                         {       std::cout << "Homingswitch reached" << std::endl; }
00525                 // Bit 2 
00526                 if ((status & 4)==4)
00527                         {       std::cout << "negative endswitch reached" << std::endl; }
00528                 // Bit 3 
00529                 if ((status & 8)==8)
00530                         {       std::cout << "positive endswitch reached" << std::endl; }
00531                 // Bit 4 
00532                 if ((status & 16)==16)
00533                         {       std::cout << "positioning successfull" << std::endl; }          
00534                 // Bit 5 
00535                 if ((status & 32)==32)
00536                         {       std::cout << "target reached" << std::endl; }           
00537                 // Bit 6 
00538                 if ((status & 64)==64)
00539                         {       std::cout << "rest of positioning distance reached" << std::endl; }     
00540                 // Bit 7 
00541                 if ((status & 128)==128)
00542                         {       std::cout << "reversive mode" << std::endl; }   
00543                 // Bit 8 
00544                 if ((status & 256)==256)
00545                         {       std::cout << "rpm reached n_ist=(n_mel +/-n_mel_hyst)" << std::endl; }          
00546                 // Bit 9 
00547                 if ((status & 512)==512)
00548                         {       std::cout << "rpm reached n_ist=(n_soll +/-n_mel_hyst)" << std::endl; } 
00549                 // Bit 10 
00550                 if ((status & 1024)==1024)
00551                         {       std::cout << "Positioning started" << std::endl; }      
00552                 // Bit 11 
00553                 if ((status & 2048)==2048)
00554                         {       std::cout << "I²t, Current-limiting active" << std::endl; }    
00555                 // Bit 12 
00556                 if ((status & 4096)==4096)
00557                         {       std::cout << "SinCos producer active" << std::endl; }   
00558                 // Bit 13 
00559                 if ((status & 8192)==8192)
00560                         {       std::cout << "rpm reached n_ist=(0 +/-n_mel_hyst)" << std::endl; }      
00561                 // Bit 14 
00562                 if ((status & 16384)==16384)
00563                         {       std::cout << "rpm reached n_ist=(0 +/-n_mel_hyst)" << std::endl; }      
00564                 // Bit 15 
00565                 if ((status & 32768)==32768)
00566                         {       std::cout << "rpm reached n_ist=(0 +/-n_mel_hyst)" << std::endl; }      
00567                 // Bit 16
00568                 if ((status & 65536)==65536)
00569                         {       std::cout << "Warning" << std::endl; }  
00570                 // Bit 17
00571                 if ((status & 131072)==131072)
00572                         {       std::cout << "General Error present" << std::endl; }            
00573                 // Bit 18
00574                 if ((status & 262144)==262144)
00575                         {       std::cout << "negative direction resticted" << std::endl; }                     
00576                 // Bit 19
00577                 if ((status & 524288)==524288)
00578                         {       std::cout << "positiv direction resticted" << std::endl; }      
00579                 // Bit 20
00580                 if ((status & 1048576)==1048576)
00581                         {       std::cout << "Homeing done" << std::endl; }     
00582                 // Bit 21
00583                 if ((status & 2097152)==2097152)
00584                         {       std::cout << "automatic syncronization activ" << std::endl; }   
00585                 // Bit 22
00586                 if ((status & 4194304)==4194304)
00587                         {       std::cout << "MMC initiated" << std::endl; }    
00588                 // Bit 23
00589                 if ((status & 8388608)==8388608)
00590                         {       std::cout << "Amps enabled" << std::endl; }     
00591                 // Bit 24
00592                 if ((status & 16777216)==16777216)
00593                         {       std::cout << "controler and amps enabled" << std::endl; }       
00594                 // Bit 25
00595                 if ((status & 33554432)==33554432)
00596                         {       std::cout << "rpm desired value enabled" << std::endl; }                                
00597                 // Bit 26
00598                 if ((status & 67108864)==67108864)
00599                         {       std::cout << "emergency stop without positioinsensor" << std::endl; }           
00600                 // Bit 27
00601                 if ((status & 134217728)==134217728)
00602                         {       std::cout << "MOTID-Mode" << std::endl; }       
00603                 // Bit 28
00604                 if ((status & 268435456)==268435456)
00605                         {       std::cout << "write permission" << std::endl; }
00606                 // Bit 29
00607                 if ((status & 536870912)==536870912)
00608                         {       std::cout << "Technologiemodul present" << std::endl; }
00609                 // Bit 30
00610                 if ((status & 1073741824)==1073741824)
00611                         {       std::cout << "MMC pluged in" << std::endl; }
00612                 // Bit 31
00613                 if ((status & (unsigned int) 2147483648)== (unsigned int) 2147483648)
00614                         {       std::cout << "safe stop pluged in" << std::endl; }
00615                 
00616         return 0; 
00617 }
00618 
00619 /*---------------------------------------------------------------*/
00620 void CANOpenMaster::PrintMotorStatus()
00621 {
00622         CanMsg CMsgTr;
00623         const int ciInitUploadReq = 0x40;
00624 
00625         CMsgTr.m_iLen = 6;
00626         CMsgTr.m_iID = RxSDO;
00627 
00628         unsigned char cMsg[8];
00629 
00630         cMsg[0] = ciInitUploadReq;
00631         cMsg[1] = 0x41;
00632         cMsg[2] = 0x60;
00633         cMsg[3] = 0x00;
00634         cMsg[4] = 0x00;
00635         cMsg[5] = 0x00;
00636         cMsg[6] = 0x00;
00637         cMsg[7] = 0x00;
00638 
00639         CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
00640         can_itf->transmitMsg(CMsgTr);
00641 
00642         while (can_itf->receiveMsg(&CMsgTr)==0)
00643         {       
00644                 //std::cout << "waiting for statusreport" << std::endl;
00645                 CMsgTr.print();
00646                 usleep(500);
00647         }
00648         CMsgTr.print();
00649         if (CMsgTr.getAt(0) == 0x80)
00650         {       std::cout << "Error on status request. SDO Errorcode: " << std::hex << CMsgTr.getAt(7) << " " << std::hex << CMsgTr.getAt(6) << " " << std::hex << CMsgTr.getAt(5) << " " << std::hex << CMsgTr.getAt(4) << std::endl;
00651         }
00652         else
00653         {
00654                 short CurrState = ((CMsgTr.getAt(7)<<8)|CMsgTr.getAt(6)); 
00655                 //std::cout << CurrState << std::endl;
00656 
00657                 // bits 0-3 and 5-6 displays state of the motorcontoller
00658 
00659                         // Not_Ready_To_Switch_On (bit 5 doesn't matter) 
00660                         if ((CurrState & 0x004F)==0)
00661                         {       std::cout << "MotorState: Not_Ready_To_Switch_On" << std::endl; }
00662         
00663                         // Switch_On_Disabled (bit 5 doesn't matter) 
00664                         if ((CurrState & 0x004F)==0x0040)
00665                         {       std::cout << "MotorState: Switch_On_Disabled" << std::endl; }
00666         
00667                         // Ready_To_Switch_On 
00668                         if ((CurrState & 0x006F)==0x0021)
00669                         {       std::cout << "MotorState: Ready_To_Switch_On" << std::endl; }
00670         
00671                         // Switched_On 
00672                         if ((CurrState & 0x006F)==0x0023)
00673                         {       std::cout << "MotorState: Switched_On" << std::endl; }
00674         
00675                         // Operation_Enable 
00676                         if ((CurrState & 0x006F)==0x0027)
00677                         {       std::cout << "MotorState: Operation_Enable" << std::endl; }
00678         
00679                         // Fault (bit 5 doesn't matter) 
00680                         if ((CurrState & 0x004F)==0x0008)
00681                         {       std::cout << "MotorState: Fault" << std::endl; }
00682 
00683                         // Fault_Reaction_Active (bit 5 doesn't matter) 
00684                         if ((CurrState & 0x004F)==0x00F)
00685                         {       std::cout << "MotorState: Fault_Reaction_Active" << std::endl; }
00686         
00687                         // Quick_Stop_Active
00688                         if ((CurrState & 0x006F)==0x0007)
00689                         {       std::cout << "MotorState: Quick_Stop_Active" << std::endl; }
00690         
00691                 // bit 4 displays the voltage state
00692                 if ((CurrState & 0x0010)==0x0010)
00693                 {       std::cout << "voltage_enabled" << std::endl; } 
00694 
00695                 // bit 7 displays if there are warnings 
00696                 if ((CurrState & 0x0080)==0x0080)
00697                 {       std::cout << "There are Warnings! Check!" << std::endl; } 
00698 
00699                 // bit 8 is enabled if the drive moves 
00700                 if ((CurrState & 0x0100)==0x0100)
00701                 {       std::cout << "drive moves" << std::endl; } 
00702 
00703                 // bit 9 is set when remote control via can is active
00704                 if ((CurrState & 0x0200)==0x0200)
00705                 {       std::cout << "voltage_enabled" << std::endl; } 
00706 
00707                 // bit 10 is set if target position is reached 
00708                 //(point in point mode, velocity in speed mode) 
00709                 if ((CurrState & 0x0400)==0x0400)
00710                 {       std::cout << "target reached" << std::endl; }
00711 
00712                 // bit 11 is set when internal limits are reached 
00713                 if ((CurrState & 0x0800)==0x0800)
00714                 {       std::cout << "internal limits reached" << std::endl; } 
00715 
00716                 // bit 12 set_point_acknowladge / speed_0 / homing_attained / ip_mode_active
00717                 if ((CurrState & 0x1000)==0x1000)
00718                 {       std::cout << "set_point_acknowladge / speed_0 / homing_attained / ip_mode_active" << std::endl; }  
00719 
00720                 // bit 13 following_error / homing_error
00721                 if ((CurrState & 0x2000)==0x2000)
00722                 {       std::cout << "following_error / homing_error" << std::endl; } 
00723 
00724                 // bit 14 reserved 
00725 
00726                 // bit 15 drive referenced 
00727                 if ((CurrState & 0x8000)==0x8000)
00728                 {       std::cout << "drive referenced" << std::endl; } 
00729         }
00730 }
00731 
00732 /* ============================================================== */    
00733 /* ====================== private =============================== */    
00734 /* ============================================================== */    
00735 
00736 
00737 
00738 /*---------------------------------------------------------------*/
00739 // handle CAN Error 
00740 bool CANOpenMaster::CANError(CanMsg* CMsgTr)
00741 {       
00742         // error case for SDOs
00743         if (CMsgTr->getAt(0) == 0x80) 
00744         {
00745                 ROS_INFO("Error on CAN request: %i %i %i %i", CMsgTr->getAt(4), CMsgTr->getAt(5), CMsgTr->getAt(6), CMsgTr->getAt(7));
00746                 return true; 
00747         }
00748         
00749         return false;  
00750 }
00751 /*---------------------------------------------------------------*/
00752 // Nodestate Error (test if heardbeat message has changed)
00753 bool CANOpenMaster::NodeStateError(CanMsg* CMsgTr)
00754 {       
00755         // if Msg is Heartbeat 
00756         if (CMsgTr->m_iID == HEARTBEAT)  
00757         {       
00758                 //if Nodestate has changed send an error
00759                 if (CMsgTr->getAt(0) != NodeState)
00760                 {
00761                         ROS_INFO("Error! CAN-Node %i not operational. State: %i", m_CanBaseAddress, CMsgTr->getAt(0));
00762                         return true;
00763                 } 
00764                 //get next msg because heartbeat is evaluated
00765                 can_itf->receiveMsg(CMsgTr);
00766         }
00767         
00768         return false;  
00769 }
00770 /*---------------------------------------------------------------*/
00771 // read object from device
00772 unsigned int CANOpenMaster::ReadObject(CANOpenCiA401ObjDirectory::CANOpenObj* obj)
00773 {       
00774         CanMsg CMsgTr;
00775         
00776         int i, result = 0, timer = 0; 
00777         
00778         switch (obj->Format)
00779         {       case 0x2F : CMsgTr.m_iLen = 5;
00780                 case 0x2b : CMsgTr.m_iLen = 6;
00781                 case 0x23 : CMsgTr.m_iLen = 8;
00782         }
00783         
00784         CMsgTr.m_iID = RxSDO;
00785 
00786         unsigned char cMsg[8];
00787 
00788         cMsg[0] = 0x40; //for read always 0x40 
00789         cMsg[1] = obj->Index;           // low byte
00790         cMsg[2] = obj->Index >> 8;      // high byte
00791         cMsg[3] = obj->SubIndex;
00792         cMsg[4] = 0x00; 
00793         cMsg[5] = 0x00;
00794         cMsg[6] = 0x00;
00795         cMsg[7] = 0x00;
00796 
00797         CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
00798         
00799         if (can_itf->transmitMsg(CMsgTr) == 0)
00800         {throw -1; } 
00801 
00802         while(timer<1000)
00803         {               
00804                 can_itf->receiveMsg(&CMsgTr);
00805                 
00806                 if (NodeStateError(&CMsgTr)) {throw -2;}
00807                 
00808                 if (CANError(&CMsgTr)) {throw -3;}
00809                  
00810                 if((CMsgTr.getAt(0) == (obj->Format+0x20) ) && (CMsgTr.getAt(1)==cMsg[1]) && (CMsgTr.getAt(2)==cMsg[2]) && (CMsgTr.getAt(3)==cMsg[3]))
00811                 {
00812                         for(i=4;i<CMsgTr.m_iLen;i++)
00813                         {
00814                                 result += (CMsgTr.getAt(i) << (8*(i-4))); 
00815                         } 
00816                         return  result;  
00817                 }
00818                 timer++;
00819                 usleep(1000);
00820         }
00821         CMsgTr.print();
00822         throw -4; 
00823 }
00824 
00825 /*---------------------------------------------------------------*/
00826 // write object on device
00827 int CANOpenMaster::WriteObject(CANOpenCiA401ObjDirectory::CANOpenObj* obj, int val)
00828 {       
00829         CanMsg CMsgTr;
00830         
00831         int timer = 0; 
00832         
00833         switch (obj->Format)
00834         {       case 0x2F : CMsgTr.m_iLen = 5;
00835                 case 0x2b : CMsgTr.m_iLen = 6;
00836                 case 0x23 : CMsgTr.m_iLen = 8;
00837         }
00838         
00839         CMsgTr.m_iID = RxSDO;
00840 
00841         unsigned char cMsg[8];
00842 
00843         cMsg[0] = obj->Format;  //for read always 0x40 
00844         cMsg[1] = obj->Index;           // low byte
00845         cMsg[2] = obj->Index >> 8;      // high byte
00846         cMsg[3] = obj->SubIndex;
00847         cMsg[4] = val; 
00848         if (CMsgTr.m_iLen > 5){cMsg[5] = val >> 8;}else{cMsg[5] = 0;}
00849         if (CMsgTr.m_iLen > 6){cMsg[6] = val >> 16; cMsg[7] = val >> 24;}else{cMsg[6] = 0,cMsg[7] = 0;}
00850 
00851         CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
00852         
00853         if (can_itf->transmitMsg(CMsgTr) == 0)
00854         {return -1; } 
00855 
00856         // wait for ACK
00857         while(timer<1000)
00858         {       
00859                 can_itf->receiveMsg(&CMsgTr);
00860                 
00861                 if (NodeStateError(&CMsgTr)) {return -2;}
00862                 
00863                 if (CANError(&CMsgTr)) {return -3;}
00864                 
00865                 if((CMsgTr.getAt(0) == 0x60) && (CMsgTr.getAt(1)==cMsg[1]) && (CMsgTr.getAt(2)==cMsg[2]) && (CMsgTr.getAt(3)==cMsg[3]))
00866                 {
00867                         // ACK
00868                         return  0;  
00869                 }
00870                 timer++;
00871                 usleep(1000);
00872         }
00873         CMsgTr.print(); 
00874         return -4; 
00875 }
00876 
00877 /*---------------------------------------------------------------*/
00878 // write object PDO on bus
00879 int CANOpenMaster::WritePDO(CanMsg CMsgTr)
00880 {               
00881         //CMsgTr.print();
00882         if (can_itf->transmitMsg(CMsgTr) == 0)
00883         {return -1; } 
00884         
00885         return 0; 
00886 }
00887 
00888 /*---------------------------------------------------------------*/
00889 // write object PDO on bus
00890 int CANOpenMaster::WritePDO(int ControlWord, int IP_command)
00891 {       
00892         CanMsg CMsgTr;
00893         
00894         CMsgTr.m_iID = RxPDO1;
00895         CMsgTr.m_iLen = 8;
00896 
00897         unsigned char cMsg[8];
00898 
00899         cMsg[0] = (ControlWord >> 0); 
00900         cMsg[1] = (ControlWord >> 8);
00901         cMsg[2] = 0;
00902         cMsg[3] = 0;    
00903         cMsg[4] = (IP_command >> 0);
00904         cMsg[5] = (IP_command >> 8);
00905         cMsg[6] = (IP_command >> 16);
00906         cMsg[7] = (IP_command >> 24);
00907         
00908         CMsgTr.set(cMsg[0], cMsg[1], cMsg[2], cMsg[3], cMsg[4], cMsg[5], cMsg[6], cMsg[7]);
00909         
00910         //CMsgTr.print();
00911         if (can_itf->transmitMsg(CMsgTr) == 0)
00912         {return -1; } 
00913         
00914         // read Buffer for debug
00915 
00916         if(can_itf->receiveMsg(&CMsgTr)!=0)
00917         {CMsgTr.print();}
00918 
00919         return 0; 
00920 }
00921 
00922 
00923 /*---------------------------------------------------------------*/
00924 // send CAN-Network-Management commands to control the state-machine of the CAN-node
00925 void CANOpenMaster::SendNMT(unsigned char NodeID, unsigned char NMT_Command)
00926 {
00927         CanMsg CMsgTr;
00928 
00929         CMsgTr.m_iLen = 2;
00930         CMsgTr.m_iID = 0x000;
00931 
00932         unsigned char cMsg[2];
00933 
00934         cMsg[0] = NMT_Command;
00935         cMsg[1] = NodeID; 
00936 
00937         CMsgTr.set(cMsg[0], cMsg[1]);
00938         can_itf->transmitMsg(CMsgTr);
00939 }
00940 
00941 /*---------------------------------------------------------------*/
00945         int CANOpenMaster::WaitForHeartbeat()
00946         {
00947                 CanMsg CMsgTr;
00948                 int timer = 0; 
00949                 
00950                 while(timer<100)
00951                 {       can_itf->receiveMsg(&CMsgTr);
00952                         if(CMsgTr.m_iID == HEARTBEAT)
00953                         {return CMsgTr.getAt(0);}
00954                         timer++;
00955                         usleep(10000);
00956                 }
00957                 return -1; 
00958         }
00959 
00960 /*---------------------------------------------------------------*/
00961         // sets global variables of controller state
00962         int CANOpenMaster::EvaluateControlerState()
00963         {       
00964                 int CurrState; 
00965                 
00966                 try {CurrState = ReadObject(&CANObj->statusword);}
00967                 catch(int error){return error;}
00968                 
00969                 // bits 0-3 and 5-6 displays state of the motorcontoller
00970 
00971                         // Not_Ready_To_Switch_On (bit 5 doesn't matter) 
00972                         if ((CurrState & 0x004F)==Not_Ready_To_Switch_On)
00973                         {       ControlerState = Not_Ready_To_Switch_On;
00974                                 std::cout << "MotorState: Not_Ready_To_Switch_On" << std::endl; }
00975         
00976                         // Switch_On_Disabled (bit 5 doesn't matter) 
00977                         if ((CurrState & 0x004F)==Switch_On_Disabled)
00978                         {       ControlerState = Switch_On_Disabled;
00979                                 std::cout << "MotorState: Switch_On_Disabled" << std::endl; }
00980         
00981                         // Ready_To_Switch_On 
00982                         if ((CurrState & 0x006F)==Ready_To_Switch_On)
00983                         {       ControlerState = Ready_To_Switch_On;
00984                                 std::cout << "MotorState: Ready_To_Switch_On" << std::endl; }
00985         
00986                         // Switched_On 
00987                         if ((CurrState & 0x006F)==Switched_On)
00988                         {       ControlerState = Switched_On;
00989                                 std::cout << "MotorState: Switched_On" << std::endl; }
00990         
00991                         // Operation_Enable 
00992                         if ((CurrState & 0x006F)==Operation_Enable)
00993                         {       ControlerState = Operation_Enable;
00994                                 std::cout << "MotorState: Operation_Enable" << std::endl; }
00995         
00996                         // Fault (bit 5 doesn't matter) 
00997                         if ((CurrState & 0x004F)==Fault)
00998                         {       ControlerState = Fault;
00999                                 std::cout << "MotorState: Fault" << std::endl; }
01000 
01001                         // Fault_Reaction_Active (bit 5 doesn't matter) 
01002                         if ((CurrState & 0x004F)==Fault_Reaction_Active)
01003                         {       ControlerState = Fault_Reaction_Active;
01004                                 std::cout << "MotorState: Fault_Reaction_Active" << std::endl; }
01005         
01006                         // Quick_Stop_Active
01007                         if ((CurrState & 0x006F)==Quick_Stop_Active)
01008                         {       ControlerState = Quick_Stop_Active;
01009                                 std::cout << "MotorState: Quick_Stop_Active" << std::endl; }
01010         
01011                 // bit 4 displays the voltage state
01012                 if ((CurrState & 0x0010)==0x0010)
01013                 {       std::cout << "voltage_enabled" << std::endl; } 
01014 
01015                 // bit 7 displays if there are warnings 
01016                 if ((CurrState & 0x0080)==0x0080)
01017                 {       std::cout << "There are Warnings! Check!" << std::endl; } 
01018 
01019                 // bit 8 is enabled if the drive moves 
01020                 if ((CurrState & 0x0100)==0x0100)
01021                 {       std::cout << "drive moves" << std::endl; } 
01022 
01023                 // bit 9 is set when remote control via can is active
01024                 if ((CurrState & 0x0200)==0x0200)
01025                 {       std::cout << "voltage_enabled" << std::endl; } 
01026 
01027                 // bit 10 is set if target position is reached 
01028                 //(point in point mode, velocity in speed mode) 
01029                 if ((CurrState & 0x0400)==0x0400)
01030                 {       std::cout << "target reached" << std::endl; }
01031 
01032                 // bit 11 is set when internal limits are reached 
01033                 if ((CurrState & 0x0800)==0x0800)
01034                 {       std::cout << "internal limits reached" << std::endl; } 
01035 
01036                 // bit 12 set_point_acknowladge / speed_0 / homing_attained / ip_mode_active
01037                 if ((CurrState & 0x1000)==0x1000)
01038                 {       std::cout << "set_point_acknowladge / speed_0 / homing_attained / ip_mode_active" << std::endl; }  
01039 
01040                 // bit 13 following_error / homing_error
01041                 if ((CurrState & 0x2000)==0x2000)
01042                 {       std::cout << "following_error / homing_error" << std::endl; } 
01043 
01044                 // bit 14 reserved 
01045 
01046                 // bit 15 drive referenced 
01047                 if ((CurrState & 0x8000)==0x8000)
01048                 {       std::cout << "drive referenced" << std::endl; } 
01049                 
01050         return 0;
01051         }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines


CANOpen_driver
Author(s): Tim Fröhlich
autogenerated on Mon Jan 14 2013 16:55:42