MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman and others 00010 // at MIT 2001-2002 and Oxford University 2003-2005. 00011 // email: pnewman@robots.ox.ac.uk. 00012 // 00013 // This file is part of a MOOS Instrument. 00014 // 00015 // This program is free software; you can redistribute it and/or 00016 // modify it under the terms of the GNU General Public License as 00017 // published by the Free Software Foundation; either version 2 of the 00018 // License, or (at your option) any later version. 00019 // 00020 // This program is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00023 // General Public License for more details. 00024 // 00025 // You should have received a copy of the GNU General Public License 00026 // along with this program; if not, write to the Free Software 00027 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00028 // 02111-1307, USA. 00029 // 00031 // BluefinBatteryDriverV2.cpp: implementation of the CBluefinBatteryDriverV2 class. 00032 // 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #endif 00037 00038 #include <MOOSGenLib/MOOSGenLib.h> 00039 #include <MOOSLIB/MOOSLib.h> 00040 #include <iomanip> 00041 00042 #include <strstream> 00043 00044 #include "BluefinBatteryDriverV2.h" 00045 00047 // Construction/Destruction 00049 00050 #define BLUEFIN_SMART_FULL 33.8 00051 #define BLUEFIN_SMART_EMPTY 25.9 00052 00053 CBluefinBatteryDriverV2::CBluefinBatteryDriverV2() 00054 { 00055 m_bEchoing = true; 00056 } 00057 00058 CBluefinBatteryDriverV2::~CBluefinBatteryDriverV2() 00059 { 00060 00061 } 00062 00063 bool CBluefinBatteryDriverV2::Initialise() 00064 { 00065 MOOSPause(1000); 00066 00067 //start clean 00068 m_pPort->Flush(); 00069 00070 //look for carriage return 00071 m_pPort->SetTermCharacter('\r'); 00072 00073 //who is out there? 00074 DiscoverAndMakeBatteries(); 00075 00076 //fetch battery information 00077 GetData(); 00078 00079 //if batteries have timed out turn them off and on 00080 //to remove timeout flag 00081 BATTERY_MAP::iterator p; 00082 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00083 { 00084 CBatteryPack & rPack =p->second; 00085 00086 SwitchPack(rPack,true); 00087 00088 if(rPack.m_sError != "NONE") 00089 { 00090 MOOSTrace("Clearing battery initial error flag \"%s\" for battery %d\n", 00091 rPack.m_sError.c_str(), 00092 rPack.m_nPackAddress); 00093 SwitchPack(rPack,false); 00094 SwitchPack(rPack,true); 00095 00096 GetData(); 00097 00098 if(rPack.m_sError !="NONE") 00099 { 00100 MOOSTrace("Battery %d still has an error - it will be ignored!\n", 00101 rPack.m_nPackAddress); 00102 rPack.m_bIgnore = true; 00103 } 00104 } 00105 } 00106 00107 return true; 00108 } 00109 00110 bool CBluefinBatteryDriverV2::Switch(bool bOn) 00111 { 00112 BATTERY_MAP::iterator p; 00113 00114 double dfMeanVoltage = 0; 00115 00116 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00117 { 00118 CBatteryPack & rPack = p->second; 00119 SwitchPack(rPack,bOn); 00120 } 00121 00122 return true; 00123 } 00124 00125 string CBluefinBatteryDriverV2::GetCellsString() 00126 { 00127 ostrstream os; 00128 BATTERY_MAP::iterator p; 00129 00130 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00131 { 00132 CBatteryPack & rPack = p->second; 00133 00134 os<<"PACK="<<rPack.m_nPackAddress<<":"; 00135 00136 os<<"V="<<rPack.m_dfVoltage<<","; 00137 os<<"Cells=["; 00138 00139 for(int nCell = 0; nCell<CELLS_PER_PACK;nCell++) 00140 { 00141 os<<rPack.m_Cells[nCell].m_dfVoltage<<","; 00142 } 00143 00144 os<<"];"; 00145 } 00146 00147 os<<ends; 00148 00149 string sResult = os.str(); 00150 00151 os.rdbuf()->freeze(0); 00152 00153 return sResult; 00154 } 00155 00156 00157 00158 bool CBluefinBatteryDriverV2::GetData() 00159 { 00160 SetEmptyVolts(BLUEFIN_SMART_EMPTY); 00161 SetFullVolts(BLUEFIN_SMART_FULL); 00162 00163 00164 BATTERY_MAP::iterator p; 00165 00166 double dfMeanVoltage = 0; 00167 int nIncluded = 0; 00168 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00169 { 00170 CBatteryPack & rPack = p->second; 00171 QueryBattery(rPack); 00172 00173 if(!rPack.m_bIgnore) 00174 { 00175 dfMeanVoltage += rPack.m_dfVoltage; 00176 nIncluded++; 00177 } 00178 00179 //read cells state.... 00180 QueryCellsState(rPack); 00181 00182 00183 } 00184 if(nIncluded>0) 00185 { 00186 //calculate mean voltage.. 00187 m_Status.m_dfVoltage = dfMeanVoltage/nIncluded; 00188 } 00189 else 00190 { 00191 m_Status.m_dfVoltage = 0; 00192 } 00193 00194 return true; 00195 } 00196 00197 bool CBluefinBatteryDriverV2::DiscoverAndMakeBatteries() 00198 { 00199 MOOSTrace("Discovering Packs...\n"); 00200 string sQuery = "!?\r"; 00201 string sReply; 00202 if(WriteAndRead(sQuery,sReply,2.0,true)) 00203 { 00204 MOOSTrace("Boards discovered: %s\n",sReply.c_str()); 00205 00206 00207 istrstream is(sReply.c_str()); 00208 is.flags(ios::hex); 00209 00210 while(!is.eof()) 00211 { 00212 int nPack=0; 00213 is>>ws; 00214 is>>nPack; 00215 if(nPack>0) 00216 { 00217 MOOSTrace("Creating Pack %d\n",nPack); 00218 CBatteryPack NewPack; 00219 NewPack.m_nPackAddress = nPack; 00220 NewPack.m_bIgnore = false; 00221 m_BatteryMap[nPack] = NewPack; 00222 } 00223 } 00224 } 00225 00226 MOOSTrace("There are %d batteries in the vehicle\n",m_BatteryMap.size()); 00227 00228 return true; 00229 } 00230 00231 //this is a custom function for reading and rwriting 00232 //in development RS232->485 converter echoed commands 00233 bool CBluefinBatteryDriverV2::WriteAndRead(string sOut, 00234 string &sReply, 00235 double dfTimeOut, 00236 bool bNoTerm) 00237 { 00238 if(!m_pPort->Write((char *)sOut.c_str(),sOut.size())) 00239 return false; 00240 00241 if(m_bEchoing) 00242 { 00243 string sWhatISaid; 00244 if(!m_pPort->GetTelegram(sWhatISaid,1.0)) 00245 { 00246 MOOSTrace("no command echo found\n!"); 00247 } 00248 } 00249 00250 if(bNoTerm) 00251 { 00252 //this is an unterminated reply... 00253 char Tmp[2000]; 00254 int nRead = m_pPort->ReadNWithTimeOut(Tmp,sizeof(Tmp),dfTimeOut); 00255 00256 if(nRead>0 && nRead< sizeof(Tmp)) 00257 { 00258 Tmp[nRead] = '\0'; 00259 sReply = string(Tmp); 00260 return true; 00261 } 00262 else 00263 { 00264 MOOSTrace("could not read unterminated telegram in %f seconds\n",dfTimeOut); 00265 return false; 00266 } 00267 } 00268 else 00269 { 00270 //we expect a standard reply 00271 if(dfTimeOut>0) 00272 { 00273 if(!m_pPort->GetTelegram(sReply,dfTimeOut)) 00274 { 00275 MOOSTrace("Failed telgram fetch\n"); 00276 return false; 00277 } 00278 } 00279 return true; 00280 } 00281 00282 return false; 00283 } 00284 00285 bool CBluefinBatteryDriverV2::QueryBattery(CBatteryPack &rPack) 00286 { 00287 ostrstream os; 00288 os.flags(ios::hex); 00289 00290 //format stream 00291 os<<"#"; 00292 os.fill('0'); 00293 os<<setw(2)<<rPack.m_nPackAddress; 00294 os<<"Q0\r"; 00295 os<<ends; 00296 00297 //make the string.. 00298 string sEnquire = os.str(); 00299 00300 //free memory 00301 os.rdbuf()->freeze(0); 00302 00303 string sReply; 00304 if(!WriteAndRead(sEnquire,sReply,1.0)) 00305 { 00306 MOOSTrace("failed battery status fetch on pack %d\n",rPack.m_nPackAddress); 00307 return false; 00308 } 00309 00310 //OK if we are here things look good! 00311 //start parsing 00312 00313 string sHeader,sState,sVoltage,sCurrent,sMaxTemp,sMinCell,sMaxCell,sLeak,sCapacity,sTime; 00314 istrstream is(sReply.c_str()); 00315 is>>sHeader>>ws; 00316 is>>sState>>ws; 00317 is>>sVoltage>>ws; 00318 is>>sCurrent>>ws; 00319 is>>sMaxTemp>>ws; 00320 is>>sMinCell>>ws; 00321 is>>sMaxCell>>ws; 00322 is>>sLeak>>ws; 00323 is>>sCapacity>>ws; 00324 is>>sTime>>ws; 00325 00326 00327 rPack.m_sComment = MOOSFormat("%s, Current = %s A,Temp = %s deg, Capacity = %sWh, CellMax = %sV CellMin = %sV", 00328 rPack.m_sState.c_str(), 00329 sCurrent.c_str(), 00330 sMaxTemp.c_str(), 00331 sCapacity.c_str(), 00332 sMaxCell.c_str(), 00333 sMinCell.c_str()); 00334 00335 //voltage is useful... 00336 rPack.m_dfVoltage = atof(sVoltage.c_str()); 00337 00338 //state is useful... 00339 ProcessStateString(rPack,sState); 00340 00341 00342 00343 return true; 00344 } 00345 00346 bool CBluefinBatteryDriverV2::SwitchPack(CBatteryPack &rPack, bool bOn) 00347 { 00348 MOOSTrace("Switching Pack %d %s\n",rPack.m_nPackAddress,bOn?"ON":"OFF"); 00349 00350 ostrstream os; 00351 os.flags(ios::hex); 00352 00353 //format stream 00354 os<<"#"; 00355 os.fill('0'); 00356 os<<setw(2)<<rPack.m_nPackAddress; 00357 os<<"B"; 00358 os<<(bOn?"D":"F"); 00359 os<<"\r"; 00360 os<<ends; 00361 00362 //make the string.. 00363 string sSwitch = os.str(); 00364 00365 //free memory 00366 os.rdbuf()->freeze(0); 00367 00368 string sReply; 00369 if(!WriteAndRead(sSwitch,sReply,1.0)) 00370 { 00371 MOOSTrace("failed switch pack %d\n",rPack.m_nPackAddress); 00372 return false; 00373 } 00374 00375 //and now disable watch dog - make an option later on.... 00376 //format stream 00377 if(bOn) 00378 { 00379 ostrstream os; 00380 os.flags(ios::hex); 00381 os<<"#"; 00382 os.fill('0'); 00383 os<<setw(2)<<rPack.m_nPackAddress; 00384 os<<"MF\r"<<ends; 00385 string sWDOff = os.str(); 00386 os.rdbuf()->freeze(0); 00387 00388 if(!WriteAndRead(sWDOff,sReply,1.0)) 00389 { 00390 MOOSTrace("failed to disable watch dog on %d\n",rPack.m_nPackAddress); 00391 return false; 00392 } 00393 00394 } 00395 00396 return true; 00397 00398 } 00399 00400 bool CBluefinBatteryDriverV2::ProcessStateString(CBatteryPack & rPack,string sState) 00401 { 00402 MOOSRemoveChars(sState," "); 00403 if(sState.size()!=2) 00404 return false; 00405 00406 switch(sState[0]) 00407 { 00408 case 'f': rPack.m_eState = OFF; rPack.m_sState = "OFF"; break; 00409 case 'd': rPack.m_eState = ON; rPack.m_sState = "ON";break; 00410 case 'c': rPack.m_eState = CHARGING; rPack.m_sState = "CHARGING";break; 00411 case 'b': rPack.m_eState = BALANCING;rPack.m_sState = "BALANCING"; break; 00412 } 00413 00414 switch(sState[1]) 00415 { 00416 case '-': rPack.m_sError = "NONE"; break; 00417 case 'V': rPack.m_sError = "OVERVOLTAGE"; break; 00418 case 'v': rPack.m_sError = "UNDERVOLTAGE"; break; 00419 case 'I': rPack.m_sError = "OVERCURRENT"; break; 00420 case 'T': rPack.m_sError = "CELL OVER TEMPERATURE"; break; 00421 case 'O': rPack.m_sError = "OIL OVERTEMPERATURE"; break; 00422 case 'C': rPack.m_sError = "CELL OVERVOLTAGE"; break; 00423 case 'c': rPack.m_sError = "CELL UNDERVOLTAGE"; break; 00424 case 'H': rPack.m_sError = "HARDWARE FAULT"; break; 00425 case 'h': rPack.m_sError = "TRANSIENT FAULT"; break; 00426 case 'm': rPack.m_sError = "TIMEOUT"; break; 00427 } 00428 00429 return true; 00430 00431 } 00432 00433 bool CBluefinBatteryDriverV2::QueryCellsState(CBatteryPack &rPack) 00434 { 00435 ostrstream os; 00436 os.flags(ios::hex); 00437 00438 //format stream 00439 os<<"#"; 00440 os.fill('0'); 00441 os<<setw(2)<<rPack.m_nPackAddress; 00442 os<<"Q1\r"; 00443 os<<ends; 00444 00445 //make the string.. 00446 string sEnquire = os.str(); 00447 00448 //free memory 00449 os.rdbuf()->freeze(0); 00450 00451 string sReply; 00452 if(!WriteAndRead(sEnquire,sReply,1.0)) 00453 { 00454 MOOSTrace("failed battery cell status fetch on pack %d\n",rPack.m_nPackAddress); 00455 return false; 00456 } 00457 00458 string sHeader = MOOSChomp(sReply," "); 00459 int nRead = 0; 00460 while(!sReply.empty() && nRead < CELLS_PER_PACK) 00461 { 00462 string sVal = MOOSChomp(sReply," "); 00463 double dfVal = atof(sVal.c_str()); 00464 rPack.m_Cells[nRead++].m_dfVoltage = dfVal; 00465 } 00466 00467 return true; 00468 } 00469 00470 string CBluefinBatteryDriverV2::GetErrorString() 00471 { 00472 BATTERY_MAP::iterator p; 00473 00474 m_sError = ""; 00475 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00476 { 00477 CBatteryPack & rPack = p->second; 00478 string sPackError = MOOSFormat("Pack[%d] Error = \"%s\"", 00479 rPack.m_nPackAddress, 00480 rPack.m_sError.c_str()); 00481 m_sError+=sPackError+";";; 00482 } 00483 00484 return m_sError; 00485 } 00486 00487 string CBluefinBatteryDriverV2::GetCommentString() 00488 { 00489 BATTERY_MAP::iterator p; 00490 00491 m_sComment = ""; 00492 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00493 { 00494 CBatteryPack & rPack = p->second; 00495 string sPackComment = MOOSFormat("Pack[%d] Comment = \"%s\"", 00496 rPack.m_nPackAddress, 00497 rPack.m_sComment.c_str()); 00498 m_sComment+=sPackComment+";"; 00499 } 00500 00501 return m_sComment; 00502 } 00503 00504 bool CBluefinBatteryDriverV2::IsError() 00505 { 00506 BATTERY_MAP::iterator p; 00507 00508 for(p = m_BatteryMap.begin();p!=m_BatteryMap.end();p++) 00509 { 00510 CBatteryPack & rPack = p->second; 00511 if(rPack.m_sError!="NONE" && rPack.m_sState =="ON") 00512 return true; 00513 } 00514 return false; 00515 } 00516 00517 00518 00519 00520 00521 00522 00523