MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Instruments/Ocean/iBattery/BluefinBatteryDriverV2.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines