CanESD.cpp
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2010
00004  *
00005  * Fraunhofer Institute for Manufacturing Engineering   
00006  * and Automation (IPA)
00007  *
00008  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00009  *
00010  * Project name: care-o-bot
00011  * ROS stack name: cob_drivers
00012  * ROS package name: cob_generic_can
00013  * Description: This class implements the interface to an ESD can node
00014  *                                                              
00015  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00016  *                      
00017  * Author: Christian Connette, email:christian.connette@ipa.fhg.de
00018  * Supervised by: Christian Connette, email:christian.connette@ipa.fhg.de
00019  *
00020  * Date of creation: April 2010
00021  * ToDo: - Remove Mutex.h search for a Boost lib
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00034  *       Engineering and Automation (IPA) nor the names of its
00035  *       contributors may be used to endorse or promote products derived from
00036  *       this software without specific prior written permission.
00037  *
00038  * This program is free software: you can redistribute it and/or modify
00039  * it under the terms of the GNU Lesser General Public License LGPL as 
00040  * published by the Free Software Foundation, either version 3 of the 
00041  * License, or (at your option) any later version.
00042  * 
00043  * This program is distributed in the hope that it will be useful,
00044  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00045  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00046  * GNU Lesser General Public License LGPL for more details.
00047  * 
00048  * You should have received a copy of the GNU Lesser General Public 
00049  * License LGPL along with this program. 
00050  * If not, see <http://www.gnu.org/licenses/>.
00051  *
00052  ****************************************************************/
00053 
00054 // general includes
00055 
00056 // Headers provided by other cob-packages
00057 #include <cob_generic_can/CanESD.h>
00058 
00059 // Headers provided by other cob-packages which should be avoided/removed
00060 
00061 
00062 //-----------------------------------------------
00063 CanESD::CanESD(const char* cIniFile, bool bObjectMode)
00064 {
00065         m_bObjectMode = bObjectMode;
00066         m_bIsTXError = false;
00067         m_IniFile.SetFileName(cIniFile, "CanESD.cpp");
00068         initIntern();
00069 }
00070 
00071 //-----------------------------------------------
00076 CanESD::~CanESD()
00077 {
00078         std::cout << "Closing CAN handle" << std::endl;
00079         canClose(m_Handle);
00080 }
00081 
00082 
00083 //-----------------------------------------------
00084 void CanESD::initIntern()
00085 {       
00086         int ret=0;      
00087         ret = 0;
00088         int iCanNet = 1;
00089         m_IniFile.GetKeyInt( "CanCtrl", "NetESD", &iCanNet, true);
00090         
00091         int iBaudrateVal = 2;
00092         m_IniFile.GetKeyInt( "CanCtrl", "BaudrateVal", &iBaudrateVal, true);
00093 
00094         std::cout << "Initializing CAN network with id =" << iCanNet << ", baudrate=" << iBaudrateVal << std::endl;
00095 
00096         int iRet;
00097         if( m_bObjectMode )
00098                 iRet = canOpen(iCanNet, NTCAN_MODE_OBJECT, 10000, 10000, 1000, 0, &m_Handle);
00099         else
00100                 iRet = canOpen(iCanNet, 0, 10000, 10000, 1000, 0, &m_Handle);
00101         Sleep(300);
00102 
00103         if(iRet == NTCAN_SUCCESS)
00104                 std::cout << "CanESD::CanESD(), init ok" << std::endl;
00105         else
00106                 std::cout << "error in CANESD::receiveMsg: " << GetErrorStr(iRet) << std::endl;
00107 
00108         iRet = canSetBaudrate(m_Handle, iBaudrateVal);
00109         if(iRet == NTCAN_SUCCESS)
00110                 std::cout << "CanESD::CanESD(), canSetBaudrate ok" << std::endl;
00111         else
00112                 std::cout << "error in CANESD::receiveMsg: " << GetErrorStr(iRet) << std::endl;
00113         Sleep(300);
00114 
00115         //long lArg;
00116         iRet = canIoctl(m_Handle, NTCAN_IOCTL_FLUSH_RX_FIFO, NULL);
00117 
00118         // MMB/24.02.2006: Add all 11-bit identifiers as there is no loss in performance.
00119         for( int i=0; i<=0x7FF; ++i ) {
00120                 iRet = canIdAdd( m_Handle, i );
00121                 if(iRet != NTCAN_SUCCESS)
00122                         std::cout << "error in CANESD::receiveMsg: " << GetErrorStr(iRet) << std::endl;
00123         }
00124 
00125 
00126         Sleep(300);
00127 
00128         m_LastID = -1;
00129 }
00130 
00131 //-----------------------------------------------
00138 bool CanESD::transmitMsg(CanMsg CMsg, bool bBlocking)
00139 {
00140         CMSG NTCANMsg;
00141         NTCANMsg.id = CMsg.m_iID;
00142         NTCANMsg.len = CMsg.m_iLen;
00143 
00144         for(int i=0; i<8; i++)
00145                 NTCANMsg.data[i] = CMsg.getAt(i);
00146         
00147         int ret;
00148         int32_t len;
00149         bool bRet = true;
00150         
00151         len = 1;
00152 
00153         if (bBlocking)
00154                 ret = canWrite(m_Handle, &NTCANMsg, &len, NULL);
00155         else
00156                 ret = canSend(m_Handle, &NTCANMsg, &len);
00157 
00158         if( ret != NTCAN_SUCCESS)
00159         {
00160                 std::cout << "error in CANESD::transmitMsg: " << GetErrorStr(ret) << std::endl;
00161                 bRet = false;
00162         }
00163 
00164         m_LastID = (int)NTCANMsg.data[0];
00165 
00166         m_bIsTXError = !bRet;
00167         return bRet;
00168 }
00169 
00170 //-----------------------------------------------
00171 bool CanESD::receiveMsgRetry(CanMsg* pCMsg, int iNrOfRetry)
00172 {
00173         //int id = pCMsg->m_iID;
00174         CMSG NTCANMsg;
00175         NTCANMsg.len = 8;
00176         
00177         int32_t len;
00178         int i, ret;
00179         bool bRet = true;
00180         
00181         i=0;
00182         
00183         len = 1;
00184 
00185         do
00186         {
00187                 len = 1;
00188                 ret = canTake(m_Handle, &NTCANMsg, &len);
00189                 i++;
00190                 Sleep(10);
00191         }
00192 
00193         while((len == 0) && (i < iNrOfRetry));
00194         
00195         if(i == iNrOfRetry)
00196         {
00197                 if( ret != NTCAN_SUCCESS )
00198                         std::cout << "error in CANESD::receiveMsgRetry: " << GetErrorStr(ret) << std::endl;
00199 
00200                 bRet = false;
00201         }
00202         else
00203         {
00204                 pCMsg->m_iID = NTCANMsg.id;
00205                 pCMsg->m_iLen = NTCANMsg.len;
00206                 pCMsg->set(NTCANMsg.data[0], NTCANMsg.data[1], NTCANMsg.data[2], NTCANMsg.data[3],
00207                         NTCANMsg.data[4], NTCANMsg.data[5], NTCANMsg.data[6], NTCANMsg.data[7]);
00208         }
00209 
00210         return bRet;
00211 }
00212 
00213 //-----------------------------------------------
00214 bool CanESD::receiveMsg(CanMsg* pCMsg)
00215 {
00216         CMSG NTCANMsg;
00217         NTCANMsg.len = 8;
00218 
00219         int ret;
00220         int32_t len;
00221         bool bRet = true;
00222         
00223         len = 1;
00224 
00225         // Debug valgrind
00226         NTCANMsg.data[0] = 0;
00227         NTCANMsg.data[1] = 0;
00228         NTCANMsg.data[2] = 0;
00229         NTCANMsg.data[3] = 0;
00230         NTCANMsg.data[4] = 0;
00231         NTCANMsg.data[5] = 0;
00232         NTCANMsg.data[6] = 0;
00233         NTCANMsg.data[7] = 0;
00234         NTCANMsg.msg_lost = 0;
00235         NTCANMsg.id = 0;
00236         NTCANMsg.len = 0;
00237 
00238         pCMsg->set(0,0,0,0,0,0,0,0);
00239 
00240         
00241         if( !isObjectMode() ) {
00242                 pCMsg->m_iID = 0;
00243         } else {
00244                 NTCANMsg.id = pCMsg->m_iID;
00245         }
00246 
00247         ret = canTake(m_Handle, &NTCANMsg, &len);
00248 
00249         if( !isObjectMode() ) {
00250                 if( (len == 1) && (ret == NTCAN_SUCCESS) )
00251                 {
00252                         // message received
00253                         pCMsg->m_iID = NTCANMsg.id;
00254                         pCMsg->m_iLen = NTCANMsg.len;
00255                         pCMsg->set(NTCANMsg.data[0], NTCANMsg.data[1], NTCANMsg.data[2], NTCANMsg.data[3],
00256                                 NTCANMsg.data[4], NTCANMsg.data[5], NTCANMsg.data[6], NTCANMsg.data[7]);
00257                         bRet = true;
00258                 }
00259                 else
00260                 {
00261                         // no message
00262                         if( ret != NTCAN_SUCCESS)
00263                         {
00264                                 // error
00265                                 std::cout << "error in CANESD::receiveMsg: " << GetErrorStr(ret) << std::endl;
00266                         }
00267         
00268                         pCMsg->m_iID = NTCANMsg.id;
00269                         pCMsg->set(0,0,0,0,0,0,0,0);
00270 
00271                         bRet = false;
00272                 }
00273         } else {
00274                 if( len == 16 ) {
00275                         // No message was received yet.
00276                         pCMsg->m_iID = NTCANMsg.id;
00277                         pCMsg->set(0,0,0,0,0,0,0,0);
00278                         bRet = false;
00279                 } else {
00280                         pCMsg->m_iID = NTCANMsg.id;
00281                         pCMsg->m_iLen = NTCANMsg.len;
00282                         pCMsg->set(NTCANMsg.data[0], NTCANMsg.data[1], NTCANMsg.data[2], NTCANMsg.data[3],
00283                                    NTCANMsg.data[4], NTCANMsg.data[5], NTCANMsg.data[6], NTCANMsg.data[7]);
00284                         bRet = true;
00285                 }
00286         }
00287         
00288         if( NTCANMsg.msg_lost != 0 )
00289                 std::cout << (int)(NTCANMsg.msg_lost) << " messages lost!" << std::endl;
00290 
00291         return bRet;
00292 }
00293 
00294 
00303 int CanESD::canIdAddGroup(NTCAN_HANDLE handle, int id)
00304 {
00305         int result = NTCAN_SUCCESS;
00306         int i = 0;
00307         int iRes = 0;
00308         int cmd_id = invert(id);
00309 
00310         for( i=0; i<8; ++i) {
00311                 iRes = canIdAdd(m_Handle, cmd_id+i);
00312 
00313                 if( iRes != NTCAN_SUCCESS ) {
00314                         std::cout << "Adding CAN ID " << cmd_id+i << " failed with errorcode: " << iRes << " " << GetErrorStr(iRes) << std::endl;
00315                         result = iRes;
00316                 }
00317         }
00318 
00319         return result;
00320 }
00321 
00322 //-----------------------------------------------
00323 std::string CanESD::GetErrorStr(int ntstatus) const
00324 {
00325         switch (ntstatus)
00326         {
00327         case NTCAN_SUCCESS:                     return "NTCAN_SUCCESS";
00328         case NTCAN_RX_TIMEOUT:                  return "NTCAN_RX_TIMEOUT";
00329         case NTCAN_TX_TIMEOUT:                  return "NTCAN_TX_TIMEOUT";
00330         case NTCAN_TX_ERROR:                    return "NTCAN_TX_ERROR";
00331         case NTCAN_CONTR_OFF_BUS:               return "NTCAN_CONTR_OFF_BUS";
00332         case NTCAN_CONTR_BUSY:                  return "NTCAN_CONTR_BUSY";
00333         case NTCAN_CONTR_WARN:                  return "NTCAN_CONTR_WARN";
00334         case NTCAN_NO_ID_ENABLED:               return "NTCAN_NO_ID_ENABLED";
00335         case NTCAN_ID_ALREADY_ENABLED:          return "NTCAN_ID_ALREADY_ENABLED";
00336         case NTCAN_ID_NOT_ENABLED:              return "NTCAN_ID_NOT_ENABLED";
00337 
00338         case NTCAN_INVALID_FIRMWARE:            return "NTCAN_INVALID_FIRMWARE";
00339         case NTCAN_MESSAGE_LOST:                return "NTCAN_MESSAGE_LOST";
00340         case NTCAN_INVALID_HARDWARE:            return "NTCAN_INVALID_HARDWARE";
00341 
00342         case NTCAN_PENDING_WRITE:               return "NTCAN_PENDING_WRITE";
00343         case NTCAN_PENDING_READ:                return "NTCAN_PENDING_READ";
00344         case NTCAN_INVALID_DRIVER:              return "NTCAN_INVALID_DRIVER";
00345 
00346         case NTCAN_INVALID_PARAMETER:           return "NTCAN_INVALID_PARAMETER";
00347         case NTCAN_INVALID_HANDLE:              return "NTCAN_INVALID_HANDLE";
00348         case NTCAN_NET_NOT_FOUND:               return "NTCAN_NET_NOT_FOUND";
00349         case NTCAN_INSUFFICIENT_RESOURCES:      return "NTCAN_INSUFFICIENT_RESOURCES";
00350         
00351         case NTCAN_OPERATION_ABORTED:           return "NTCAN_OPERATION_ABORTED";
00352         }
00353         char msg[100];
00354         sprintf(msg, "unknown error code %d", ntstatus);
00355         return msg;
00356 }
00357 
00367 int CanESD::readEvent()
00368 {
00369         EVMSG evmsg;
00370         int iRet = 0;
00371         int ret;
00372 
00373         ret = canReadEvent(m_Handle, &evmsg, NULL);
00374         
00375         if(ret == NTCAN_SUCCESS)
00376         {
00377                 if( (int)evmsg.evid == NTCAN_EV_CAN_ERROR ) {
00378                         switch( evmsg.evdata.s[0] ) {
00379                                 case 0x00:
00380                                         iRet = 0;
00381                                         break;
00382                                 case 0xC0:
00383                                         iRet = -6;
00384                                         std::cout << "BUS OFF" << std::endl;
00385                                         break;
00386                                 case 0x40:
00387                                         iRet = -7;
00388                                         std::cout << "ERROR PASSIVE" << std::endl;
00389                                         break;
00390                         }
00391                         if( evmsg.evdata.s[3] != 0 ) {
00392                                 iRet = -3;
00393                                 std::cout << "Lost " << (int)evmsg.evdata.s[3] << " messages" << std::endl;
00394                         } else if( evmsg.evdata.s[5] != 0 ) {
00395                                 iRet = -5;
00396                                 std::cout << "Lost " << (int)evmsg.evdata.s[5] << " messages from fifo" << std::endl;
00397                         }
00398                 }
00399         }
00400         return iRet;
00401 }
00402 


cob_generic_can
Author(s): Christian Connette
autogenerated on Sun Oct 5 2014 23:01:41