BeoSubBallast.C
Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include "BeoSub/BeoSubBallast.H"
00039 #include "Devices/BeoChip.H"
00040 
00041 
00042 BeoSubBallast::BeoSubBallast(OptionManager& mgr ,
00043                              const std::string& descrName,
00044                              const std::string& tagName) :
00045   ModelComponent(mgr, descrName, tagName),
00046   itsPulsesPerFill(tagName+"PulsesPerFill", this, 435),
00047   itsOutRed(tagName+"OutRed", this, 0),
00048   itsOutWhite(tagName+"OutWhite", this, 1),
00049   itsInYellow(tagName+"InYellow", this, 0),
00050   itsInWhite(tagName+"InWhite", this, 1),
00051   itsBeoChip(), itsDesiredPulses(0), itsCurrentPulses(10),
00052   itsDirection(Idle), itsPreviousDirection(Idle),
00053   itsIsFull(false), itsIsEmpty(false), itsInitialized(false),
00054   itsPreviousInputs(0), itsGotEndstop(false)
00055 {
00056   pthread_mutex_init(&itsLock, NULL);
00057 }
00058 
00059 
00060 void BeoSubBallast::setBeoChip(nub::soft_ref<BeoChip>& bc)
00061 { itsBeoChip = bc; }
00062 
00063 
00064 BeoSubBallast::~BeoSubBallast()
00065 {
00066   pthread_mutex_destroy(&itsLock);
00067 }
00068 
00069 
00070 void  BeoSubBallast::set(const float val, const bool blocking)
00071 {
00072   if (itsBeoChip.get() == NULL) LFATAL("I need a BeoChip!");
00073   bool waitdone = true;
00074 
00075   pthread_mutex_lock(&itsLock);
00076 
00077   
00078   float v = val;
00079   if (v < 0.0F) { LERROR("CAUTION: Value %f clamped to 0.0", v); v = 0.0F; }
00080   if (v > 1.0F) { LERROR("CAUTION: Value %f clamped to 1.0", v); v = 1.0F; }
00081   itsDesiredPulses = int(val * itsPulsesPerFill.getVal() + 0.5F);
00082 
00083   
00084   if (itsDesiredPulses > itsCurrentPulses) move(Filling);
00085   else if (itsDesiredPulses < itsCurrentPulses) move(Emptying);
00086   else move(Idle);
00087 
00088   pthread_mutex_unlock(&itsLock);
00089 
00090   if (blocking)
00091     {
00092       while(waitdone)
00093         {
00094           
00095           bool done = false;
00096           pthread_mutex_lock(&itsLock);
00097           if (itsDirection == Idle) done = true;
00098           pthread_mutex_unlock(&itsLock);
00099 
00100           if (done) break; else usleep(50000);
00101         }
00102     }
00103 }
00104 
00105 
00106 void BeoSubBallast::mechanicalInitialize()
00107 {
00108   
00109   
00110   
00111   
00112   
00113   
00114   
00115   
00116   
00117   
00118 
00119   CLINFO("filling...");
00120   set(1.0F, false); sleep(4);
00121   CLINFO("emptying...");
00122   set(0.0F, true);
00123 }
00124 
00125 
00126 float BeoSubBallast::get() const
00127 {
00128   pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock));
00129   const float ret = float(itsCurrentPulses) / itsPulsesPerFill.getVal();
00130   pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock));
00131   return ret;
00132 }
00133 
00134 
00135 int BeoSubBallast::getPulses() const
00136 {
00137   pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock));
00138   int ret = itsCurrentPulses;
00139   pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock));
00140   return ret;
00141 }
00142 
00143 
00144 void BeoSubBallast::input(const int val)
00145 {
00146   
00147   if (itsInitialized == false) { inputDuringInit(val); return; }
00148 
00149   pthread_mutex_lock(&itsLock);
00150 
00151   
00152   int changed = itsPreviousInputs ^ val;
00153   bool opto = ((changed & (1 << itsInYellow.getVal())) != 0);
00154   bool endstop = ((val & (1 << itsInWhite.getVal())) != 0);
00155   itsPreviousInputs = val;
00156 
00157   
00158   
00159   
00160 
00161   
00162   
00163   
00164   
00165   
00166   if (opto)
00167     {
00168       switch (itsDirection)
00169         {
00170         case Filling:
00171           ++ itsCurrentPulses;
00172           if (itsCurrentPulses >= itsDesiredPulses) move(Idle);
00173           break;
00174 
00175         case Emptying:
00176           -- itsCurrentPulses;
00177           if (itsCurrentPulses <= itsDesiredPulses) move(Idle);
00178           break;
00179 
00180         case Idle:
00181           {
00182             switch (itsPreviousDirection)
00183               {
00184               case Filling:
00185                 if (itsCurrentPulses < itsPulsesPerFill.getVal())
00186                   ++ itsCurrentPulses;
00187                 break;
00188 
00189               case Emptying:
00190                 if (itsCurrentPulses > 0)
00191                   -- itsCurrentPulses;
00192                 break;
00193 
00194               case Idle:
00195                 CLERROR("Received pulse while Idle! -- DISCARDED");
00196               }
00197           }
00198         }
00199     }
00200 
00201   
00202   if (endstop == false) itsGotEndstop = false;
00203 
00204   
00205   
00206   if (itsDirection != Idle)
00207     {
00208       if (endstop == false)
00209         {
00210           itsIsFull = false;
00211           itsIsEmpty = false;
00212         }
00213       else
00214         {
00215           
00216           
00217           
00218           
00219           if (itsIsFull == false && itsIsEmpty == false)
00220             {
00221               
00222               
00223               
00224               
00225               
00226               
00227               
00228               
00229               
00230               
00231               
00232               
00233               
00234               if (itsGotEndstop ||
00235                   itsCurrentPulses < itsPulsesPerFill.getVal() / 10 ||
00236                   itsCurrentPulses > (itsPulsesPerFill.getVal()*9) / 10)
00237                 {
00238                   
00239                   if (itsCurrentPulses > itsPulsesPerFill.getVal() / 2)
00240                     {
00241                       
00242                       itsCurrentPulses = itsPulsesPerFill.getVal();
00243                       move(Idle); itsIsFull = true;
00244                       CLINFO("Endstop reached -> full");
00245                     }
00246                   else
00247                     {
00248                       
00249                       itsCurrentPulses = 0;
00250                       move(Idle); itsIsEmpty = true;
00251                       CLINFO("Endstop reached -> empty");
00252                     }
00253                 }
00254               else
00255                 itsGotEndstop = true; 
00256             }
00257         }
00258     }
00259 
00260   
00261 
00262   pthread_mutex_unlock(&itsLock);
00263 }
00264 
00265 
00266 void BeoSubBallast::inputDuringInit(const int val)
00267 {
00268   pthread_mutex_lock(&itsLock);
00269 
00270   bool endstop = ((val & (1 << itsInWhite.getVal())) != 0);
00271   itsPreviousInputs = val;
00272 
00273   
00274 
00275   
00276   
00277   
00278 
00279   
00280   
00281   if (itsDirection != Idle)
00282     {
00283       if (endstop == false)
00284         {
00285           itsIsFull = false;
00286           itsIsEmpty = false;
00287         }
00288       else
00289         {
00290           
00291           switch (itsDirection)
00292             {
00293             case Filling:
00294               
00295               if (itsIsFull == false && itsIsEmpty == false)
00296                 {
00297                   
00298                   itsCurrentPulses = itsPulsesPerFill.getVal();
00299                   move(Idle); itsIsFull = true;
00300                 }
00301               break;
00302 
00303             case Emptying:
00304               
00305               if (itsIsFull == false && itsIsEmpty == false)
00306                 {
00307                   
00308                   itsCurrentPulses = 0;
00309                   move(Idle); itsIsEmpty = true;
00310 
00311 
00312                   
00313                   CLINFO("Mechanical initialization complete.");
00314                   itsInitialized = true;
00315                 }
00316               break;
00317 
00318             default:
00319               break;
00320             }
00321         }
00322     }
00323 
00324   
00325   pthread_mutex_unlock(&itsLock);
00326 }
00327 
00328 
00329 bool BeoSubBallast::moving() const
00330 {
00331   pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock));
00332   bool ret = (itsDirection != Idle);
00333   pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock));
00334   return ret;
00335 }
00336 
00337 
00338 void BeoSubBallast::move(const MotorDirection dir)
00339 {
00340   
00341   switch(dir)
00342     {
00343     case Filling:
00344       if (itsDirection != Filling) itsPreviousDirection = itsDirection;
00345       itsDirection = Filling;
00346       itsBeoChip->setDigitalOut(itsOutRed.getVal(), true);
00347       itsBeoChip->setDigitalOut(itsOutWhite.getVal(), false);
00348       break;
00349     case Emptying:
00350       if (itsDirection != Emptying) itsPreviousDirection = itsDirection;
00351       itsDirection = Emptying;
00352       itsBeoChip->setDigitalOut(itsOutRed.getVal(), false);
00353       itsBeoChip->setDigitalOut(itsOutWhite.getVal(), true);
00354       break;
00355     case Idle:
00356       if (itsDirection != Idle) itsPreviousDirection = itsDirection;
00357       itsDirection = Idle;
00358       itsBeoChip->setDigitalOut(itsOutRed.getVal(), false);
00359       itsBeoChip->setDigitalOut(itsOutWhite.getVal(), false);
00360       break;
00361     default:
00362       CLERROR("Unknown move command ignored");
00363     }
00364 }
00365 
00366 
00367 
00368 
00369 
00370