SerRelayBoard.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_driver
00012  * ROS package name: cob_relayboard
00013  * Description: Class for communication with relayboard. The relayboard is mainly used for reading the Emergencystop and Laserscannerstop states.
00014  *                                                              
00015  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00016  *                      
00017  * Author: Philipp Koehler
00018  * Supervised by: Christian Connette, email:christian.connette@ipa.fhg.de
00019  *
00020  * Date of creation: March 2010
00021  * ToDo:
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00034  *       Engineering and Automation (IPA) nor the names of its
00035  *       contributors may be used to endorse or promote products derived from
00036  *       this software without specific prior written permission.
00037  *
00038  * This program is free software: you can redistribute it and/or modify
00039  * it under the terms of the GNU Lesser General Public License LGPL as 
00040  * published by the Free Software Foundation, either version 3 of the 
00041  * License, or (at your option) any later version.
00042  * 
00043  * This program is distributed in the hope that it will be useful,
00044  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00045  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00046  * GNU Lesser General Public License LGPL for more details.
00047  * 
00048  * You should have received a copy of the GNU Lesser General Public 
00049  * License LGPL along with this program. 
00050  * If not, see <http://www.gnu.org/licenses/>.
00051  *
00052  ****************************************************************/
00053 
00054 
00055 #include <math.h>
00056 #include <cob_relayboard/SerRelayBoard.h>
00057 
00058 //-----------------------------------------------
00059 
00060 
00061 // #define NUM_BYTE_SEND 79 //Total amount of data sent to relayboard in one message, is now passed and set as protocol-version argument in constructor
00062 
00063 #define RS422_BAUDRATE 420000
00064 #define RS422_RX_BUFFERSIZE 1024
00065 #define RS422_TX_BUFFERSIZE 1024
00066 
00067 #define RS422_TIMEOUT 0.025
00068 
00069 #define NUM_BYTE_REC_MAX 120
00070 #define NUM_BYTE_REC_HEADER 4 //Header bytes, which are used to identify the beginning of a new received message {0x02, 0x80, 0xD6, 0x02}
00071 #define NUM_BYTE_REC_CHECKSUM 2 //checksum for message, that is built as the sum of all data bytes contained in the message
00072 #define NUM_BYTE_REC 104 //Total amount of data bytes in a received message (from the relayboard)
00073 
00074 
00075 //-----------------------------------------------
00076 SerRelayBoard::SerRelayBoard(std::string ComPort, int ProtocolVersion)
00077 {
00078         m_iProtocolVersion = ProtocolVersion;
00079         if(m_iProtocolVersion == 1)
00080                 m_NUM_BYTE_SEND = 50;
00081         else if(m_iProtocolVersion == 2)
00082                 m_NUM_BYTE_SEND = 79;
00083         else
00084                 m_NUM_BYTE_SEND = 50;
00085 
00086         m_bComInit = false;
00087         m_sNumComPort = ComPort;
00088 
00089         m_iRelBoardBattVoltage = 0;
00090         m_iConfigRelayBoard = 0;
00091         m_iRelBoardKeyPad = 0xFFFF;
00092         m_iCmdRelayBoard = 0;
00093         m_iDigIn = 0;
00094 }
00095 
00096 //-----------------------------------------------
00097 SerRelayBoard::~SerRelayBoard()
00098 {
00099         m_SerIO.close();
00100 }
00101 
00102 //-----------------------------------------------
00103 int SerRelayBoard::evalRxBuffer()
00104 {
00105         static int siNoMsgCnt = 0;
00106         
00107         const int c_iNrBytesMin = NUM_BYTE_REC_HEADER + NUM_BYTE_REC + NUM_BYTE_REC_CHECKSUM;
00108         const int c_iSizeBuffer = 4096;
00109 
00110         int i;
00111         int errorFlag = NO_ERROR;
00112         int iNrBytesInQueue, iNrBytesRead, iDataStart;
00113         unsigned char cDat[c_iSizeBuffer];
00114         unsigned char cTest[4] = {0x02, 0x80, 0xD6, 0x02};
00115 
00116         if( !m_bComInit ) return NOT_INITIALIZED;
00117 
00118         //enough data in queue?
00119         iNrBytesInQueue = m_SerIO.getSizeRXQueue();
00120         if(iNrBytesInQueue < c_iNrBytesMin)
00121         {
00122                 //there are too less bytes in queue
00123                 siNoMsgCnt++;
00124                 if(siNoMsgCnt > 29)
00125                 {
00126                         //std::cerr << "Relayboard: " << siNoMsgCnt << " cycles no msg received";
00127                         siNoMsgCnt = 0;
00128                         errorFlag = NO_MESSAGES;
00129                 } else errorFlag = TOO_LESS_BYTES_IN_QUEUE;
00130                 
00131                 return errorFlag;
00132         }
00133         else
00134         {
00135                 siNoMsgCnt = 0;
00136         }
00137 
00138         // search most recent data from back of queue
00139         iNrBytesRead = m_SerIO.readBlocking((char*)&cDat[0], iNrBytesInQueue);
00140         for(i = (iNrBytesRead - c_iNrBytesMin); i >= 0 ; i--)
00141         {
00142                 //try to find start bytes
00143                 if((cDat[i] == cTest[0]) && (cDat[i+1] == cTest[1]) && (cDat[i+2] == cTest[2]) && (cDat[i+3] == cTest[3]))
00144                 {
00145                         iDataStart = i + 4;
00146 
00147                         // checksum ok?
00148                         if( convRecMsgToData(&cDat[iDataStart]) )
00149                         {
00150                                 return errorFlag;
00151                         }
00152                         else
00153                         {
00154                                 //std::cerr << "Relayboard: checksum error";
00155                                 errorFlag = CHECKSUM_ERROR;
00156                                 return errorFlag;
00157                         }
00158                 }
00159         }
00160 
00161         return errorFlag;
00162 }
00163 
00164 //-----------------------------------------------
00165 bool SerRelayBoard::init()
00166 {
00167         int iRet;
00168         
00169         m_SerIO.setBaudRate(RS422_BAUDRATE);
00170         m_SerIO.setDeviceName( m_sNumComPort.c_str() );
00171         m_SerIO.setBufferSize(RS422_RX_BUFFERSIZE, RS422_TX_BUFFERSIZE);
00172         m_SerIO.setTimeout(RS422_TIMEOUT);
00173 
00174         iRet = m_SerIO.open();
00175 
00176         m_bComInit = true;
00177 
00178         return true;
00179 }
00180 
00181 //-----------------------------------------------
00182 bool SerRelayBoard::reset()
00183 {
00184         m_SerIO.close();
00185         m_bComInit = false;
00186 
00187         init();
00188 
00189         return true;
00190 }
00191 
00192 //-----------------------------------------------
00193 bool SerRelayBoard::shutdown()
00194 {
00195         m_SerIO.close();
00196 
00197         m_bComInit = false;
00198         
00199         return true;
00200 }
00201 
00202 
00203 //-----------------------------------------------
00204 bool SerRelayBoard::isEMStop()
00205 {
00206         if( (m_iRelBoardStatus & 0x0001) != 0)
00207         {
00208                 return true;
00209         }
00210         else
00211         {
00212                 return false;
00213         }
00214 }
00215 
00216 //-----------------------------------------------
00217 bool SerRelayBoard::isScannerStop()
00218 {
00219         if( (m_iRelBoardStatus & 0x0002) != 0)
00220         {
00221                 return true;
00222         }
00223         else
00224         {
00225                 return false;
00226         }
00227 }
00228 
00229 //-----------------------------------------------
00230 int SerRelayBoard::sendRequest() {
00231         int errorFlag = NO_ERROR;
00232         int iNrBytesWritten;
00233 
00234         unsigned char cMsg[m_NUM_BYTE_SEND];
00235         
00236         m_Mutex.lock();
00237         
00238                 convDataToSendMsg(cMsg);
00239 
00240                 m_SerIO.purgeTx();
00241 
00242                 iNrBytesWritten = m_SerIO.write((char*)cMsg, m_NUM_BYTE_SEND);
00243         
00244                 if(iNrBytesWritten < m_NUM_BYTE_SEND) {
00245                         //std::cerr << "Error in sending message to Relayboard over SerialIO, lost bytes during writing" << std::endl;
00246                         errorFlag = GENERAL_SENDING_ERROR;
00247                 }
00248 
00249         m_Mutex.unlock();
00250 
00251         return errorFlag;
00252 }
00253 
00254 int SerRelayBoard::setDigOut(int iChannel, bool bOn)
00255 {
00256         switch( iChannel)
00257         {
00258         case 0:
00259 
00260                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_CHARGE_RELAY; }
00261                 else { m_iCmdRelayBoard &= ~CMD_SET_CHARGE_RELAY; }
00262                 
00263                 break;
00264 
00265         case 1:
00266 
00267                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY1; }
00268                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY1; }
00269 
00270                 break;
00271 
00272         case 2:
00273 
00274                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY2; }
00275                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY2; }
00276 
00277                 break;
00278 
00279         case 3:
00280 
00281                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY3; }
00282                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY3; }
00283 
00284                 break;
00285 
00286         case 4:
00287 
00288                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY4; }
00289                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY4; }
00290 
00291                 break;
00292 
00293         case 5:
00294 
00295                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY5; }
00296                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY5; }
00297 
00298                 break;
00299 
00300         case 6:
00301 
00302                 if(bOn) { m_iCmdRelayBoard |= CMD_SET_RELAY6; }
00303                 else { m_iCmdRelayBoard &= ~CMD_SET_RELAY6; }
00304 
00305                 break;
00306 
00307         default:
00308 
00309                 return -1;
00310         }
00311         
00312         return 0;
00313 }
00314 //-----------------------------------------------
00315 int SerRelayBoard::getAnalogIn(int* piAnalogIn)
00316 {
00317         piAnalogIn[0] = m_iChargeCurrent;
00318         piAnalogIn[1] = m_iRelBoardBattVoltage;
00319         piAnalogIn[2] = m_iRelBoardTempSensor;
00320         piAnalogIn[3] = m_iRelBoardKeyPad;
00321         piAnalogIn[4] = m_iRelBoardAnalogIn[0];
00322         piAnalogIn[5] = m_iRelBoardAnalogIn[1];
00323         piAnalogIn[6] = m_iRelBoardAnalogIn[2];
00324         piAnalogIn[7] = m_iRelBoardAnalogIn[3];
00325 
00326         return 0;
00327 }
00328 
00329 //-----------------------------------------------
00330 int SerRelayBoard::getDigIn()
00331 {
00332         return m_iDigIn;
00333 }
00334 
00335 //-----------------------------------------------
00336 void SerRelayBoard::convDataToSendMsg(unsigned char cMsg[])
00337 {
00338         int i;
00339         int iCnt = 0;
00340         int iChkSum = 0;
00341 
00342         cMsg[iCnt++] = 1;//CMD_RELAISBOARD_GET_DATA;
00343 
00344         cMsg[iCnt++] = m_iConfigRelayBoard >> 8;
00345         cMsg[iCnt++] = m_iConfigRelayBoard;
00346 
00347         cMsg[iCnt++] = m_iCmdRelayBoard >> 8;
00348         cMsg[iCnt++] = m_iCmdRelayBoard;
00349         
00350         // fill remaining msg with 0's
00351         do
00352         {
00353                 cMsg[iCnt++] = 0;
00354         }
00355         while(iCnt < (m_NUM_BYTE_SEND - 2));
00356 
00357         // calc checksum: summation of all bytes in the message
00358         for(i = 0; i < (m_NUM_BYTE_SEND - 2); i++)
00359         {
00360                 iChkSum += cMsg[i];
00361         }
00362 
00363         cMsg[m_NUM_BYTE_SEND - 2] = iChkSum >> 8;
00364         cMsg[m_NUM_BYTE_SEND - 1] = iChkSum;
00365 
00366         // reset flags
00367         m_iCmdRelayBoard &= ~CMD_RESET_POS_CNT;
00368 }
00369 
00370 //-----------------------------------------------
00371 bool SerRelayBoard::convRecMsgToData(unsigned char cMsg[])
00372 {
00373         const int c_iStartCheckSum = NUM_BYTE_REC;
00374         
00375         int i;
00376         unsigned int iTxCheckSum;
00377         unsigned int iCheckSum;
00378 
00379         m_Mutex.lock();
00380 
00381         // test checksum: checksum should be sum of all bytes
00382         iTxCheckSum = (cMsg[c_iStartCheckSum + 1] << 8) | cMsg[c_iStartCheckSum];
00383         
00384         iCheckSum = 0;
00385         for(i = 0; i < c_iStartCheckSum; i++)
00386         {
00387                 iCheckSum += cMsg[i];
00388         }
00389 
00390         if(iCheckSum != iTxCheckSum)
00391         {
00392                 return false;
00393         }
00394 
00395         // convert data
00396         int iCnt = 0;
00397 
00398         //RelayboardStatus bytes contain EM-Stop and Scanner-Stop bits
00399         m_iRelBoardStatus = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00400         iCnt += 2;
00401 
00402         //unused at the moment
00403         m_iChargeCurrent = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00404         iCnt += 2;
00405 
00406         //unused at the moment
00407         m_iRelBoardBattVoltage = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00408         iCnt += 2;
00409 
00410         //unused at the moment  
00411         m_iRelBoardKeyPad = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00412         iCnt += 2;
00413 
00414         //unused at the moment
00415         for(i = 0; i < 4; i++)
00416         {
00417                 m_iRelBoardAnalogIn[i] = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00418                 iCnt += 2;
00419         }
00420 
00421         //unused at the moment
00422         m_iRelBoardTempSensor = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00423         iCnt += 2;
00424         
00425         //Digital Inputs
00426         //unused at the moment
00427         m_iDigIn = (cMsg[iCnt + 1] << 8) | cMsg[iCnt];
00428         iCnt += 2;
00429 
00430         //Throw away rest of the message, it was used for earlier purposes
00431 
00432         m_Mutex.unlock();
00433         return true;
00434 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


cob_relayboard
Author(s): Christian Connette
autogenerated on Fri Mar 1 2013 17:46:29