Ignore:
Timestamp:
05/04/13 11:22:21 (11 years ago)
Author:
tbretz
Message:
Reverting to last revision.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/feedback.cc

    r15490 r15493  
    3737        kFeedbackGlobal,
    3838        kCurrents,
    39         kCurrentsNew,
    4039    };
    4140
     
    9594    int HandleCameraTemp(const EventImp &evt)
    9695    {
    97         if (fControlType!=kTemp && fControlType!=kCurrents && fControlType!=kCurrentsNew)
     96        if (fControlType!=kTemp && fControlType!=kCurrents)
    9897            return GetCurrentState();
    9998
     
    124123        fCursorTemp++;
    125124
    126         return fControlType==kCurrentsNew ? HandleCurrentControlNew() : HandleCurrentControl();
    127     }
    128 
    129     int HandleCurrentControlNew()
    130     {
    131         if (GetCurrentState()==Feedback::State::kCalibrating && fBiasOffset>fTempOffset-1.2)
    132         {
    133             fCursorTemp = 0;
    134 
    135             ostringstream msg;
    136             msg << " (applied calibration offset " << fBiasOffset << "V exceeds temperature correction " << fTempOffset << "V - 1.2V.";
    137             Warn("Trying to calibrate above G-APD breakdown volatge!");
    138             Warn(msg);
    139             return GetCurrentState();
    140         }
    141 
    142         double avg[2] = {   0,   0 };
    143         double min[2] = {  90,  90 };
    144         double max[2] = { -90, -90 };
    145         int    num[2] = {   0,   0 };
    146 
    147         vector<double> med[2];
    148         med[0].resize(416);
    149         med[1].resize(416);
    150 
    151         const float *Ravg = fCalibration.data()+BIAS::kNumChannels*2; // Measured resistance
    152 
    153         vector<float> vec(2*BIAS::kNumChannels+2);
    154 
    155         vec[BIAS::kNumChannels*2]   = fTempOffset;
    156         vec[BIAS::kNumChannels*2+1] = fBiasOffset;
    157 
    158         float *Uoff = vec.data()+BIAS::kNumChannels;
    159 
    160         if (GetCurrentState()==Feedback::State::kCalibrating)
    161             for (int i=0; i<BIAS::kNumChannels; i++)
    162                 Uoff[i] = fBiasOffset;
    163         else
    164             for (int i=0; i<BIAS::kNumChannels; i++)
    165                 Uoff[i] = fTempOffset+fBiasOffset;
    166 
    167         if (fControlType==kCurrentsNew)
    168         {
    169             // Would be a devision by zero. We need informations first.
    170             if (fCursorCur==0)
    171                 return GetCurrentState();
    172 
    173             for (int i=0; i<BIAS::kNumChannels; i++)
    174             {
    175                 const PixelMapEntry &hv = fMap.hv(i);
    176                 if (!hv)
    177                     continue;
    178 
    179                 // Nominal breakdown voltage (includes overvoltage already)
    180                 double Ubd = fVoltGapd[i];
    181 
    182                 // Nominal breakdown voltage excluding overvoltage of 1.1V
    183                 Ubd -= 1.1;
    184 
    185                 // Correct breakdown voltage for temperature dependence
    186                 Ubd += fTempOffset;
    187 
    188                 // Number of G-APDs in this patch
    189                 const int N = hv.group() ? 5 : 4;
    190 
    191                 // 100 Ohm measurement resistor for current measurement
    192                 const double R2 = 100;
    193 
    194                 // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera)
    195                 const double R4 = 2000;
    196 
    197                 // Serial resistor of the individual G-APDs
    198                 double R5 = 3900/N;
    199 
    200                 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
    201                 if (i==66)                 // Pixel 830(66)
    202                     R5 = 300;              // 2400 = 1/(3/3900 + 1/390)
    203                 if (i==191 || i==193)      // Pixel 583(191) / Pixel 1401(193)
    204                     R5 = 390/1.4;          // 379 = 1/(4/3900 + 1/390)
    205 
    206                 // Total resistance of branch with diode
    207                 const double R3 = R4+R5;
    208 
    209                 // Measured calibration resistor
    210                 const double R1 = Ravg[i] - R2;
    211 
    212                 // Voltage output of bias crate
    213                 const double Uout = fBiasVolt[i];
    214 
    215                 // Average current measured for this channel
    216                 const double Imes = double(fCurrentsAvg[i])/fCursorCur * (5000/4096.); // [uA]
    217 
    218                 // Voltage drop at measurement resistor R2 is define
    219                 // bythe measured current and the resistor
    220                 const double U2 = R2*Imes;
    221 
    222                 // The voltage seen by the calibration resistor R1 is defined by the
    223                 // bias crate output voltage minus the drop at the measurement resistor R2
    224                 const double U1 = Uout - U2;
    225 
    226                 // The current through the resistor R1 is defined
    227                 // by the applied voltage and the resistor
    228                 const double I1 = U1/R1;
    229 
    230                 // The current through the diode branch is the measured current
    231                 // minus the current through the calibration resistor R1
    232                 const double I3 = Imes - I1;
    233 
    234                 // The voltage drop in the diode branch (without the diode) is defined by the
    235                 // resistor and the current. It is 0 below the breakdown voltage of the G-APD
    236                 // is reached at the G-APD. This is the case when the output voltage minus
    237                 // the voltage drop at the calibration resistor reaches the breakdown voltage.
    238                 const double U3 = Uout-U2<Ubd ? 0 : R3*I3;
    239 
    240                 // Voltage drop at measurement resistor R2 and
    241                 // the total serial resistor R3 in the diode branch
    242                 const double Udrp = U2 + U3;
    243 
    244                 // Voltage finally at each G-APD (bias crate output voltage minus voltage drop)
    245                 const double Uapd = Uout - Udrp;
    246 
    247                 // The over-voltage seen by the G-APD (the voltage above the breakdown voltage) is
    248                 const double Uov = Uapd<Ubd ? 0 : Uapd - Ubd;
    249 
    250                 // The current through one G-APD is the sum divided by the number of G-APDs
    251                 // (assuming identical serial resistors)
    252                 double Iapd = I3/N;
    253 
    254                 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
    255                 // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an
    256                 // assumption: The differential resistance depends more on the NSB than on the PDE,
    257                 // thus it is at least comparable for all G-APDs in the patch. In addition, although the
    258                 // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not
    259                 // significantly influences the ohmic resistor or the G-APD because the differential
    260                 // resistor is large enough that the increase of the overvoltage does not dramatically
    261                 // increase the current flow as compared to the total current flow.
    262                 if (i==66)
    263                     Iapd *= 1.3;
    264                 if (i==191 || i==193)
    265                     Iapd *= 1.4;
    266 
    267                 // If the G-APD voltage is above the breakdown voltage we have the current through the
    268                 // G-APD and the over-voltage applied to the G-APD to calculate its differential resistor.
    269                 if (Uapd>Ubd)
    270                 {
    271                     // The differential resistance of the G-APD, i.e. the dependence of the
    272                     // current above the breakdown voltage, is given by
    273                     const double Rapd = Uov/Iapd;
    274 
    275                     // This allows us to estimate the current Iov at the overvoltage we want to apply
    276                     const double Iov = (1.1+fBiasOffset)/Rapd;
    277 
    278                     // This gives us an ohmic resistance Rov of the G-APD at the set-point
    279                     const double Rest = (Ubd+1.1+fBiasOffset)/Iov;
    280 
    281                     // This lets us estimate the total resistance Rtot of the circuit at the set-point
    282                     const double R3b  = R4 + (R5+Rest)/N;
    283                     const double Rtot = R2 + 1/(1/R1 + 1/R3b);
    284 
    285                     // From this we can estimate the output voltage we need to get the
    286                     // over-voltage at the G-APD as anticipated
    287                     const double r    = 1 + R3/R1 - (R2 + R3 + R3*R2/R1)/Rtot;
    288                     const double Uset = (Ubd+1.1+fBiasOffset)/r;
    289 
    290                     Uoff[i] = Uset - fVoltGapd[i];
    291                 }
    292 
    293                  // Calculate statistics only for channels with a valid calibration
    294                  if (Uov>0)
    295                  {
    296                      const int g = hv.group();
    297 
    298                      med[g][num[g]] = Uov;
    299                      avg[g] += Uov;
    300                      num[g]++;
    301 
    302                      if (Uov<min[g])
    303                          min[g] = Uov;
    304                      if (Uov>max[g])
    305                          max[g] = Uov;
    306                  }
    307             }
    308 
    309             sort(med[0].begin(), med[0].begin()+num[0]);
    310             sort(med[1].begin(), med[1].begin()+num[1]);
    311 
    312             fCurrentsAvg.assign(BIAS::kNumChannels, 0);
    313             fCursorCur = 0;
    314         }
    315 
    316         fDimDeviation.setQuality(fControlType);
    317         fDimDeviation.Update(vec);
    318 
    319         // Warning: Here it is assumed that the ramp up and down is done properly
    320         // within the time between two new temperatures and that the calibration
    321         // is finished within that time.
    322         if (GetCurrentState()!=Feedback::State::kCalibrating ||
    323             fDimBias.state()!=BIAS::State::kVoltageOff ||
    324             fCursorTemp!=1 || !fOutputEnabled)
    325         {
    326             if (!fOutputEnabled || fDimBias.state()!=BIAS::State::kVoltageOn)
    327                 return GetCurrentState();
    328 
    329             // Trigger calibration
    330             if (GetCurrentState()==Feedback::State::kCalibrating && fCursorTemp==2)
    331             {
    332                 DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
    333                 return GetCurrentState();
    334             }
    335         }
    336 
    337         ostringstream msg;
    338         msg << setprecision(4) << "Sending new absolute offset (" << fAppliedOffset << "V+" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << "V) to biasctrl.";
    339         Info(msg);
    340 
    341         if (fControlType==kCurrents && num[0]>0 && num[1]>0)
    342         {
    343             msg.str("");
    344             msg << "   Avg0=" << setw(7) << avg[0]/num[0]    << "  |  Avg1=" << setw(7) << avg[1]/num[1];
    345             Debug(msg);
    346 
    347             msg.str("");
    348             msg << "   Med0=" << setw(7) << med[0][num[0]/2] << "  |  Med1=" << setw(7) << med[1][num[1]/2];
    349             Debug(msg);
    350 
    351             msg.str("");
    352             msg << "   Min0=" << setw(7) << min[0]           << "  |  Min1=" << setw(7) << min[1];
    353             Debug(msg);
    354 
    355             msg.str("");
    356             msg << "   Max0=" << setw(7) << max[0]           << "  |  Max1=" << setw(7) << max[1];
    357             Debug(msg);
    358         }
    359 
    360         DimClient::sendCommandNB("BIAS_CONTROL/SET_ALL_CHANNELS_OFFSET",
    361                                  vec.data()+BIAS::kNumChannels, BIAS::kNumChannels*sizeof(float));
    362 
    363         return GetCurrentState();
     125        return HandleCurrentControl();
    364126    }
    365127
     
    1044806            HandleCalibration(evt);
    1045807
    1046         if (fControlType==kFeedbackGlobal || fControlType==kCurrents || fControlType==kCurrentsNew)
     808        if (fControlType==kFeedbackGlobal || fControlType==kCurrents)
    1047809            AverageCurrents(evt);
    1048810
     
    1191953        fOutputEnabled = evt.GetBool();
    1192954
    1193         if (fControlType==kCurrents || fControlType==kCurrentsNew)
     955        if (fControlType==kCurrents)
    1194956            if (fCursorTemp>1)
    1195957                fCursorTemp = 1;
     
    12961058        ostringstream out;
    12971059        out << "Starting current/temp feedback with an offset of " << fBiasOffset << "V";
    1298         Message(out);
    1299 
    1300         return GetCurrentState();
    1301     }
    1302 
    1303     int StartNewCurrentCtrl(const EventImp &evt)
    1304     {
    1305         if (!CheckEventSize(evt.GetSize(), "StartNewCurrentCtrl", 4))
    1306             return kSM_FatalError;
    1307 
    1308         if (fCalibration.size()==0)
    1309         {
    1310             Warn("Current control needs a bias crate calibration first... command ignored.");
    1311             return GetCurrentState();
    1312         }
    1313 
    1314         WarnState(true, false);
    1315 
    1316         fBiasOffset = evt.GetFloat();
    1317         fTempOffset = -3;
    1318         ResetData(0);
    1319         fControlType = kCurrentsNew;
    1320 
    1321         ostringstream out;
    1322         out << "Starting new current/temp feedback with an offset of " << fBiasOffset << "V";
    13231060        Message(out);
    13241061
     
    15111248                return fOutputEnabled ? Feedback::State::kTempCtrlRunning : Feedback::State::kTempCtrlIdle;
    15121249            }
    1513             if (fControlType==kCurrents || fControlType==kCurrentsNew)
     1250            if (fControlType==kCurrents)
    15141251            {
    15151252                static Time past;
Note: See TracChangeset for help on using the changeset viewer.