rllib  1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
Public Member Functions | Private Member Functions | Private Attributes | List of all members
rlCanOpen Class Reference

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

#include <rlcanopen.h>

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.

{
rlDebugPrintf("Constructer nodes class\n");
read_inifile("./canopen.ini");
FILE* fp;
fp = freopen (logFileName.ascii(),"w",stdout); // redirekt stdout to textfile
/* enable linebuffering in order to write every line to the file immediately */
setvbuf ( fp , NULL , _IOFBF , 1024 );
}
ini();
}
rlCanOpen::rlCanOpen ( char *  _inifilename)

Definition at line 29 of file rlcanopen.cpp.

{
rlDebugPrintf("Constructer nodes class\n");
read_inifile(_inifilename);
freopen (logFileName.ascii(),"w",stdout); // redirekt stdout to textfile
}
ini();
}
rlCanOpen::~rlCanOpen ( )

Definition at line 54 of file rlcanopen.cpp.

{
rlDebugPrintf("destruktor rlCanOpen\n");
for (int i=0;i<boardcount;i++)
DevExitBoard(i);
#ifdef RLWIN32
DevCloseDriver(0);
#else
DevCloseDriver();
#endif
fclose (stdout);
}

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.

{
int pdomax = 0;
if (_pdoDirection == DIRECTION_RECEIVE)
pdomax = nodelist[nodelist.size()-1]->getReceivePdoCount();
else if(_pdoDirection == DIRECTION_TRANSMIT)
pdomax = nodelist[nodelist.size()-1]->getTransmitPdoCount();
for (int j = 1;j<=pdomax;j++) //each receive/transmit pdo
if(refreshMappingList(_boardid,_nodeid,j,_pdoDirection)==0) return 0;
return 1;
}
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.

{
int nodeid;
for (int boardid = 0;boardid<boardcount;boardid++)
{
setBoardActive(boardid);
for(nodeid = 0; nodeid <= MAX_NODES; nodeid++) // from node 0..127
if (getNodeConfiguration(nodeid)) // writes received node-configuration
// into class-global message-struct
{
// new node found. insert it into the nodelist
nodelist.resize( nodelist.size() + 1 );
// append the new node in the list
nodelist.insert( nodelist.size()-1,
new rlCanNode(boardid,nodeid,message));
//append Mapping data
if (nodelist[nodelist.size()-1]->hasMapping()){
if(!createMappingObjects(boardid,nodeid,DIRECTION_TRANSMIT))return 0;
if(!createMappingObjects(boardid,nodeid,DIRECTION_RECEIVE))return 0;
}
else
{
rlDebugPrintf("WARNING: no Mapping available on node %d.", nodeid);
rlDebugPrintf("Probably EDS file couldn't be found in EDS directory.\n");
}
}
}
return 1;
}
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.

{
message.rx =0;
message.tx =0;
message.ln =0;
message.nr =0;
message.a =0;
message.f =0;
message.b =0;
message.e =0;
message.device_adr =0;
message.data_area =0;
message.data_adr =0;
message.data_idx =0;
message.data_cnt =0;
message.data_type =0;
message.function =0;
for (int i = 0; i < MAX_SDO_BUFFERSIZE; i++)
message.d[i] = 0;
}
int rlCanOpen::getActiveBoard ( )

returns the number of currently active board

returns the currently active board

Definition at line 296 of file rlcanopen.cpp.

{
return activeboard;
}
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.

{
return boardcount;
}
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.

{
//build message
message.ln = 8;
message.a =0;
message.f =0;
message.e =0x00; //fragmentation
message.device_adr =_nodeID;
message.data_area =0;
message.data_adr =0;
message.data_idx =0;
message.data_cnt =0;
message.data_type =0;
message.function =0;
//put configuration request
DevPutMessage(0, (MSG_STRUC *)&message,5000L) ;
//receive answer message
sRet = DevGetMessage ( 0,
sizeof(message),
(MSG_STRUC *)&message,
2000L );
unsigned char msgnrlocal = messagenr -1;
// receive correct answer
if((message.a == RESPONSE_CODE_GET_CONFIGURATION) && (message.nr == msgnrlocal))
if (message.f == ERRCODE_NOERROR) // node active, no error
if(message.e == 0x00) //configuration fits in the message
{
sprintf(err_out_buf, "Board %d node %d is active. No problems found\n",
getActiveBoard(), _nodeID);
return 1;
}
else
{
sprintf(err_out_buf, "Board %d node %d is active. \n",
getActiveBoard(), _nodeID);
rlDebugPrintf("Configuration data does not fit in one message,\n");
rlDebugPrintf("so the current node does not include the complete data\n");
rlDebugPrintf(" - multiplex configration data is not yet implemented!!! -\n");
return 1;
}
else return 0;
else
{
sprintf(err_out_buf, "---->message.a=%d, message.nr=%d unsere msg nr: %d\n",
message.a, message.nr, msgnrlocal);
sprintf(err_out_buf, "%s\n", "Communication ERROR!!!");
return 0;
}
}
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.

{
for(unsigned int i = 0; i < nodelist.size(); i++)
{
if ((nodelist[i]->getNodeID() == _nodeid) &&
(nodelist[i]->getBoardID() == _boardnr))
{
_index = i;
return true;
}
}
return false;
}
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.

{
setBoardActive(_boardnr);
COM_ND_DIAGNOSTICS * diag;
diag = (COM_ND_DIAGNOSTICS*) &message.d[0];
message.rx = CAN_TASK ;//receiver = user at HOST
message.tx = USER_AT_HOST ;// transmitter = USR_INTF-Task
message.ln = 8 ;//length of message
message.nr = messagenr++ ;//number of the message
message.a = 0 ;//no answer
message.f = 0 ;//error, status
message.b = CMDCODE_Node_Diag;//command = COM_Node_Diag
message.e =0 ;//extension
message.device_adr = _nodeid ;//k Rem_Adr
message.data_area = 0 ;// data area, unused
message.data_adr = 0 ;//data address, unused
message.data_idx = 0 ;//data index, unused
message.data_cnt = 0 ;//data count, unused
message.data_type = 5 ;// data type byte string
message.function = 1 ;//function read
if ( (sRet = DevPutMessage(_boardnr, (MSG_STRUC *)&message, 5000L))
== DRV_NO_ERROR )
{
while( (sRet = DevGetMessage(_boardnr, sizeof(message),
(MSG_STRUC *)&message, 0))
== DRV_DEV_GET_NO_MESSAGE )
{
continue;
}
if ( sRet == DRV_NO_ERROR )
{
rlDebugPrintf("message successfully received\n");
// continue;
}
else
{
rlDebugPrintf("Error Message (f = %d))\n",message.f);
rlDebugPrintf("\nDevGetMessage(%d, sizeof(message), &message, 500): %d\n",
_boardnr, (int)sRet);
return 0;
}
}
else
{
rlDebugPrintf("\nDevPutMessage(%d, &message, 5000): %d\n",_boardnr, (int)sRet);
return 0;
}
_data.set_nodestateFlags( diag->bNodeStatus_1.bNodeNoResponse,
diag->bNodeStatus_1.bEmcyBuffOverflow,
diag->bNodeStatus_1.bPrmFault,
diag->bNodeStatus_1.bGuardActive,
diag->bNodeStatus_1.bDeactivated );
_data.set_nodestate(diag->bNodeState);
_data.set_nodeerror(diag->bActualError);
return 1;
}
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.

{
int nodeindex;
if (getNodeIndex(_boardnr, _nodeid, nodeindex)){
if (nodelist[nodeindex]->hasMapping())
return nodelist[nodeindex]->objecttype(_objectindex, _subindex);
else
}
else{
}
}
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.

{
int pdomax=0;
int nodeindex=0;
int madress=0;
// get index of node in nodelist depending on boardid and nodeid
// index is stored in nodeindex variable
getNodeIndex(_boardnr, _nodeid, nodeindex);
// get number of elements in particular PDO list
if (_direction == DIRECTION_RECEIVE)
pdomax = nodelist[nodeindex]->getReceivePdoCount();
if (_direction == DIRECTION_TRANSMIT)
pdomax = nodelist[nodeindex]->getTransmitPdoCount();
/* iterate through every element of particular list until mapping
object adress matches given objectindex */
for (int j=1;j<=pdomax;j++)
{
madress = nodelist[nodeindex]->pdoList[_direction][j-1]->mappingOvAdress;
if (madress == _objektindex)
return j;
}
return 0;
}
bool rlCanOpen::ini ( )
private

initialize nodes and create nodelist

Definition at line 71 of file rlcanopen.cpp.

{
messagenr = 0;
nodelist.setAutoDelete(true);
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
sprintf(err_out_buf, "\nnew session startet: %s\n", asctime(timeinfo));
if (iniboards()){
rlDebugPrintf("at least one board initialize!\n");
}
else
{
rlDebugPrintf("no board available or no board could be initialized correctly!\n");
rlDebugPrintf("Programm -> Close\n");
exit(0);
}
// search for active nodes and create them
return 1;
}
bool rlCanOpen::iniboards ( )
private

Read informations about installed devices.

Definition at line 154 of file rlcanopen.cpp.

{
int currentboardcount=0;
BOARD_INFO tBoardInfo;
#ifdef RLWIN32
if ( (sRet = DevOpenDriver(0)) == DRV_NO_ERROR)
#else
if ( (sRet = DevOpenDriver()) == DRV_NO_ERROR)
#endif
{
// Driver successfully opend, read board information
#ifdef RLWIN32
if ( (sRet = DevGetBoardInfo( 0, sizeof(tBoardInfo), &tBoardInfo)) != DRV_NO_ERROR)
#else
if ( (sRet = DevGetBoardInfo( &tBoardInfo)) != DRV_NO_ERROR)
#endif
{
// Function error
rlDebugPrintf( "DevGetBoardInfo RetWert = %5d \n", sRet );
} else
{
// Information successfully read, save for further use
// Check out which boards are available
for ( int usIdx = 0; usIdx < MAX_DEV_BOARDS; usIdx++)
{
if ( tBoardInfo.tBoard[usIdx].usAvailable == TRUE) {
// Board is configured, try to init the board
sRet = DevInitBoard(
#ifdef RLWIN32
tBoardInfo.tBoard[usIdx].usBoardNumber, NULL);
#else
tBoardInfo.tBoard[usIdx].usBoard);
#endif
if ( sRet != DRV_NO_ERROR) {
// Function error
rlDebugPrintf( "DevInitBoard RetWert = %5d \n", sRet );
} else {
// DEVICE is available and ready............
currentboardcount++;
}
}
}
}
}
boardcount = currentboardcount;
if (currentboardcount!=0)
return 1;
else
return 0;
}
bool rlCanOpen::is_twisted_type ( int  _canopentype)

Definition at line 1226 of file rlcanopen.cpp.

{
switch (_canopentype){
case rlCanOpenTypes::INTEGER24_t :return true;
case rlCanOpenTypes::INTEGER40_t :return true;
case rlCanOpenTypes::INTEGER48_t :return true;
case rlCanOpenTypes::INTEGER56_t :return true;
case rlCanOpenTypes::UNSIGNED24_t:return true;
case rlCanOpenTypes::UNSIGNED40_t:return true;
case rlCanOpenTypes::UNSIGNED48_t:return true;
case rlCanOpenTypes::UNSIGNED56_t:return true;
default :return false;
};
}
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.

{
int nodeindex;
unsigned char buffer[8];
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
rlDebugPrintf("ERROR: specified node does not exist! PDO receive failed!");
rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT].size() < (unsigned int) _pdonr){
rlDebugPrintf("ERROR: specified PDO ID does not exist! PDO receive failed!");
rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
else if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr -1]->mappingList.size()
< (unsigned int) _mappingnr){
rlDebugPrintf("ERROR: specified Mappingnr does not exist! PDO receive failed!");
rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
// PDO No.1 has the index 0 !!!
int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->bPDOSize;
int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->usPDOAddress;
//cout<<"size ="<<pdosize<<" offset = "<<pdooffset<<"\n";
if ( (sRet = DevExchangeIO( _boardnr, // Board NO
0, //offset send data
0, //Length of the send IO data
NULL, //Pointer to the user send data buffer
pdooffset, //Byte offset in the receive IO data area
pdosize, //Length of the receive IO data
&buffer[0], //Pointer to the user read data buffer
100L) //timeout in milliseconds
) == DRV_NO_ERROR)
{
int length_in_byte = nodelist[nodeindex]->
pdoList[DIRECTION_TRANSMIT][_pdonr-1]->mappingList[_mappingnr-1]->length/8;
int position_in_byte = nodelist[nodeindex]->
pdoList[DIRECTION_TRANSMIT][_pdonr-1]->mappingList[_mappingnr-1]->position/8;
_pdo_data.clearBuffer();
for(int i = position_in_byte; i< length_in_byte+position_in_byte;i++)
{
_pdo_data.set_buffer(i-position_in_byte,buffer[i]);
}
_pdo_data.set_DaemonType( nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->
mappingList[_mappingnr-1]->etype);
// if CanOpen-Type is a twistet integer (etc. 52Bit ) the value will be converted
int canopentype = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->
mappingList[_mappingnr-1]->canopentype;
if (is_twisted_type(canopentype))
_pdo_data.translate_CanOpenType(canopentype);
return 1;
}
rlDebugPrintf("ERROR: PDO receive failed!");
rlDebugPrintf("BoardId: %d NodeId: %d PDO ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
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.

{
int nodeindex;
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
sprintf(err_out_buf, "ERROR: specified node does not exist! PDO \
receive failed! BoardId: %d NodeId: %d PDO \
ID: %d\n", _boardnr, _nodeid, _pdonr);
//cout<<"ERROR: specified node does not exist!\n";
return 0;
}
if (nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT].size() < (unsigned int) _pdonr){
sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! \
PDO receive failed! BoardId: %d NodeId: \
%d PDO ID: %d\n", _boardnr, _nodeid, _pdonr);
//cout<<"PDO ID does not exists!\n";
return 0;
}
int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_TRANSMIT][_pdonr-1]->bPDOSize;
int pdooffset = nodelist[nodeindex]->
pdoList[DIRECTION_TRANSMIT][_pdonr-1]->usPDOAddress;
//cout<<"\nsize ="<<pdosize<<" offset = "<<pdooffset;
if ( (sRet = DevExchangeIO( _boardnr, // Board NO
0, //offset send data
0, //Length of the send IO data
NULL, //Pointer to the user send data buffer
pdooffset, //Byte offset in the receive IO data area
pdosize, //Length of the receive IO data
&_pdo_data.pdobuffer[0],//Pointer to the user read data buffer
100L) //timeout in milliseconds
) == DRV_NO_ERROR)
{
_pdo_data.pdobuf2buf();
//rlDebugPrintf("PDO recieve successfull!\n");
return 1;
}
sprintf(err_out_buf, "ERROR: PDO receive failed! \
BoardId: %d NodeId: %d PDO \
ID: %d\n", _boardnr, _nodeid, _pdonr);
//rlDebugPrintf("ERROR: PDO RECEIVE FAILED\n");
return 0;
}
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.

{
int nodeindex;
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
sprintf(err_out_buf, "ERROR: specified node does not exist! PDO transmit \
failed! BoardId: %d NodeId: %d PDO ID: %d Mappingnr:\
%d\n", _boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE].size() < (unsigned int) _pdonr){
sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! PDO transmit\
failed! BoardId: %d NodeId: %d PDO ID: %d Mappingnr:\
%d\n", _boardnr, _nodeid, _pdonr, _mappingnr);
//cout<<"PDO ID does not exists!\n";
return 0;
}
else if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr -1]->mappingList.size()
< (unsigned int) _mappingnr){
sprintf(err_out_buf, "ERROR: specified mappingnr does not exist! PDO \
transmit failed! BoardId: %d NodeId: %d PDO \
ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
//cout<<"mapping ID does not exists!\n";
return 0;
}
// PDO No.1 has the index 0 !!!
int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->bPDOSize;
int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->usPDOAddress;
int length_in_byte = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
mappingList[_mappingnr-1]->length/8;
int position_in_byte = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
mappingList[_mappingnr-1]->position/8;
if (_pdo_data.get_DaemonType() != (nodelist[nodeindex]->
pdoList[DIRECTION_RECEIVE][_pdonr-1]->mappingList[_mappingnr-1]->etype))
{
sprintf(err_out_buf, "ERROR: invalid type! Expected type: %d Your Type:\
%d! PDO transmit failed! BoardId: %d NodeId: %d \
PDO ID: %d Mappingnr: %d\n",
nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->
mappingList[_mappingnr-1]->etype,
_pdo_data.get_DaemonType(), _boardnr, _nodeid, _pdonr, _mappingnr);
_pdo_data.get_DaemonType();
return 0;
}
_pdo_data.buf2pdobuf();
// no conversion necessary. correct length in mapping list
pdooffset = pdooffset + position_in_byte;
pdosize = length_in_byte;
//cout<<"size ="<<pdosize<<" offset = "<<pdooffset<<"\n";
if ( (sRet = DevExchangeIO( _boardnr, // Board NO
pdooffset, //offset send data
pdosize, //Length of the send IO data
&_pdo_data.pdobuffer[0],//Pointer to the user send data buffer
0, //Byte offset in the receive IO data area
0, //Length of the receive IO data
NULL, //Pointer to the user read data buffer
100L) //timeout in milliseconds
) == DRV_NO_ERROR)
{
_pdo_data.set_rlmsgerr(0);
//rlDebugPrintf("PDO transmit successful! \n");
return 1;
}
sprintf(err_out_buf, "ERROR: PDO transmit failed! BoardId: %d NodeId: %d \
PDO ID: %d Mappingnr: %d\n",
_boardnr, _nodeid, _pdonr, _mappingnr);
return 0;
}
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.

{
int nodeindex;
_pdo_data.buf2pdobuf();
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
sprintf(err_out_buf, "ERROR: specified node does not exist! PDO transmit\
failed! BoardId: %d NodeId: %d PDO ID: %d \n",
_boardnr, _nodeid, _pdonr);
return 0;
}
if (nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE].size() < (unsigned int) _pdonr){
sprintf(err_out_buf, "ERROR: specified PDO ID does not exist! PDO \
transmit failed! BoardId: %d NodeId: %d PDO \
ID: %d \n", _boardnr, _nodeid, _pdonr);
return 0;
}
int pdosize = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->bPDOSize;
int pdooffset = nodelist[nodeindex]->pdoList[DIRECTION_RECEIVE][_pdonr-1]->usPDOAddress;
if ( (sRet = DevExchangeIO( _boardnr, // Board NO
pdooffset, //offset send data
pdosize, //Length of the send IO data
&_pdo_data.pdobuffer[0],//Pointer to the user send data buffer
0, //Byte offset in the receive IO data area
0, //Length of the receive IO data
NULL, //Pointer to the user read data buffer
100L) //timeout in milliseconds
) == DRV_NO_ERROR)
{
return 1;
}
sprintf(err_out_buf, "ERROR: PDO transmit failed! BoardId: %d NodeId: %d \
PDO ID: %d \n", _boardnr, _nodeid, _pdonr);
return 0;
}
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.

{
QString buffer;
if (ini.read(_filename)!=-1){
rlDebugPrintf("used inifile: %s\n", _filename);
// read EDS directory location
buffer=QString(ini.text("DIRECTORIES","EdsDir"));
buffer.remove((char) ACSII_CODE_CARRIAGE_RETURN);
rlDebugPrintf("EdsDir: %s\n", buffer.ascii());
// store EDS directory location in environmet variable
#ifdef RLWIN32
SetEnvironmentVariable("EdsDir", buffer.ascii());
#else
setenv("EdsDir", buffer.ascii(), 1);
#endif
// read Logfilename
logFileName=QString(ini.text("DIRECTORIES","LogFileName"));
logFileName.remove((char) ACSII_CODE_CARRIAGE_RETURN);
rlDebugPrintf("Log Filename: %s\n", logFileName.ascii());
// read loggin-option
buffer=QString(ini.text("OPTIONS","enableLoggin"));
if (buffer.contains("yes", false)==1)
else
enableLogging=false;
}
else
{
logFileName= "./outfile.txt";
rlDebugPrintf("ERROR: INIFILE NOT FOUND\n");
}
}
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.

{
//rlDebugPrintf("refresh mappinglist1\n");
int nodeindex;
int madress=0;
madress = nodelist[nodelist.size()-1]->
pdoList[_pdoDirection][_pdoID -1]->mappingOvAdress;
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== false)
{
sprintf(err_out_buf, "ERROR: specified node does not exist! refresh \
mapping list failed! BoardId: %d NodeId: %d \
PDO ID: %d \n", _boardnr, _nodeid, _pdoID);
return 0;
}
if(nodelist[nodeindex]->pdoList[_pdoDirection].size() < (unsigned int) _pdoID)
{
sprintf(err_out_buf, "ERROR: PDO does not exist! refresh \
mapping list failed! BoardId: %d NodeId: %d \
PDO ID: %d \n", _boardnr, _nodeid, _pdoID);
return 0;
}
//append Mapping data
rlCanOpenTypes sdobuffer;
int mappingcount;
rlCanMapping * mappingobject;
//get mapping count
if (sdo_read(_boardnr,_nodeid,madress,0,sdobuffer) == 0){
sprintf(err_out_buf, "ERROR: read sdo data! refresh mapping list failed! \
BoardId: %d NodeId: %d PDO ID: %d \n",
_boardnr, _nodeid, _pdoID);
}
mappingcount = sdobuffer.get_uchar();
sprintf(err_out_buf, "Current mappingcount: %d\n", mappingcount);
nodelist[nodeindex]->pdoList[_pdoDirection][_pdoID-1]->
mappingList.resize(mappingcount);
int currentposition = 0;
for (int mcount = 1; mcount <= mappingcount;mcount++) //each mappingobject
{
mappingobject = new rlCanMapping; //create new mappingobject in memory
mappingobject->mappingId = mcount;
if (sdo_read(_boardnr,_nodeid,madress,mcount,sdobuffer) == 0){
sprintf(err_out_buf, "ERROR: read sdo data! refresh mapping list failed! \
BoardId: %d NodeId: %d PDO ID: %d \n",
_boardnr, _nodeid, _pdoID);
//cout<<"Error during create Mappinglist!\n";
}
//get length of mapping object
int mlength = sdobuffer.get_buffer(0);
mappingobject->length = mlength;
//calculate the mapping position
if (mcount>1)
mappingobject->position = currentposition;
else
mappingobject->position = 0;
currentposition+=mlength;
// get the ov adress of the current mapped object
int mi = (int) (sdobuffer.get_buffer(3)*pow(256,1)
+ sdobuffer.get_buffer(2));
unsigned char msi = sdobuffer.get_buffer(1);
rlCanOpenTypes temptype;
mappingobject->etype = temptype.canOpenType2DeamonType
(nodelist[nodelist.size()-1]->objecttype(mi, msi));
// insert the mappingobject to mappinglist
nodelist[nodeindex]->pdoList[_pdoDirection][_pdoID-1]->
mappingList.insert(mcount-1,mappingobject);
}
return 1;
}
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.

{
//COLDSTART 2
//WARMSTART 3
//BOOTSTART 4
if ( (sRet = DevReset(_boardnr, _restarttype, 5000L) != DRV_NO_ERROR ))
{
rlDebugPrintf("restart failed!\n");
rlDebugPrintf("DevReset(%d, Restart, 5000): %d\n", _boardnr, sRet);
return 0;
}
rlDebugPrintf("restart successfully\n");
return 1;
}
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.

{
int datalength;
int canopentype;
int nodeindex;
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
rlDebugPrintf("ERROR: specified node does not exist! SDO write failed!");
rlDebugPrintf("BoardId: %d NodeId: %d Objektindex: %d Subindex: %d\n",
_boardnr, _nodeid, _objectindex, _subindex);
return 0;
}
delmsg();
setBoardActive(_boardnr);
message.ln = 8;
message.nr = messagenr++;
message.a = 0;
message.f = 0;
message.e = 0;
message.device_adr = _nodeid;
message.data_area = 0;
message.data_adr = _objectindex;
message.data_idx = _subindex;
message.data_cnt = 0;
message.data_type = 0;
message.function = TASK_TFC_READ;
if(DevPutMessage(0, (MSG_STRUC *)&message,5000L) != DRV_NO_ERROR) return 0;
delmsg();
// receive the answer
sRet = DevGetMessage( getActiveBoard(), // Device Number
sizeof(message),
(MSG_STRUC *)&message, // Pointer to user buffer
2000L ); // Timeout
unsigned char msgnrlocal;
msgnrlocal = messagenr - 1;
// receive correct answer
if((message.a == CMDCODE_SDO_UPDOWNLOAD)&&(message.nr == msgnrlocal)){
_sdo_data.set_rlmsgerr(message.f);
if (message.f == ERRCODE_NOERROR) // node active, no error
{
canopentype=getObjectType(_boardnr, _nodeid, _objectindex, _subindex);
if (canopentype!=rlCanOpenTypes::RL_NOTYPE){
_sdo_data.set_CanOpenType(canopentype);
datalength = _sdo_data.getLength();
}
else
{
datalength = MAX_SDO_BUFFERSIZE;
}
_sdo_data.clearBuffer();
for(int i = 0; i < datalength; i++)
_sdo_data.set_buffer(i, message.d[i]);
// if CanOpen-Type is a twistet integer (etc. 52Bit ) the value will be converted
if ((is_twisted_type(canopentype)) && (nodelist[nodeindex]->hasMapping()))
_sdo_data.translate_CanOpenType(canopentype);
return 1;
}
else
{
rlDebugPrintf("message.f = %d message.f = %x Hex \n", message.f, message.f);
}
}
else
{
rlDebugPrintf("message.a = %d message.nr = %d vergleich mit: %d\n",
message.a, message.nr, msgnrlocal);
_sdo_data.set_rlmsgerr(-1);
}
rlDebugPrintf("ERROR during read SDO message!");
rlDebugPrintf("BoardId: %d NodeId: %d Obj: %x Sub: %x\n",
_boardnr, _nodeid, _objectindex, _subindex);
return 0;
}
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.

{
int length;
int pdoid;
length = _sdo_data.getLength();
int nodeindex;
if (getNodeIndex(_boardnr,_nodeid,nodeindex)== 0)
{
rlDebugPrintf("ERROR: specified node does not exist! SDO write failed!");
rlDebugPrintf("BoardId: %d NodeId: %d Objektindex: %d Subindex: %d\n",
_boardnr, _nodeid, _objectindex, _subindex);
return 0;
}
// if CanOpen-Type is a twistet integer (etc. 52Bit ) the datalength must be adjusted
int canopentype = getObjectType(_boardnr, _nodeid, _objectindex, _subindex);
if ((is_twisted_type(canopentype)) && (nodelist[nodeindex]->hasMapping()))
length = _sdo_data.get_CanOpenTypeLength(canopentype);
for(int i = 0;i<length;i++)
message.d[i] = _sdo_data.get_buffer(i);
setBoardActive(_boardnr);
message.ln = 8+ length;
message.nr = messagenr++;
message.a = 0;
message.f = 0;
message.e = 0;
message.device_adr = _nodeid;
message.data_area = 0;
message.data_adr = _objectindex;
message.data_idx = _subindex;
message.data_cnt = length;
message.data_type = 0;
message.function = TASK_TFC_WRITE;
if(DevPutMessage(0, (MSG_STRUC *)&message,5000L) != DRV_NO_ERROR) return 0;
// receive the answer
sRet = DevGetMessage ( _boardnr, // Device Number
sizeof(message),
(MSG_STRUC *)&message, // Pointer to user buffer
2000L ); // Timeout
unsigned char msgnrlocal = messagenr - 1;
// receive correct answer
if((message.a == CMDCODE_SDO_UPDOWNLOAD)&&(message.nr == msgnrlocal)){
_sdo_data.set_rlmsgerr(message.f);
if (message.f == ERRCODE_NOERROR) // node active, no error
{
//check if the mapping has changed
if( (_objectindex >= TRANSMIT_PDO_MAPPING_STARTADRESS) &&
(_objectindex <= TRANSMIT_PDO_MAPPING_MAXADRESS) &&
(nodelist[nodeindex]->hasMapping()) )
{
rlDebugPrintf("Mapping has changed: boardid %d, nodeid %d, objectindex %x\n",
_boardnr, _nodeid, _objectindex);
pdoid = getPdoID(_boardnr, _nodeid, _objectindex, DIRECTION_TRANSMIT);
refreshMappingList(_boardnr,_nodeid,pdoid,DIRECTION_TRANSMIT);
}
else if ( (_objectindex >= RECEIVE_PDO_MAPPING_STARTADRESS) &&
(_objectindex <= RECEIVE_PDO_MAPPING_MAXADRESS) &&
(nodelist[nodeindex]->hasMapping()) )
{
rlDebugPrintf("Mapping has changed: boardid %d, nodeid %d, objectindex %x\n",
_boardnr, _nodeid, _objectindex);
pdoid = getPdoID(_boardnr, _nodeid, _objectindex, DIRECTION_RECEIVE);
refreshMappingList(_boardnr,_nodeid,pdoid,DIRECTION_RECEIVE);
}
return 1;
}
else
{
sprintf(err_out_buf, "message.f = %d message.f = %x Hex \n",
_sdo_data.set_rlmsgerr(message.f);
}
}
else
{
_sdo_data.set_rlmsgerr(-1);
sprintf(err_out_buf, "message.a = %d message.nr = %d vergleich mit: %d\n",
message.a, message.nr, msgnrlocal);
}
rlDebugPrintf("ERROR during read SDO message!");
rlDebugPrintf("BoardId: %d NodeId: %d Obj: %x Sub: %x\n",
_boardnr, _nodeid, _objectindex, _subindex);
return 0;
}
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.

{
MSG_STRUC message;
setBoardActive(_boardnr);
message.rx = CAN_TASK ;//receiver = user at HOST
message.tx = USER_AT_HOST ;// transmitter = USR_INTF-Task
message.ln = 2 ;//length of message
message.nr = messagenr++ ;//number of the message
message.a = 0 ;//no answer
message.f = 0 ;//error, status
message.b = CMD_NMT_Module_Protocol;//command = COM_Node_Diag
message.e = 0 ;//extension
// NMT Command specifier
//1 Start Remote Node
//2 Stop Remote Node
//128 Enter Pre-Operational
//129 Reset Node
//130 Reset Communication
message.data[0] = _cmd ;//NMT Command specifier
message.data[1] = _nodeid ;//NodeID
if ( (sRet = DevPutMessage(_boardnr, (MSG_STRUC *)&message, 5000L))
== DRV_NO_ERROR )
{
while( (sRet = DevGetMessage(_boardnr, sizeof(message),
(MSG_STRUC *)&message, 0))
== DRV_DEV_GET_NO_MESSAGE )
{
continue;
}
if ( sRet == DRV_NO_ERROR )
{
rlDebugPrintf("NMT message successfully received\n");
// continue;
}
else
{
rlDebugPrintf("Error Message (f = %d))\n",message.f);
rlDebugPrintf("\nDevGetMessage(%d, sizeof(message), &message, 500): %d\n",
_boardnr, (int)sRet);
return 0;
}
}
else
{
rlDebugPrintf("\nDevPutMessage(NMT)(%d, &message, 5000): %d\n",_boardnr, (int)sRet);
return 0;
} /* if ( (sRet = DevPutMessage(...)) == DRV_NO_ERROR ) else */
return 1;
}
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.

{
if ( (sRet = DevSetHostState( _boardnr, HOST_READY, 0L) == DRV_NO_ERROR) )
activeboard = _boardnr;
return sRet;
}
bool rlCanOpen::showNodeConfiguration ( int  _boardnr,
int  _nodeid 
)

prints out the configuration of a specific node

Definition at line 303 of file rlcanopen.cpp.

{
for( unsigned int i = 0; i < nodelist.size(); i++)
{
if ((nodelist[i]->getNodeID() == _nodeid) &&
(nodelist[i]->getBoardID() == _boardnr))
{
nodelist[i]->showConfiguration();
return true;
}
}
return false;
}
bool rlCanOpen::showNodeConfiguration ( )

prints out the configuration off all available nodes from all boards

Definition at line 320 of file rlcanopen.cpp.

{
if(nodelist.size() == 0) return 0;
for(unsigned int i = 0; i < nodelist.size(); i++)
{
nodelist[i]->showConfiguration();
}
return 1;
}

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: