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