rlCanOpen Class Reference

main class which provides canopen API functions and manages all nodes. More...

#include <rlcanopen.h>

List of all members.

Public Member Functions

 rlCanOpen ()
 rlCanOpen (char *_inifilename)
 ~rlCanOpen ()
int getBoardCount ()
 returns the number of available boards
int getActiveBoard ()
 returns the number of currently active board
bool showNodeConfiguration (int _boardnr, int _nodeid)
 prints out the configuration of a specific node
bool showNodeConfiguration ()
 prints out the configuration off all available nodes from all boards
int sdo_read (int _boardnr, int _nodeid, int _objectindex, int _subindex, rlCanOpenTypes &_sdo_data)
 read a certain object from the object dictionary of a node
int sdo_write (int _boardnr, int _nodeid, int _objectindex, int _subindex, rlCanOpenTypes &_sdo_data)
 write data into a certain object from the object dictionary of a node
int pdo_receive (int _boardnr, int _nodeid, int _pdonr, int _mappingnr, rlCanOpenTypes &_pdo_data)
 using the pdo_receive function you can receive a mapped object within PDO
int pdo_receive (int _boardnr, int _nodeid, int _pdonr, rlCanOpenTypes &_pdo_data)
 using the pdo_receive function you can receive a PDO (Process Data Object)
int pdo_transmit (int _boardnr, int _nodeid, int _pdonr, int _mappingnr, rlCanOpenTypes &_pdo_data)
 transmit a mapped object within a PDO to a specific node
int pdo_transmit (int _boardnr, int _nodeid, int _pdonr, rlCanOpenTypes &_pdo_data)
 transmit a 8 Byte PDO to a specific node
int getNodeIndex (int _boardnr, int _nodeid, int &_index)
 this function returns the listindex of a desired node
int getObjectType (int _boardnr, int _nodeid, int _objectindex, int _subindex)
 returns daemontype number of a specific object
int getNodeState (int _boardnr, int _nodeid, rlCanOpenTypes &_data)
 use this function to get information about a specific node
int restartBoard (int _boardnr, int _restarttype)
 using this function you are able to restart a CanOpenMaster board
int sendNMTCommand (int _boardnr, int _nodeid, unsigned char _cmd)
 send a NMT Command to one or all nodes (of one board)
bool is_twisted_type (int _canopentype)

Private Member Functions

bool getNodeConfiguration (int _nodeID)
int getPdoID (int _boardnr, int _nodeid, int _objektindex, int _direction)
 return PdoId of mapped object.
void read_inifile (const char *_filename)
 read properties of inifile
bool ini ()
 initialize nodes and create nodelist
void delmsg ()
 clear message struct by setting all elements to zero
bool iniboards ()
 Read informations about installed devices.
short setBoardActive (int _boardnr)
 sets a desired CanOpenMaster active, so that it can be used
int refreshMappingList (int _boardnr, int _nodeid, int _pdoID, int _pdoDirection)
int createNodes ()
 Search for nodes in all boards and append it into the nodelist.
int createMappingObjects (int _boardid, int _nodeid, int _pdoDirection)
 this function writes the mapping objects for each pdo of a node

Private Attributes

int activeboard
 the currently active board
char err_out_buf [255]
 this string buffer is usually written with sprintf before sent to stdout
short sRet
 return value for hilscher specific message functions
FILE * err_fp
 Pointer to error logfile.
QString logFileName
 name of logfile stdout is redirected to
RCS_MESSAGETELEGRAM_10 message
 hilscher specific message structur which will be sent to the master card
QPtrVector< rlCanNodenodelist
 this list contains all nodes from all boards
int boardcount
 the current count of CanOpenMaster cards
unsigned char messagenr
 message counter
bool enableLogging

Detailed Description

main class which provides canopen API functions and manages all nodes.

This class contains a canopen specific API which accesses the canopen bus through the bus-independ Hilscher device API. It reads the configuration which has to be written previously to the device by SyCon. Based on this configuration data it searches node corresponding EDS files to create object directories. These help to enshure type security and cast warnings when users try to write incorrect data types to can nodes.

Definition at line 55 of file rlcanopen.h.


Constructor & Destructor Documentation

rlCanOpen::rlCanOpen (  ) 

Definition at line 40 of file rlcanopen.cpp.

00041 {
00042   rlDebugPrintf("Constructer nodes class\n");
00043   read_inifile("./canopen.ini");
00044   if (enableLogging){
00045     FILE* fp;
00046     fp = freopen (logFileName.ascii(),"w",stdout); // redirekt stdout to textfile
00047     
00048     /* enable linebuffering in order to write every line to the file immediately */
00049     setvbuf ( fp , NULL , _IOFBF , 1024 ); 
00050   }
00051   ini();
00052 }

rlCanOpen::rlCanOpen ( char *  _inifilename  ) 

Definition at line 29 of file rlcanopen.cpp.

00030 {
00031   rlDebugPrintf("Constructer nodes class\n");
00032   read_inifile(_inifilename);
00033   if (enableLogging){
00034     freopen (logFileName.ascii(),"w",stdout); // redirekt stdout to textfile
00035   }
00036   ini();
00037 }

rlCanOpen::~rlCanOpen (  ) 

Definition at line 54 of file rlcanopen.cpp.

00055 {
00056   rlDebugPrintf("destruktor rlCanOpen\n");
00057   for (int i=0;i<boardcount;i++)
00058     DevExitBoard(i);
00059 
00060 #ifdef RLWIN32
00061   DevCloseDriver(0);
00062 #else
00063   DevCloseDriver();
00064 #endif    
00065   if (enableLogging)    
00066     fclose (stdout);
00067   
00068 }


Member Function Documentation

int rlCanOpen::createMappingObjects ( int  _boardid,
int  _nodeid,
int  _pdoDirection 
) [private]

this function writes the mapping objects for each pdo of a node

creates the mappings for each pdo

Definition at line 137 of file rlcanopen.cpp.

00138 {
00139   int pdomax = 0;
00140   if (_pdoDirection == DIRECTION_RECEIVE)
00141     pdomax = nodelist[nodelist.size()-1]->getReceivePdoCount();
00142   else if(_pdoDirection == DIRECTION_TRANSMIT)
00143     pdomax = nodelist[nodelist.size()-1]->getTransmitPdoCount();
00144     
00145   for (int j = 1;j<=pdomax;j++)    //each receive/transmit pdo
00146   if(refreshMappingList(_boardid,_nodeid,j,_pdoDirection)==0) return 0;
00147   return 1;
00148 
00149 }   

int rlCanOpen::createNodes (  )  [private]

Search for nodes in all boards and append it into the nodelist.

this function checks the bus for available nodes and creates a corresponding nodelist

Definition at line 103 of file rlcanopen.cpp.

00104 {
00105  int nodeid;
00106   for (int boardid = 0;boardid<boardcount;boardid++)
00107   {
00108     setBoardActive(boardid);
00109     for(nodeid = 0; nodeid <= MAX_NODES; nodeid++)  // from node 0..127
00110       if (getNodeConfiguration(nodeid)) // writes received node-configuration 
00111                                         // into class-global message-struct
00112       {
00113         // new node found. insert it into the nodelist
00114         nodelist.resize( nodelist.size() + 1 );   
00115         
00116         // append the new node in the list
00117         nodelist.insert( nodelist.size()-1, 
00118                          new rlCanNode(boardid,nodeid,message));
00119         
00120        //append Mapping data                                  
00121         if (nodelist[nodelist.size()-1]->hasMapping()){
00122           if(!createMappingObjects(boardid,nodeid,DIRECTION_TRANSMIT))return 0;
00123           if(!createMappingObjects(boardid,nodeid,DIRECTION_RECEIVE))return 0;
00124         }
00125         else
00126         {
00127           rlDebugPrintf("WARNING: no Mapping available on node %d.", nodeid);
00128           rlDebugPrintf("Probably EDS file couldn't be found in EDS directory.\n");
00129         }
00130       }             
00131   }
00132   return 1;
00133 }

void rlCanOpen::delmsg (  )  [private]

clear message struct by setting all elements to zero

this function resets all elements of global message struct to zero

Definition at line 859 of file rlcanopen.cpp.

00859                       {
00860   message.rx            =0;
00861   message.tx            =0;
00862   message.ln            =0;
00863   message.nr            =0;
00864   message.a             =0;
00865   message.f             =0;
00866   message.b             =0;
00867   message.e             =0;
00868   message.device_adr    =0;
00869   message.data_area     =0;
00870   message.data_adr      =0;
00871   message.data_idx      =0;
00872   message.data_cnt      =0;
00873   message.data_type     =0;
00874   message.function      =0;
00875   
00876   for (int i = 0; i < MAX_SDO_BUFFERSIZE; i++)
00877     message.d[i] = 0;
00878 
00879 }

int rlCanOpen::getActiveBoard (  ) 

returns the number of currently active board

returns the currently active board

Definition at line 296 of file rlcanopen.cpp.

00297 {
00298   return activeboard;
00299 }                                                                                                                                                                                

int rlCanOpen::getBoardCount (  ) 

returns the number of available boards

returns the current count of available CanOpenMaster cards

Definition at line 211 of file rlcanopen.cpp.

00212 {
00213   return boardcount;
00214 }  

bool rlCanOpen::getNodeConfiguration ( int  _nodeID  )  [private]

This function reads out the configuration of a specific node using special Hilscher commands (CMDCODE_GET_CONFIGURATION). If the master board isn't configurated by SyCon it is not possibly to use this function with success. It returns false if the node is not available

Device Number

Pointer to user buffer

Timeout

Definition at line 217 of file rlcanopen.cpp.

00218 {
00219   //build message       
00220   message.rx            = CAN_TASK; 
00221   message.tx            = USER_AT_HOST;
00222   message.ln            = 8;
00223   message.nr            =messagenr++; 
00224   message.a             =0; 
00225   message.f             =0;
00226   message.b             =CMDCODE_GET_CONFIGURATION;
00227   message.e             =0x00;  //fragmentation
00228   message.device_adr    =_nodeID;  
00229   message.data_area     =0; 
00230   message.data_adr      =0; 
00231   message.data_idx      =0; 
00232   message.data_cnt      =0; 
00233   message.data_type     =0; 
00234   message.function      =0;
00235   
00236   //put configuration request
00237   DevPutMessage(0, (MSG_STRUC *)&message,5000L) ;  
00238   
00239   //receive answer message
00240   sRet = DevGetMessage (  0,                       
00241                           sizeof(message),      
00242                           (MSG_STRUC *)&message,   
00243                           2000L );                 
00244 
00245   unsigned char msgnrlocal = messagenr -1;
00246   
00247   // receive correct answer 
00248   if((message.a == RESPONSE_CODE_GET_CONFIGURATION) && (message.nr == msgnrlocal))
00249     if (message.f == ERRCODE_NOERROR) // node active, no error
00250       if(message.e == 0x00) //configuration fits in the message
00251       {
00252         sprintf(err_out_buf, "Board %d node %d is active. No problems found\n", 
00253           getActiveBoard(), _nodeID);
00254         
00255         rlDebugPrintf(err_out_buf);
00256         return 1;
00257       }
00258       else
00259       {
00260          sprintf(err_out_buf, "Board %d node %d is active. \n", 
00261            getActiveBoard(), _nodeID);
00262            
00263          rlDebugPrintf(err_out_buf);
00264          rlDebugPrintf("Configuration data does not fit in one message,\n");
00265          rlDebugPrintf("so the current node does not include the complete data\n");
00266          rlDebugPrintf(" - multiplex configration data is not yet implemented!!! -\n");
00267          return 1;
00268       } 
00269     else return 0;
00270   else 
00271   {
00272     sprintf(err_out_buf, "---->message.a=%d, message.nr=%d unsere msg nr: %d\n", 
00273       message.a, message.nr, msgnrlocal);
00274       
00275     rlDebugPrintf(err_out_buf);
00276     sprintf(err_out_buf, "%s\n", "Communication ERROR!!!");
00277     rlDebugPrintf(err_out_buf);
00278     return 0;
00279   }
00280 }

int rlCanOpen::getNodeIndex ( int  _boardnr,
int  _nodeid,
int &  _index 
)

this function returns the listindex of a desired node

Because the nodes of all boards are stored in one list, the listindex is not equal to the nodeID(1-127). Use this function to get the listindex of a desired node

Definition at line 882 of file rlcanopen.cpp.

00883 {
00884   for(unsigned int i = 0; i < nodelist.size(); i++)
00885   {
00886     if ((nodelist[i]->getNodeID() == _nodeid) && 
00887         (nodelist[i]->getBoardID() == _boardnr))
00888     {
00889       _index = i;
00890       return true;
00891     }           
00892   }
00893   return false; 
00894 }

int rlCanOpen::getNodeState ( int  _boardnr,
int  _nodeid,
rlCanOpenTypes _data 
)

use this function to get information about a specific node

Use this function to get information about a specific node. The nodestate, nodeerror and a nodestateFlag will be written to the rlCanOpenTypes. Read the rlCanOpenTypes.h header to get further information about these variables. Hilscher specific function (so no CanOpoen services) are used to receive the information

Definition at line 1045 of file rlcanopen.cpp.

01046 { 
01047  
01048  setBoardActive(_boardnr);
01049  
01050  COM_ND_DIAGNOSTICS * diag;
01051  diag = (COM_ND_DIAGNOSTICS*) &message.d[0];
01052 
01053   message.rx = CAN_TASK         ;//receiver = user at HOST
01054   message.tx = USER_AT_HOST     ;// transmitter = USR_INTF-Task
01055   message.ln = 8                ;//length of message
01056   message.nr = messagenr++      ;//number of the message
01057   message.a  = 0                ;//no answer
01058   message.f  = 0                ;//error, status
01059   message.b  = CMDCODE_Node_Diag;//command = COM_Node_Diag
01060   message.e =0                  ;//extension
01061   message.device_adr = _nodeid  ;//k Rem_Adr
01062   message.data_area = 0         ;// data area, unused
01063   message.data_adr  = 0         ;//data address, unused
01064   message.data_idx  = 0         ;//data index, unused
01065   message.data_cnt  = 0         ;//data count, unused
01066   message.data_type = 5         ;// data type byte string
01067   message.function =  1         ;//function read
01068   
01069   
01070  if ( (sRet = DevPutMessage(_boardnr, (MSG_STRUC *)&message, 5000L)) 
01071        == DRV_NO_ERROR )
01072  {
01073    while( (sRet = DevGetMessage(_boardnr, sizeof(message), 
01074                                 (MSG_STRUC *)&message, 0)) 
01075           == DRV_DEV_GET_NO_MESSAGE )       
01076    {
01077      continue;
01078    }
01079    if ( sRet == DRV_NO_ERROR )
01080    {
01081      rlDebugPrintf("message successfully received\n");
01082      // continue;
01083    }
01084    else
01085    {
01086      rlDebugPrintf("Error  Message (f = %d))\n",message.f);
01087      rlDebugPrintf("\nDevGetMessage(%d, sizeof(message), &message, 500): %d\n",
01088              _boardnr, (int)sRet);
01089              
01090      return 0;
01091     } 
01092   }
01093   else
01094   {
01095     rlDebugPrintf("\nDevPutMessage(%d, &message, 5000): %d\n",_boardnr, (int)sRet);
01096     return 0;
01097   }   
01098   _data.set_nodestateFlags( diag->bNodeStatus_1.bNodeNoResponse, 
01099                             diag->bNodeStatus_1.bEmcyBuffOverflow,
01100                             diag->bNodeStatus_1.bPrmFault, 
01101                             diag->bNodeStatus_1.bGuardActive,
01102                             diag->bNodeStatus_1.bDeactivated );
01103                        
01104   _data.set_nodestate(diag->bNodeState);
01105   _data.set_nodeerror(diag->bActualError);
01106                        
01107   _data.set_DaemonType(rlCanOpenTypes::RL_NODESTATE);
01108   
01109   return 1;
01110 }

int rlCanOpen::getObjectType ( int  _boardnr,
int  _nodeid,
int  _objectindex,
int  _subindex 
)

returns daemontype number of a specific object

returns daemontype number of an object. The type is retrieved from the node's objectdir. When no objectdir exists (e.g. because of a missing EDS file) or when the requested object does not exist, this function will return 0xFF (the corresponding value to rlCanOpenTypes::RL_NOTYPE)

Definition at line 897 of file rlcanopen.cpp.

00901 {
00902   int nodeindex;
00903   if (getNodeIndex(_boardnr, _nodeid, nodeindex)){
00904     if (nodelist[nodeindex]->hasMapping())
00905       return nodelist[nodeindex]->objecttype(_objectindex, _subindex);
00906     else
00907       return rlCanOpenTypes::RL_BUFFER;
00908   }
00909   else{
00910     return rlCanOpenTypes::RL_NOTYPE;
00911   }
00912 }

int rlCanOpen::getPdoID ( int  _boardnr,
int  _nodeid,
int  _objektindex,
int  _direction 
) [private]

return PdoId of mapped object.

this function iterates through the recieve/tramsmit pdo lists and returns the ID number of the pdo that fits the given objektindex. The PdoId identifies the send/receive PDO on the given node

Definition at line 1015 of file rlcanopen.cpp.

01018                                         {
01019   int pdomax=0;
01020   int nodeindex=0;
01021   int madress=0;
01022   // get index of node in nodelist depending on boardid and nodeid
01023   // index is stored in nodeindex variable
01024   getNodeIndex(_boardnr, _nodeid, nodeindex); 
01025   
01026   // get number of elements in particular PDO list
01027   if (_direction == DIRECTION_RECEIVE)
01028     pdomax = nodelist[nodeindex]->getReceivePdoCount();
01029   if (_direction == DIRECTION_TRANSMIT)
01030     pdomax = nodelist[nodeindex]->getTransmitPdoCount();
01031    
01032    /* iterate through every element of particular list until mapping 
01033       object adress matches given objectindex */
01034    for (int j=1;j<=pdomax;j++)  
01035    {                                                                                                    
01036       
01037      madress = nodelist[nodeindex]->pdoList[_direction][j-1]->mappingOvAdress;    
01038      if (madress == _objektindex)
01039        return j;  
01040    }
01041    return 0;
01042 }

bool rlCanOpen::ini (  )  [private]

initialize nodes and create nodelist

Definition at line 71 of file rlcanopen.cpp.

00072 {
00073   messagenr = 0;
00074   nodelist.setAutoDelete(true);
00075 
00076   time_t rawtime;
00077   struct tm * timeinfo;
00078   time ( &rawtime );
00079   timeinfo = localtime ( &rawtime );
00080 
00081   sprintf(err_out_buf, "\nnew session startet: %s\n", asctime(timeinfo));
00082   rlDebugPrintf(err_out_buf);
00083  
00084   if (iniboards()){
00085     rlDebugPrintf("at least one board initialize!\n");
00086   }
00087   else
00088   {
00089     rlDebugPrintf("no board available or no board could be initialized correctly!\n");
00090     rlDebugPrintf("Programm -> Close\n");
00091     exit(0); 
00092   }
00093   
00094   // search for active nodes and create them
00095   
00096   createNodes();
00097   
00098  
00099   return 1;
00100 }

bool rlCanOpen::iniboards (  )  [private]

Read informations about installed devices.

Definition at line 154 of file rlcanopen.cpp.

00155 {
00156   
00157   int currentboardcount=0;
00158   
00159   BOARD_INFO tBoardInfo;
00160 
00161 #ifdef RLWIN32
00162     if ( (sRet = DevOpenDriver(0)) == DRV_NO_ERROR) 
00163 #else
00164     if ( (sRet = DevOpenDriver()) == DRV_NO_ERROR) 
00165 #endif    
00166   {
00167     // Driver successfully opend, read board information
00168 #ifdef RLWIN32
00169     if ( (sRet = DevGetBoardInfo( 0, sizeof(tBoardInfo), &tBoardInfo)) != DRV_NO_ERROR) 
00170 #else
00171     if ( (sRet = DevGetBoardInfo( &tBoardInfo)) != DRV_NO_ERROR) 
00172 #endif    
00173           {
00174           // Function error
00175             rlDebugPrintf( "DevGetBoardInfo RetWert = %5d \n", sRet );
00176           } else 
00177           {
00178             // Information successfully read, save for further use
00179             // Check out which boards are available
00180             for ( int usIdx = 0; usIdx < MAX_DEV_BOARDS; usIdx++)
00181             {
00182               if ( tBoardInfo.tBoard[usIdx].usAvailable == TRUE) {
00183               // Board is configured, try to init the board
00184                 sRet = DevInitBoard(
00185 #ifdef RLWIN32
00186                 tBoardInfo.tBoard[usIdx].usBoardNumber, NULL);
00187 #else
00188                 tBoardInfo.tBoard[usIdx].usBoard);
00189 #endif    
00190                 if ( sRet != DRV_NO_ERROR) {
00191                   // Function error
00192                   rlDebugPrintf( "DevInitBoard RetWert = %5d \n", sRet );
00193                 } else {
00194                 // DEVICE is available and ready............
00195                 currentboardcount++;
00196                        }
00197               }
00198             }
00199           }
00200    }
00201   boardcount = currentboardcount;       
00202  
00203   if (currentboardcount!=0)
00204     return 1;   
00205   else
00206    return 0;    
00207 }

bool rlCanOpen::is_twisted_type ( int  _canopentype  ) 

Definition at line 1226 of file rlcanopen.cpp.

01227 {
01228   switch (_canopentype){
01229   
01230     case rlCanOpenTypes::INTEGER24_t :return true;  
01231     case rlCanOpenTypes::INTEGER40_t :return true;  
01232     case rlCanOpenTypes::INTEGER48_t :return true;  
01233     case rlCanOpenTypes::INTEGER56_t :return true;  
01234     case rlCanOpenTypes::UNSIGNED24_t:return true;  
01235     case rlCanOpenTypes::UNSIGNED40_t:return true;  
01236     case rlCanOpenTypes::UNSIGNED48_t:return true; 
01237     case rlCanOpenTypes::UNSIGNED56_t:return true;   
01238     default                          :return false;
01239   };
01240 
01241 }

int rlCanOpen::pdo_receive ( int  _boardnr,
int  _nodeid,
int  _pdonr,
rlCanOpenTypes _pdo_data 
)

using the pdo_receive function you can receive a PDO (Process Data Object)

using the pdo_receive function you can receive a PDO (Process Data Object), which is send from the specific node to the canOpen master card. The data will be written to the rlCanOpenTypes class. This function doesn't use mapping. So the whole 8Byte PDO data, will be received. To read out use the rlCanOpenTypes::get_buffer({0-7}) function

Definition at line 637 of file rlcanopen.cpp.

00641 {
00642    
00643    int nodeindex;
00644    if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00645    {
00646      sprintf(err_out_buf, "ERROR: specified node does not exist! PDO \
00647                            receive failed! BoardId: %d NodeId: %d PDO \
00648                            ID: %d\n", _boardnr, _nodeid, _pdonr);
00649      rlDebugPrintf(err_out_buf);
00650      
00651      //cout<<"ERROR: specified node does not exist!\n";
00652      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00653      return 0;
00654    }
00655    
00656    if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT].size() < (unsigned int) _pdonr){
00657      sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! \
00658                            PDO receive failed! BoardId: %d NodeId: \
00659                            %d PDO ID: %d\n", _boardnr, _nodeid, _pdonr);
00660      rlDebugPrintf(err_out_buf);
00661 
00662      //cout<<"PDO ID does not exists!\n";
00663      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_PDOID);
00664      return 0;
00665    }
00666    
00667    int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->bPDOSize;
00668    
00669    int pdooffset = nodelist[nodeindex]->
00670                                 pdoList[DIRECTION_TRANSMIT][_pdonr-1]->usPDOAddress;
00671    
00672    //cout<<"\nsize ="<<pdosize<<" offset = "<<pdooffset;
00673      
00674    if ( (sRet =  DevExchangeIO( _boardnr, // Board NO
00675                   0,                      //offset send data
00676                   0,                      //Length of the send IO data
00677                   NULL,                   //Pointer to the user send data buffer
00678                   pdooffset,              //Byte offset in the receive IO data area
00679                   pdosize,                //Length of the receive IO data
00680                   &_pdo_data.pdobuffer[0],//Pointer to the user read data buffer
00681                   100L)                   //timeout in milliseconds
00682         ) == DRV_NO_ERROR)
00683    {
00684      _pdo_data.pdobuf2buf();
00685      //rlDebugPrintf("PDO recieve successfull!\n");
00686      _pdo_data.set_rlmsgerr(ERRCODE_NOERROR);
00687      return 1;
00688    
00689    }
00690    sprintf(err_out_buf, "ERROR: PDO receive failed! \
00691                          BoardId: %d NodeId: %d PDO \
00692                          ID: %d\n", _boardnr, _nodeid, _pdonr);
00693    rlDebugPrintf(err_out_buf);
00694 
00695    //rlDebugPrintf("ERROR: PDO RECEIVE FAILED\n");
00696    _pdo_data.set_rlmsgerr(ERRCODE_PDORCV_FAIL);
00697      return 0;                          
00698 }

int rlCanOpen::pdo_receive ( int  _boardnr,
int  _nodeid,
int  _pdonr,
int  _mappingnr,
rlCanOpenTypes _pdo_data 
)

using the pdo_receive function you can receive a mapped object within PDO

using the pdo_receive function you can receive a PDO (Process Data Object), which is send from the specific node to the device. The enquired object will be written to the rlCanOpenTypes class. The mapping is only available if mapping is configurated during the node creation of the rlcanopen constructer. Therefore a eds file (electronic data sheet) is needed. Use the cannode::hasMapping() function to check if mapping is available. To read out the correct value from this class use one of the get_TYPE() {e.g. get_int() } functions you can assert the type in the class using rlCanOpenTypes::get_DaemonType();

Definition at line 544 of file rlcanopen.cpp.

00549 {
00550  
00551  int nodeindex;
00552  unsigned char buffer[8];
00553  
00554  if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00555  {
00556    rlDebugPrintf("ERROR: specified node does not exist! PDO receive failed!");
00557    rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n", 
00558      _boardnr, _nodeid, _pdonr, _mappingnr);
00559      
00560    _pdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00561    return 0;
00562  }
00563  if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT].size() < (unsigned int) _pdonr){
00564    rlDebugPrintf("ERROR: specified PDO ID does not exist! PDO receive failed!");
00565    rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n", 
00566      _boardnr, _nodeid, _pdonr, _mappingnr);
00567    
00568    _pdo_data.set_rlmsgerr(ERRCODE_INVALID_PDOID);
00569    return 0;
00570  }
00571  else if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr -1]->mappingList.size() 
00572           < (unsigned int) _mappingnr){
00573    rlDebugPrintf("ERROR: specified Mappingnr does not exist! PDO receive failed!");
00574    rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n", 
00575      _boardnr, _nodeid, _pdonr, _mappingnr);
00576      
00577    _pdo_data.set_rlmsgerr(ERRCODE_INVALID_MAPID);
00578    return 0;
00579  }      
00580  
00581  // PDO No.1 has the index 0 !!!
00582  int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->bPDOSize;      
00583  int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->usPDOAddress; 
00584  
00585  //cout<<"size ="<<pdosize<<" offset = "<<pdooffset<<"\n";
00586  
00587  if ( (sRet =  DevExchangeIO( _boardnr,   // Board NO
00588                       0,                  //offset send data
00589                       0,                  //Length of the send IO data
00590                       NULL,               //Pointer to the user send data buffer
00591                       pdooffset,          //Byte offset in the receive IO data area
00592                       pdosize,            //Length of the receive IO data
00593                       &buffer[0],         //Pointer to the user read data buffer
00594                       100L)               //timeout in milliseconds
00595       ) == DRV_NO_ERROR)
00596  {
00597    
00598    int length_in_byte = nodelist[nodeindex]->
00599          pdoList[DIRECTION_TRANSMIT][_pdonr-1]->mappingList[_mappingnr-1]->length/8;
00600            
00601    int position_in_byte = nodelist[nodeindex]->
00602          pdoList[DIRECTION_TRANSMIT][_pdonr-1]->mappingList[_mappingnr-1]->position/8; 
00603          
00604    _pdo_data.clearBuffer();
00605    
00606    for(int i = position_in_byte; i< length_in_byte+position_in_byte;i++)
00607    {
00608         _pdo_data.set_buffer(i-position_in_byte,buffer[i]);
00609    }
00610         
00611    _pdo_data.set_DaemonType( nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->
00612           mappingList[_mappingnr-1]->etype);
00613      
00614        
00615    _pdo_data.set_rlmsgerr(ERRCODE_NOERROR);
00616    
00617    
00618     // if CanOpen-Type is a twistet integer (etc. 52Bit ) the value will be converted
00619    int canopentype = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->
00620           mappingList[_mappingnr-1]->canopentype;
00621            
00622    if (is_twisted_type(canopentype))
00623      _pdo_data.translate_CanOpenType(canopentype);   
00624    
00625    return 1;  
00626  }
00627  rlDebugPrintf("ERROR: PDO receive failed!");
00628  rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n", 
00629    _boardnr, _nodeid, _pdonr, _mappingnr);
00630  
00631  _pdo_data.set_rlmsgerr(ERRCODE_PDORCV_FAIL);
00632  
00633   return 0;     
00634 }

int rlCanOpen::pdo_transmit ( int  _boardnr,
int  _nodeid,
int  _pdonr,
rlCanOpenTypes _pdo_data 
)

transmit a 8 Byte PDO to a specific node

Using the pdo_transmit function you can transmit a PDO (Process Data Object) to a specific node. The desired data must be written to the rlCanOpenTypes class. This function does not support mapping. So the whole 8byte PDO data, will be send to write to the rlCanOpenTypes use the rlCanOpenTypes::set_buffer({0-7}) function

Definition at line 806 of file rlcanopen.cpp.

00810 {
00811    int nodeindex;
00812    _pdo_data.buf2pdobuf();
00813    
00814    if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00815    {
00816      sprintf(err_out_buf, "ERROR: specified node does not exist! PDO transmit\
00817                            failed! BoardId: %d NodeId: %d PDO ID: %d \n",
00818                             _boardnr, _nodeid, _pdonr);
00819                             
00820      rlDebugPrintf(err_out_buf);
00821      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00822      return 0;
00823    }
00824    if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE].size() < (unsigned int) _pdonr){
00825      sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! PDO \
00826                            transmit failed! BoardId: %d NodeId: %d PDO \
00827                            ID: %d \n", _boardnr, _nodeid, _pdonr);
00828      rlDebugPrintf(err_out_buf);
00829      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_PDOID);
00830      return 0;
00831    }
00832    
00833    int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->bPDOSize;
00834    int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->usPDOAddress; 
00835    
00836    if ( (sRet =  DevExchangeIO( _boardnr,       // Board NO
00837                         pdooffset,              //offset send data
00838                         pdosize,                //Length of the send IO data
00839                         &_pdo_data.pdobuffer[0],//Pointer to the user send data buffer
00840                         0,                      //Byte offset in the receive IO data area
00841                         0,                      //Length of the receive IO data
00842                         NULL,                   //Pointer to the user read data buffer
00843                         100L)                   //timeout in milliseconds
00844         ) == DRV_NO_ERROR)
00845    {
00846      _pdo_data.set_rlmsgerr(ERRCODE_NOERROR);
00847      return 1;
00848    }
00849    sprintf(err_out_buf, "ERROR: PDO transmit failed! BoardId: %d NodeId: %d \
00850                          PDO ID: %d \n", _boardnr, _nodeid, _pdonr);
00851    rlDebugPrintf(err_out_buf);
00852    
00853    _pdo_data.set_rlmsgerr(ERRCODE_PDOSND_FAIL);
00854     return 0;                           
00855 }

int rlCanOpen::pdo_transmit ( int  _boardnr,
int  _nodeid,
int  _pdonr,
int  _mappingnr,
rlCanOpenTypes _pdo_data 
)

transmit a mapped object within a PDO to a specific node

Using the pdo_transmit function you can transmit a PDO (Process Data Object) to a specific node. The desired data must be written to the rlCanOpenTypes class. The mapping is only available if mapping is configurated during the node creation of the rlcanopen constructer. Therefore an eds file (electronic data sheet) is needed. Use the cannode::hasMapping() function to check if mapping is available

Definition at line 703 of file rlcanopen.cpp.

00708 {
00709    int nodeindex;
00710    if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00711    {
00712      sprintf(err_out_buf, "ERROR: specified node does not exist! PDO transmit \
00713                            failed! BoardId: %d NodeId: %d PDO ID: %d Mappingnr:\
00714                             %d\n", _boardnr, _nodeid, _pdonr, _mappingnr);
00715      rlDebugPrintf(err_out_buf);
00716      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00717      return 0;
00718    }
00719    if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE].size() < (unsigned int) _pdonr){
00720      sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! PDO transmit\
00721                            failed! BoardId: %d NodeId: %d PDO ID: %d Mappingnr:\
00722                             %d\n", _boardnr, _nodeid, _pdonr, _mappingnr);
00723      rlDebugPrintf(err_out_buf);
00724         
00725      //cout<<"PDO ID does not exists!\n";
00726      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_PDOID);
00727      return 0;
00728    }
00729    else if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr -1]->mappingList.size()
00730               < (unsigned int) _mappingnr){
00731      sprintf(err_out_buf, "ERROR: specified mappingnr does not exist! PDO \
00732                            transmit failed! BoardId: %d NodeId: %d PDO \
00733                            ID: %d Mappingnr: %d\n", 
00734                            _boardnr, _nodeid, _pdonr, _mappingnr);
00735      rlDebugPrintf(err_out_buf);
00736 
00737      //cout<<"mapping ID does not exists!\n";
00738      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_MAPID);
00739      return 0;
00740    }    
00741    
00742    // PDO No.1 has the index 0 !!!
00743    int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->bPDOSize; 
00744    int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->usPDOAddress;
00745 
00746    int length_in_byte = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
00747                           mappingList[_mappingnr-1]->length/8;
00748                           
00749    int position_in_byte = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
00750                           mappingList[_mappingnr-1]->position/8; 
00751    
00752    if (_pdo_data.get_DaemonType() != (nodelist[nodeindex]->
00753                pdoList[DIRECTION_RECEIVE][_pdonr-1]->mappingList[_mappingnr-1]->etype))
00754    {  
00755      
00756      sprintf(err_out_buf, "ERROR: invalid type! Expected type: %d  Your Type:\
00757                             %d! PDO transmit failed! BoardId: %d NodeId: %d \
00758                             PDO ID: %d Mappingnr: %d\n", 
00759           nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
00760             mappingList[_mappingnr-1]->etype, 
00761           _pdo_data.get_DaemonType(), _boardnr, _nodeid, _pdonr, _mappingnr);
00762        
00763        
00764      rlDebugPrintf(err_out_buf);
00765      _pdo_data.get_DaemonType();
00766      _pdo_data.set_rlmsgerr(ERRCODE_INVALID_RLTYPE);
00767      return 0;
00768    }
00769    
00770     _pdo_data.buf2pdobuf();
00771    
00772    // no conversion necessary. correct length in mapping list
00773 
00774    pdooffset = pdooffset + position_in_byte;
00775    pdosize = length_in_byte;
00776    
00777    
00778    
00779    //cout<<"size ="<<pdosize<<" offset = "<<pdooffset<<"\n";
00780    
00781    if ( (sRet =  DevExchangeIO( _boardnr,       // Board NO
00782                         pdooffset,              //offset send data
00783                         pdosize,                //Length of the send IO data
00784                         &_pdo_data.pdobuffer[0],//Pointer to the user send data buffer
00785                         0,                      //Byte offset in the receive IO data area
00786                         0,                      //Length of the receive IO data
00787                         NULL,                   //Pointer to the user read data buffer
00788                         100L)                   //timeout in milliseconds
00789         ) == DRV_NO_ERROR)
00790    {
00791      _pdo_data.set_rlmsgerr(0);
00792      //rlDebugPrintf("PDO transmit successful! \n");
00793      return 1;  
00794    }
00795    sprintf(err_out_buf, "ERROR: PDO transmit failed! BoardId: %d NodeId: %d \
00796                          PDO ID: %d Mappingnr: %d\n", 
00797                          _boardnr, _nodeid, _pdonr, _mappingnr);
00798    rlDebugPrintf(err_out_buf);
00799    
00800    _pdo_data.set_rlmsgerr(ERRCODE_PDOSND_FAIL);
00801    return 0;    
00802 }

void rlCanOpen::read_inifile ( const char *  _filename  )  [private]

read properties of inifile

read properties of inifile. EDS path, logfile location and user-specific options are set on startup

Definition at line 1189 of file rlcanopen.cpp.

01189                                                  {
01190   rlIniFile ini;   
01191   QString buffer;
01192   if (ini.read(_filename)!=-1){
01193     rlDebugPrintf("used inifile: %s\n", _filename);
01194     
01195     // read EDS directory location
01196     buffer=QString(ini.text("DIRECTORIES","EdsDir"));
01197     buffer.remove((char) ACSII_CODE_CARRIAGE_RETURN);
01198     rlDebugPrintf("EdsDir: %s\n", buffer.ascii());
01199     // store EDS directory location in environmet variable
01200 #ifdef RLWIN32
01201     SetEnvironmentVariable("EdsDir", buffer.ascii());
01202 #else
01203     setenv("EdsDir", buffer.ascii(), 1);
01204 #endif    
01205     
01206     // read Logfilename
01207     logFileName=QString(ini.text("DIRECTORIES","LogFileName"));
01208     logFileName.remove((char) ACSII_CODE_CARRIAGE_RETURN);
01209     rlDebugPrintf("Log Filename: %s\n", logFileName.ascii());
01210     
01211     // read loggin-option 
01212     buffer=QString(ini.text("OPTIONS","enableLoggin"));
01213     if (buffer.contains("yes", false)==1)
01214       enableLogging=true;  
01215     else
01216       enableLogging=false;  
01217   }
01218   else
01219   {
01220     logFileName=  "./outfile.txt";
01221     rlDebugPrintf("ERROR: INIFILE NOT FOUND\n");
01222   }
01223 }

int rlCanOpen::refreshMappingList ( int  _boardnr,
int  _nodeid,
int  _pdoID,
int  _pdoDirection 
) [private]

if the user changes the mapping of a node using SDO functions, the internal mapping list should be changed

Definition at line 917 of file rlcanopen.cpp.

00921 {
00922   //rlDebugPrintf("refresh mappinglist1\n");
00923   int nodeindex;
00924   int madress=0;
00925   
00926    
00927     madress = nodelist[nodelist.size()-1]->
00928                 pdoList[_pdoDirection][_pdoID -1]->mappingOvAdress;
00929       
00930   if (getNodeIndex(_boardnr,_nodeid,nodeindex)== false) 
00931   {
00932     sprintf(err_out_buf, "ERROR: specified node does not exist! refresh \
00933                           mapping list failed! BoardId: %d NodeId: %d \
00934                           PDO ID: %d \n", _boardnr, _nodeid, _pdoID);
00935     rlDebugPrintf(err_out_buf);
00936     return 0;
00937   }
00938   
00939  
00940   if(nodelist[nodeindex]->pdoList[_pdoDirection].size() < (unsigned int) _pdoID)
00941   {
00942     sprintf(err_out_buf, "ERROR: PDO does not exist! refresh \
00943                           mapping list failed! BoardId: %d NodeId: %d \
00944                           PDO ID: %d \n", _boardnr, _nodeid, _pdoID);
00945     rlDebugPrintf(err_out_buf);
00946     return 0;
00947   }
00948    
00949   //append Mapping data                                 
00950   rlCanOpenTypes sdobuffer;                            
00951   int mappingcount;
00952   rlCanMapping * mappingobject; 
00953                                             
00954   //get mapping count                       
00955   if (sdo_read(_boardnr,_nodeid,madress,0,sdobuffer) == 0){
00956     sprintf(err_out_buf, "ERROR: read sdo data! refresh mapping list failed! \
00957                           BoardId: %d NodeId: %d PDO ID: %d \n", 
00958                           _boardnr, _nodeid, _pdoID);
00959     rlDebugPrintf(err_out_buf);
00960   }
00961   
00962   mappingcount = sdobuffer.get_uchar();   
00963   
00964   sprintf(err_out_buf, "Current mappingcount: %d\n", mappingcount);
00965   rlDebugPrintf(err_out_buf);                                           
00966   
00967   nodelist[nodeindex]->pdoList[_pdoDirection][_pdoID-1]->
00968                   mappingList.resize(mappingcount);
00969 
00970   int currentposition = 0;
00971   for (int mcount = 1; mcount <= mappingcount;mcount++)  //each mappingobject
00972   {
00973     mappingobject = new rlCanMapping;  //create new mappingobject in memory
00974     mappingobject->mappingId = mcount;
00975         
00976    
00977    if (sdo_read(_boardnr,_nodeid,madress,mcount,sdobuffer) == 0){
00978      sprintf(err_out_buf, "ERROR: read sdo data! refresh mapping list failed! \
00979                            BoardId: %d NodeId: %d PDO ID: %d \n", 
00980                            _boardnr, _nodeid, _pdoID);
00981      rlDebugPrintf(err_out_buf);
00982      //cout<<"Error during create Mappinglist!\n";
00983     }
00984        
00985     //get length of mapping object
00986     int mlength  = sdobuffer.get_buffer(0);
00987     mappingobject->length = mlength;
00988     
00989     //calculate the mapping position
00990     if (mcount>1)
00991       mappingobject->position = currentposition;         
00992     else       
00993       mappingobject->position = 0;           
00994     currentposition+=mlength;
00995     
00996     // get the ov adress of the current mapped object
00997     int mi  = (int) (sdobuffer.get_buffer(3)*pow(256,1) 
00998                                           + sdobuffer.get_buffer(2));
00999                                           
01000     unsigned char msi = sdobuffer.get_buffer(1);
01001         
01002     rlCanOpenTypes temptype;
01003     mappingobject->etype = temptype.canOpenType2DeamonType
01004                            (nodelist[nodelist.size()-1]->objecttype(mi, msi));
01005         
01006     // insert the mappingobject to mappinglist
01007     nodelist[nodeindex]->pdoList[_pdoDirection][_pdoID-1]->
01008                          mappingList.insert(mcount-1,mappingobject);
01009        
01010   }
01011   return 1;                                                   
01012 }                                                               

int rlCanOpen::restartBoard ( int  _boardnr,
int  _restarttype 
)

using this function you are able to restart a CanOpenMaster board

Using this function you are able to restart a CanOpenMaster board (device). There are 3 possibly kinds of restarting the master: coldstart, warmstart, bootstart. The corresponding 'defines' are declared in canopenstructs.h Hilscher specific function (so no CanOpoen services) are used to execute this command

Definition at line 1114 of file rlcanopen.cpp.

01115 {
01116    //COLDSTART           2
01117    //WARMSTART           3
01118    //BOOTSTART           4
01119    
01120    if ( (sRet = DevReset(_boardnr, _restarttype, 5000L) != DRV_NO_ERROR ))
01121   {
01122     rlDebugPrintf("restart failed!\n");
01123     rlDebugPrintf("DevReset(%d, Restart, 5000): %d\n", _boardnr, sRet);
01124     return 0;
01125   }
01126   
01127    rlDebugPrintf("restart successfully\n");
01128    return 1;
01129 }

int rlCanOpen::sdo_read ( int  _boardnr,
int  _nodeid,
int  _objectindex,
int  _subindex,
rlCanOpenTypes _sdo_data 
)

read a certain object from the object dictionary of a node

using the sdo_read function you can read a certain object from the object dictionary of a node. For this the SDO (Service Data Object) service will be used. The enquired object will be written to the rlCanOpenTypes class. To read out the correct value from this class use one of the get_TYPE() {e.g. get_int() } functions. You can assert the type in the class using rlCanOpenTypes::get_DaemonType(); if sdo_read failures the current error can be read out using rlCanOpenTypes::get_rlmsgerr()

Definition at line 332 of file rlcanopen.cpp.

00337 {
00338     int datalength;
00339     int canopentype;
00340     int nodeindex; 
00341     
00342     if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00343     {
00344       rlDebugPrintf("ERROR: specified node does not exist! SDO write failed!");
00345       rlDebugPrintf("BoardId: %d NodeId: %d Objektindex: %d Subindex: %d\n", 
00346         _boardnr, _nodeid, _objectindex, _subindex);
00347         
00348       _sdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00349       return 0;
00350     }
00351 
00352 
00353     delmsg();
00354     setBoardActive(_boardnr);
00355     
00356     message.rx          = CAN_TASK; 
00357     message.tx          = USER_AT_HOST;
00358     message.ln          = 8;
00359     message.nr          = messagenr++; 
00360     message.a           = 0; 
00361     message.f           = 0;
00362     message.b           = CMDCODE_SDO_UPDOWNLOAD;
00363     message.e           = 0;
00364     message.device_adr  = _nodeid;  
00365     message.data_area   = 0; 
00366     message.data_adr    = _objectindex; 
00367     message.data_idx    = _subindex; 
00368     message.data_cnt    = 0; 
00369     message.data_type   = 0; 
00370     message.function    = TASK_TFC_READ; 
00371  
00372    if(DevPutMessage(0, (MSG_STRUC *)&message,5000L) != DRV_NO_ERROR) return 0;
00373    
00374    delmsg();
00375    // receive the answer
00376   
00377    sRet = DevGetMessage( getActiveBoard(),                       // Device Number            
00378                          sizeof(message), 
00379                          (MSG_STRUC *)&message,   // Pointer to user buffer  
00380                          2000L );                 // Timeout   
00381    unsigned char msgnrlocal;
00382    msgnrlocal = messagenr - 1;                       
00383    
00384    // receive correct answer   
00385    if((message.a == CMDCODE_SDO_UPDOWNLOAD)&&(message.nr == msgnrlocal)){ 
00386       _sdo_data.set_rlmsgerr(message.f);
00387       if (message.f == ERRCODE_NOERROR) // node active, no error
00388       {
00389         canopentype=getObjectType(_boardnr, _nodeid, _objectindex, _subindex);
00390         if (canopentype!=rlCanOpenTypes::RL_NOTYPE){
00391           _sdo_data.set_CanOpenType(canopentype);
00392           datalength = _sdo_data.getLength();
00393         }
00394         else 
00395         {
00396           _sdo_data.set_DaemonType(rlCanOpenTypes::RL_BUFFER);
00397           datalength = MAX_SDO_BUFFERSIZE;
00398         }
00399         _sdo_data.clearBuffer();   
00400         for(int i = 0; i < datalength; i++)
00401           _sdo_data.set_buffer(i, message.d[i]);         
00402         
00403         // if CanOpen-Type is a twistet integer (etc. 52Bit ) the value will be converted
00404         if ((is_twisted_type(canopentype)) && (nodelist[nodeindex]->hasMapping()))
00405           _sdo_data.translate_CanOpenType(canopentype);
00406         
00407         return 1;
00408       }
00409       else
00410       {
00411         rlDebugPrintf("message.f = %d  message.f = %x Hex \n", message.f, message.f);
00412       }
00413     }
00414     else
00415     {
00416       rlDebugPrintf("message.a = %d message.nr = %d vergleich mit: %d\n", 
00417          message.a, message.nr, msgnrlocal);
00418          
00419       _sdo_data.set_rlmsgerr(-1);
00420     }
00421     rlDebugPrintf("ERROR during read SDO message!");
00422     rlDebugPrintf("BoardId: %d NodeId: %d Obj: %x Sub: %x\n", 
00423       _boardnr, _nodeid, _objectindex, _subindex);
00424       
00425       
00426     return 0;
00427 }

int rlCanOpen::sdo_write ( int  _boardnr,
int  _nodeid,
int  _objectindex,
int  _subindex,
rlCanOpenTypes _sdo_data 
)

write data into a certain object from the object dictionary of a node

using the sdo_write function you can write to a certain object from the object dictionary of a node. For this the SDO (Service Data Object) Service will be used. The relevant data must be written into the rlCanOpenTypes class before. To write the data into the rlCanOpenTypes class use one of the datatype depending functions like rlCanOpenTypes::set_int(int _value); if sdo_write failures the current error can be read out using rlCanOpenTypes::get_rlmsgerr()

Definition at line 431 of file rlcanopen.cpp.

00436 {
00437     int length;
00438     int pdoid;
00439     length = _sdo_data.getLength();
00440     int nodeindex;
00441     if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0) 
00442     {
00443       rlDebugPrintf("ERROR: specified node does not exist! SDO write failed!");
00444       rlDebugPrintf("BoardId: %d NodeId: %d Objektindex: %d Subindex: %d\n", 
00445         _boardnr, _nodeid, _objectindex, _subindex);
00446       
00447       _sdo_data.set_rlmsgerr(ERRCODE_INVALID_NODEID);
00448       return 0;
00449     }
00450     
00451     // if CanOpen-Type is a twistet integer (etc. 52Bit ) the datalength must be adjusted
00452     int canopentype = getObjectType(_boardnr, _nodeid, _objectindex, _subindex);
00453    
00454     if ((is_twisted_type(canopentype)) && (nodelist[nodeindex]->hasMapping()))
00455       length = _sdo_data.get_CanOpenTypeLength(canopentype);
00456    
00457      for(int i = 0;i<length;i++)
00458         message.d[i] = _sdo_data.get_buffer(i);
00459 
00460     
00461     setBoardActive(_boardnr);
00462     
00463     message.rx          = CAN_TASK; 
00464     message.tx          = USER_AT_HOST;
00465     message.ln          = 8+ length;
00466     message.nr          = messagenr++; 
00467     message.a           = 0; 
00468     message.f           = 0;
00469     message.b           = CMDCODE_SDO_UPDOWNLOAD;
00470     message.e           = 0;
00471     message.device_adr  = _nodeid;  
00472     message.data_area   = 0; 
00473     message.data_adr    = _objectindex; 
00474     message.data_idx    = _subindex; 
00475     message.data_cnt    = length; 
00476     message.data_type   = 0; 
00477     message.function    = TASK_TFC_WRITE; 
00478     
00479     if(DevPutMessage(0, (MSG_STRUC *)&message,5000L) != DRV_NO_ERROR) return 0;
00480          
00481     
00482   // receive the answer
00483   
00484   sRet = DevGetMessage ( _boardnr,                // Device Number            
00485                          sizeof(message), 
00486                          (MSG_STRUC *)&message,   // Pointer to user buffer  
00487                          2000L );                 // Timeout   
00488    
00489    unsigned char msgnrlocal = messagenr - 1;
00490    
00491    // receive correct answer   
00492    if((message.a == CMDCODE_SDO_UPDOWNLOAD)&&(message.nr == msgnrlocal)){  
00493       _sdo_data.set_rlmsgerr(message.f);
00494       if (message.f == ERRCODE_NOERROR) // node active, no error
00495       {
00496         //check if the mapping has changed
00497         if( (_objectindex >= TRANSMIT_PDO_MAPPING_STARTADRESS) &&
00498             (_objectindex <= TRANSMIT_PDO_MAPPING_MAXADRESS) && 
00499             (nodelist[nodeindex]->hasMapping()) )
00500         { 
00501           rlDebugPrintf("Mapping has changed: boardid %d, nodeid %d, objectindex %x\n", 
00502             _boardnr, _nodeid, _objectindex);
00503             
00504           pdoid = getPdoID(_boardnr, _nodeid, _objectindex, DIRECTION_TRANSMIT);
00505           refreshMappingList(_boardnr,_nodeid,pdoid,DIRECTION_TRANSMIT);
00506         }
00507         else if ( (_objectindex >= RECEIVE_PDO_MAPPING_STARTADRESS) && 
00508                   (_objectindex <= RECEIVE_PDO_MAPPING_MAXADRESS) &&
00509                   (nodelist[nodeindex]->hasMapping()) )
00510         {
00511           rlDebugPrintf("Mapping has changed: boardid %d, nodeid %d, objectindex %x\n", 
00512             _boardnr, _nodeid, _objectindex);
00513           pdoid = getPdoID(_boardnr, _nodeid, _objectindex, DIRECTION_RECEIVE);
00514           refreshMappingList(_boardnr,_nodeid,pdoid,DIRECTION_RECEIVE);
00515         }
00516         return 1;
00517       }
00518       else
00519       {
00520         sprintf(err_out_buf, "message.f = %d  message.f = %x Hex \n", 
00521           message.f, message.f);
00522           
00523         rlDebugPrintf(err_out_buf);
00524         _sdo_data.set_rlmsgerr(message.f);
00525       }
00526     }
00527     else
00528     {
00529       _sdo_data.set_rlmsgerr(-1);
00530       sprintf(err_out_buf, "message.a = %d message.nr = %d vergleich mit: %d\n", 
00531         message.a, message.nr, msgnrlocal);
00532         
00533       rlDebugPrintf(err_out_buf);
00534     }
00535     rlDebugPrintf("ERROR during read SDO message!");
00536     rlDebugPrintf("BoardId: %d NodeId: %d Obj: %x Sub: %x\n", 
00537       _boardnr, _nodeid, _objectindex, _subindex);
00538       
00539     rlDebugPrintf(err_out_buf);
00540     return 0;
00541 }

int rlCanOpen::sendNMTCommand ( int  _boardnr,
int  _nodeid,
unsigned char  _cmd 
)

send a NMT Command to one or all nodes (of one board)

Using this function you can send a NMT Command to one or all nodes (of one board). NMT (Network Management) is a CanOpen service. Because of the device there are constrictions for the user. You can only execute the follow NMT commands: START_REMOTE_NODE, STOP_REMOTE_NODE, ENTER_PREOPERATIONAL, RESET_NODE, RESET_COMMUNICATION The corresponding 'defines' are declared in canopenstructs.h

Definition at line 1132 of file rlcanopen.cpp.

01133 {
01134   MSG_STRUC message;
01135   setBoardActive(_boardnr);
01136   
01137   message.rx = CAN_TASK         ;//receiver = user at HOST
01138   message.tx = USER_AT_HOST     ;// transmitter = USR_INTF-Task
01139   message.ln = 2                ;//length of message
01140   message.nr = messagenr++      ;//number of the message
01141   message.a  = 0                ;//no answer
01142   message.f  = 0                ;//error, status
01143   message.b  = CMD_NMT_Module_Protocol;//command = COM_Node_Diag
01144   message.e =  0                ;//extension
01145 
01146         // NMT Command specifier
01147         //1     Start Remote Node
01148         //2     Stop Remote Node
01149         //128   Enter Pre-Operational
01150         //129   Reset Node
01151         //130   Reset Communication
01152   message.data[0] = _cmd                ;//NMT Command specifier
01153   message.data[1] = _nodeid     ;//NodeID
01154   
01155    if ( (sRet = DevPutMessage(_boardnr, (MSG_STRUC *)&message, 5000L)) 
01156          == DRV_NO_ERROR )
01157  {
01158    while( (sRet = DevGetMessage(_boardnr, sizeof(message), 
01159                                (MSG_STRUC *)&message, 0)) 
01160            == DRV_DEV_GET_NO_MESSAGE )
01161    {
01162      continue;
01163    }
01164    if ( sRet == DRV_NO_ERROR )
01165    {
01166      rlDebugPrintf("NMT message successfully received\n");
01167      // continue;
01168    }
01169    else
01170    {
01171      rlDebugPrintf("Error  Message (f = %d))\n",message.f);
01172      rlDebugPrintf("\nDevGetMessage(%d, sizeof(message), &message, 500): %d\n",
01173              _boardnr, (int)sRet);
01174      
01175      return 0;
01176     }
01177   }
01178   else
01179   {
01180     rlDebugPrintf("\nDevPutMessage(NMT)(%d, &message, 5000): %d\n",_boardnr, (int)sRet);
01181     return 0;
01182   } /* if ( (sRet = DevPutMessage(...)) == DRV_NO_ERROR ) else */
01183   
01184   return 1;     
01185 }

short rlCanOpen::setBoardActive ( int  _boardnr  )  [private]

sets a desired CanOpenMaster active, so that it can be used

Definition at line 285 of file rlcanopen.cpp.

00286 {
00287                         
00288   if ( (sRet = DevSetHostState( _boardnr, HOST_READY, 0L) == DRV_NO_ERROR) )   
00289     activeboard = _boardnr;
00290  
00291   return sRet;
00292 }

bool rlCanOpen::showNodeConfiguration (  ) 

prints out the configuration off all available nodes from all boards

Definition at line 320 of file rlcanopen.cpp.

00321 {
00322   if(nodelist.size() == 0) return 0;
00323   for(unsigned int i = 0; i < nodelist.size(); i++)
00324   {
00325     nodelist[i]->showConfiguration();   
00326   }
00327    return 1;
00328 }

bool rlCanOpen::showNodeConfiguration ( int  _boardnr,
int  _nodeid 
)

prints out the configuration of a specific node

Definition at line 303 of file rlcanopen.cpp.

00304 {
00305   for( unsigned int i = 0; i < nodelist.size(); i++)
00306   {
00307     if ((nodelist[i]->getNodeID() == _nodeid) && 
00308         (nodelist[i]->getBoardID() == _boardnr))
00309     {
00310       nodelist[i]->showConfiguration();
00311       return true;
00312       
00313     }           
00314   }
00315 
00316   return false; 
00317 } 


Member Data Documentation

int rlCanOpen::activeboard [private]

the currently active board

Definition at line 219 of file rlcanopen.h.

int rlCanOpen::boardcount [private]

the current count of CanOpenMaster cards

Definition at line 253 of file rlcanopen.h.

bool rlCanOpen::enableLogging [private]

this indicator is true when stdout is redirected to file. it is set in the ini-file

Definition at line 281 of file rlcanopen.h.

FILE* rlCanOpen::err_fp [private]

Pointer to error logfile.

Definition at line 241 of file rlcanopen.h.

char rlCanOpen::err_out_buf[255] [private]

this string buffer is usually written with sprintf before sent to stdout

Definition at line 235 of file rlcanopen.h.

QString rlCanOpen::logFileName [private]

name of logfile stdout is redirected to

Definition at line 244 of file rlcanopen.h.

RCS_MESSAGETELEGRAM_10 rlCanOpen::message [private]

hilscher specific message structur which will be sent to the master card

Definition at line 247 of file rlcanopen.h.

unsigned char rlCanOpen::messagenr [private]

message counter

Definition at line 256 of file rlcanopen.h.

QPtrVector<rlCanNode> rlCanOpen::nodelist [private]

this list contains all nodes from all boards

Definition at line 250 of file rlcanopen.h.

short rlCanOpen::sRet [private]

return value for hilscher specific message functions

Definition at line 238 of file rlcanopen.h.


The documentation for this class was generated from the following files:
Generated on Mon Aug 30 20:16:16 2010 for rllib by  doxygen 1.6.3