Ignore:
Timestamp:
05/04/13 11:21:35 (12 years ago)
Author:
tbretz
Message:
Let the event buffer store the index of the corresponding runCtrl entry.
File:
1 edited

Legend:

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

    r15333 r15490  
    3737        kFeedbackGlobal,
    3838        kCurrents,
     39        kCurrentsNew,
    3940    };
    4041
     
    9495    int HandleCameraTemp(const EventImp &evt)
    9596    {
    96         if (fControlType!=kTemp && fControlType!=kCurrents)
     97        if (fControlType!=kTemp && fControlType!=kCurrents && fControlType!=kCurrentsNew)
    9798            return GetCurrentState();
    9899
     
    123124        fCursorTemp++;
    124125
    125         return HandleCurrentControl();
     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();
    126364    }
    127365
     
    8061044            HandleCalibration(evt);
    8071045
    808         if (fControlType==kFeedbackGlobal || fControlType==kCurrents)
     1046        if (fControlType==kFeedbackGlobal || fControlType==kCurrents || fControlType==kCurrentsNew)
    8091047            AverageCurrents(evt);
    8101048
     
    9531191        fOutputEnabled = evt.GetBool();
    9541192
    955         if (fControlType==kCurrents)
     1193        if (fControlType==kCurrents || fControlType==kCurrentsNew)
    9561194            if (fCursorTemp>1)
    9571195                fCursorTemp = 1;
     
    10581296        ostringstream out;
    10591297        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";
    10601323        Message(out);
    10611324
     
    12481511                return fOutputEnabled ? Feedback::State::kTempCtrlRunning : Feedback::State::kTempCtrlIdle;
    12491512            }
    1250             if (fControlType==kCurrents)
     1513            if (fControlType==kCurrents || fControlType==kCurrentsNew)
    12511514            {
    12521515                static Time past;
Note: See TracChangeset for help on using the changeset viewer.