Changeset 17173 for trunk/FACT++/src
- Timestamp:
- 09/19/13 16:13:22 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/feedback.cc
r17030 r17173 10 10 #include "Console.h" 11 11 #include "externals/PixelMap.h" 12 #include "externals/Interpolator2D.h" 12 13 13 14 #include "tools.h" … … 32 33 33 34 bool fIsVerbose; 34 bool fEnableOldAlgorithm;35 35 36 36 DimVersion fDim; … … 52 52 vector<float> fVoltGapd; // Nominal breakdown voltage + 1.1V 53 53 vector<float> fBiasVolt; // Output voltage as reported by bias crate (voltage between R10 and R8) 54 vector<float> fBiasR9; // 54 55 vector<uint16_t> fBiasDac; // Dac value corresponding to the voltage setting 55 56 … … 64 65 65 66 double fUserOffset; 66 double fTempOffset; 67 vector<double> fTempOffset; 68 float fTempOffsetAvg; 69 float fTempOffsetRms; 70 double fTempCoefficient; 67 71 double fTemp; 68 72 … … 109 113 { 110 114 fVoltGapd.assign(evt.Ptr<float>(), evt.Ptr<float>()+416); 115 fBiasR9.assign(evt.Ptr<float>()+2*416, evt.Ptr<float>()+3*416); 111 116 Info("Nominal bias voltages and calibration resistor received."); 112 117 } … … 131 136 int HandleCameraTemp(const EventImp &evt) 132 137 { 133 if (!CheckEventSize(evt.GetSize(), "HandleCameraTemp", 60*sizeof(float)))138 if (!CheckEventSize(evt.GetSize(), "HandleCameraTemp", 323*sizeof(float))) 134 139 { 135 140 fTimeTemp = Time(Time::none); … … 137 142 } 138 143 139 const float *ptr = evt.Ptr<float>(); 140 141 double avgt = 0; 142 int numt = 0; 143 for (int i=1; i<32; i++) 144 if (ptr[i]!=0) 145 { 146 avgt += ptr[i]; 147 numt++; 148 } 149 150 if (numt==0) 151 { 152 Warn("Received sensor temperatures all invalid."); 153 return GetCurrentState(); 154 } 155 156 avgt /= numt; // [deg C] 157 158 fTimeTemp = evt.GetTime(); 159 fTempOffset = (avgt-25)*0.0561765; // [V] From Hamamatsu datasheet 160 fTemp = avgt; 144 //fTempOffset = (avgt-25)*0.0561765; // [V] From Hamamatsu datasheet 145 //fTempOffset = (avgt-25)*0.05678; // [V] From Hamamatsu datasheet plus our own measurement (gein vs. temperature) 146 147 const float *ptr = evt.Ptr<float>(4); 148 149 fTimeTemp = evt.GetTime(); 150 fTemp = evt.Get<float>(321*4); 151 152 fTempOffsetAvg = (fTemp-25)*fTempCoefficient; 153 fTempOffsetRms = evt.Get<float>(322*4)*fTempCoefficient; 154 155 fTempOffset.resize(320); 156 for (int i=0; i<320; i++) 157 fTempOffset[i] = (ptr[i]-25)*fTempCoefficient; 161 158 162 159 return GetCurrentState(); … … 183 180 for (int i=0; i<BIAS::kNumChannels; i++) 184 181 { 185 avg[i] = double(fCurrentsAvg[i])/fCursorCur * conv;186 rms[i] = double(fCurrentsRms[i])/fCursorCur * conv * conv;187 188 rms[i] = sqrt(rms[i]-avg[i]*avg[i]);182 avg[i] = double(fCurrentsAvg[i])/fCursorCur * conv; 183 rms[i] = double(fCurrentsRms[i])/fCursorCur * conv * conv; 184 rms[i] -= avg[i]*avg[i]; 185 rms[i] = rms[i]<0 ? 0 : sqrt(rms[i]); 189 186 } 190 187 … … 235 232 memcpy(cal.Irms, rms.data(), 416*sizeof(float)); 236 233 237 fDimCalibration2.setData( fCalibration);234 fDimCalibration2.setData(cal); 238 235 fDimCalibration2.Update(fTimeCalib); 239 236 … … 405 402 406 403 data.Unom = overvoltage; 407 data.dUtemp = fTempOffset ;404 data.dUtemp = fTempOffsetAvg; 408 405 409 406 vector<float> vec(416); 410 407 408 /* 411 409 if (fEnableOldAlgorithm) 412 410 { 411 // ================================= old ======================= 413 412 // Pixel 583: 5 31 == 191 (5) C2 B3 P3 414 413 // Pixel 830: 2 2 == 66 (4) C0 B8 P1 … … 445 444 446 445 // Offset induced by the voltage above the calibration point 447 const double Ubd = fVoltGapd[i] + fTempOffset ;446 const double Ubd = fVoltGapd[i] + fTempOffsets[i]; 448 447 const double U0 = Ubd + overvoltage - fCalibVoltage[5][i]; // appliedOffset-fCalibrationOffset; 449 448 const double dI = U0/Ravg[i]; // [V/Ohm] … … 455 454 // Make sure that the averaged resistor is valid 456 455 const double dU = Ravg[i]>10000 ? r*(I*1e-6 - dI) : 0; 457 458 if (i==2)459 cout << setprecision(4)<< dU << endl;;460 456 461 457 vec[i] = Ubd + overvoltage + dU; … … 488 484 } 489 485 } 490 else 491 { 492 /* ================================= new ======================= */ 493 494 for (int i=0; i<320/*BIAS::kNumChannels*/; i++) 486 */ 487 488 for (int i=0; i<320/*BIAS::kNumChannels*/; i++) 489 { 490 const PixelMapEntry &hv = fMap.hv(i); 491 if (!hv) 492 continue; 493 494 // Number of G-APDs in this patch 495 const int N = hv.count(); 496 497 // Average measured ADC value for this channel 498 const double adc = Imes[i]/* * (5e-3/4096)*/; // [A] 499 500 // Current through ~100 Ohm measurement resistor 501 const double I8 = (adc-fCalibDeltaI[i])*fCalibR8[i]/100; 502 503 // Current through calibration resistors (R9) 504 // This is uncalibrated, biut since the corresponding calibrated 505 // value I8 is subtracted, the difference should yield a correct value 506 const double I9 = fBiasDac[i] * (1e-3/4096);//U9/R9; [A] 507 508 // Current in R4/R5 branch 509 const double Iout = I8>I9 ? I8 - I9 : 0; 510 511 // Applied voltage at calibration resistors, according to biasctrl 512 const double U9 = fBiasVolt[i]; 513 514 // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera) 515 const double R4 = 2000; 516 517 // Serial resistor of the individual G-APDs 518 double R5 = 3900./N; 519 520 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor 521 if (i==66) // Pixel 830(66) 522 R5 = 300; // 2400 = 1/(3/3900 + 1/390) 523 if (i==191 || i==193) // Pixel 583(191) / Pixel 1401(193) 524 R5 = 390/1.4; // 379 = 1/(4/3900 + 1/390) 525 526 // The measurement resistor 527 const double R8 = 100; 528 529 // Total resistance of branch with diodes (R4+R5) 530 // Assuming that the voltage output of the OpAMP is linear 531 // with the DAC setting and not the voltage at R9, the 532 // additional voltage drop at R8 must be taken into account 533 const double R = R4 + R5 + R8; 534 535 // For the patches with a broken resistor - ignoring the G-APD resistance - 536 // we get: 537 // 538 // I[R=3900] = Iout * 1/(10+(N-1)) = Iout /(N+9) 539 // I[R= 390] = Iout * (1 - 1/ (10+(N-1))) = Iout * (N+8)/(N+9) 540 // 541 // I[R=390] / I[R=3900] = N+8 542 // 543 // Udrp = Iout*3900/(N+9) + Iout*1000 + Iout*1000 = Iout * R 544 545 // Voltage drop in R4/R5 branch (for the G-APDs with correct resistor) 546 const double Udrp = R*Iout; 547 548 // Nominal breakdown voltage with correction for temperature dependence 549 const double Ubd = fVoltGapd[i] + fTempOffset[i]; 550 551 // Current overvoltage (at a G-APD with the correct 3900 Ohm resistor) 552 const double Uov = U9-Udrp-Ubd>0 ? U9-Udrp-Ubd : 0; 553 554 // Iout linear with U9 above Ubd 555 // 556 // Rx = (U9-Ubd)/Iout 557 // I' = (U9'-Ubd) / Rx 558 // Udrp' = R*I' 559 // Uov = U9' - Udrp' - Ubd 560 // Uov = overvoltage 561 // 562 // overvoltage = U9' - Udrp' - Ubd 563 // overvoltage = U9' - R*I' - Ubd 564 // overvoltage = U9' - R*((U9'-Ubd)/Rx) - Ubd 565 // overvoltage = U9' - U9'*R/Rx + Ubd*R/Rx - Ubd 566 // overvoltage = U9'*(1 - R/Rx) + Ubd*R/Rx - Ubd 567 // overvoltage - Ubd*R/Rx +Ubd = U9'*(1 - R/Rx) 568 // U9' = [ overvoltage - Ubd*R/Rx +Ubd ] / (1 - R/Rx) 569 // 570 571 // The current through one G-APD is the sum divided by the number of G-APDs 572 // (assuming identical serial resistors) 573 double Iapd = Iout/N; 574 575 // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an 576 // assumption: The differential resistance depends more on the NSB than on the PDE, 577 // thus it is at least comparable for all G-APDs in the patch. In addition, although the 578 // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not 579 // significantly influences the ohmic resistor or the G-APD because the differential 580 // resistor is large enough that the increase of the overvoltage does not dramatically 581 // increase the current flow as compared to the total current flow. 582 if (i==66 || i==191 || i==193) 583 Iapd = Iout/(N+9); // Iapd = R5*Iout/3900; 584 585 // The differential resistance of the G-APD, i.e. the dependence of the 586 // current above the breakdown voltage, is given by 587 //const double Rapd = Uov/Iapd; 588 // This allows us to estimate the current Iov at the overvoltage we want to apply 589 //const double Iov = overvoltage/Rapd; 590 591 // Estimate set point for over-voltage (voltage drop at the target point) 592 //const double Uset = Ubd + overvoltage + R*Iov*N; 593 const double Uset = Uov<0.3 ? Ubd + overvoltage + Udrp : Ubd + overvoltage + Udrp*pow(overvoltage/Uov, 1.66); 594 595 // Voltage set point 596 vec[i] = Uset; 597 598 /* 599 if (fDimBias.state()==BIAS::State::kVoltageOn && GetCurrentState()==Feedback::State::kInProgress && 600 fabs(Uov-overvoltage)>0.033) 601 cout << setprecision(4) << setw(3) << i << ": Uov=" << Uov << " Udrp=" << Udrp << " Iapd=" << Iapd*1e6 << endl; 602 */ 603 604 // Calculate statistics only for channels with a valid calibration 605 //if (Uov>0) 495 606 { 496 const PixelMapEntry &hv = fMap.hv(i); 497 if (!hv) 498 continue; 499 500 // Number of G-APDs in this patch 501 const int N = hv.count(); 502 503 // Average measured ADC value for this channel 504 const double adc = Imes[i]/* * (5e-3/4096)*/; // [A] 505 506 // Current through ~100 Ohm measurement resistor 507 const double I8 = (adc-fCalibDeltaI[i])*fCalibR8[i]/100; 508 509 // Applied voltage at calibration resistors, according to biasctrl 510 const double U9 = fBiasVolt[i]; 511 512 // Current through calibration resistors (R9) 513 // This is uncalibrated, biut since the corresponding calibrated 514 // value I8 is subtracted, the difference should yield a correct value 515 const double I9 = fBiasDac[i] * (1e-3/4096);//U9/R9; [A] 516 517 // Current in R4/R5 branch 518 const double Iout = I8>I9 ? I8 - I9 : 0; 519 520 // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera) 521 const double R4 = 2000; 522 523 // Serial resistor of the individual G-APDs 524 double R5 = 3900./N; 525 526 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor 527 if (i==66) // Pixel 830(66) 528 R5 = 300; // 2400 = 1/(3/3900 + 1/390) 529 if (i==191 || i==193) // Pixel 583(191) / Pixel 1401(193) 530 R5 = 390/1.4; // 379 = 1/(4/3900 + 1/390) 531 532 // Total resistance of branch with diodes 533 const double R = R4+R5; 534 535 // For the patches with a broken resistor - ignoring the G-APD resistance - 536 // we get: 537 // 538 // I[R=3900] = Iout * 1/(10+(N-1)) = Iout /(N+9) 539 // I[R= 390] = Iout * (1 - 1/ (10+(N-1))) = Iout * (N+8)/(N+9) 540 // 541 // I[R=390] / I[R=3900] = N+8 542 // 543 // Udrp = Iout*3900/(N+9) + Iout*1000 + Iout*1000 = Iout * R 544 545 // Voltage drop in R4/R5 branch (for the G-APDs with correct resistor) 546 const double Udrp = R*Iout; 547 548 // Nominal breakdown voltage with correction for temperature dependence 549 const double Ubd = fVoltGapd[i] + fTempOffset; 550 551 // Current overvoltage (at a G-APD with the correct 3900 Ohm resistor) 552 const double Uov = U9-Udrp-Ubd>0 ? U9-Udrp-Ubd : 0; 553 554 // Iout linear with U9 above Ubd 555 // 556 // Rx = (U9-Ubd)/Iout 557 // I' = (U9'-Ubd) / Rx 558 // Udrp' = R*I' 559 // Uov = U9' - Udrp' - Ubd 560 // Uov = overvoltage 561 // 562 // overvoltage = U9' - Udrp' - Ubd 563 // overvoltage = U9' - R*I' - Ubd 564 // overvoltage = U9' - R*((U9'-Ubd)/Rx) - Ubd 565 // overvoltage = U9' - U9'*R/Rx + Ubd*R/Rx - Ubd 566 // overvoltage = U9'*(1 - R/Rx) + Ubd*R/Rx - Ubd 567 // overvoltage - Ubd*R/Rx +Ubd = U9'*(1 - R/Rx) 568 // U9' = [ overvoltage - Ubd*R/Rx +Ubd ] / (1 - R/Rx) 569 // 570 571 // The current through one G-APD is the sum divided by the number of G-APDs 572 // (assuming identical serial resistors) 573 double Iapd = Iout/N; 574 575 // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an 576 // assumption: The differential resistance depends more on the NSB than on the PDE, 577 // thus it is at least comparable for all G-APDs in the patch. In addition, although the 578 // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not 579 // significantly influences the ohmic resistor or the G-APD because the differential 580 // resistor is large enough that the increase of the overvoltage does not dramatically 581 // increase the current flow as compared to the total current flow. 582 if (i==66 || i==191 || i==193) 583 Iapd = Iout/(N+9); // Iapd = R5*Iout/3900; 584 585 // The differential resistance of the G-APD, i.e. the dependence of the 586 // current above the breakdown voltage, is given by 587 //const double Rapd = Uov/Iapd; 588 // This allows us to estimate the current Iov at the overvoltage we want to apply 589 //const double Iov = overvoltage/Rapd; 590 591 // Estimate set point for over-voltage (voltage drop at the target point) 592 //const double Uset = Ubd + overvoltage + R*Iov*N; 593 const double Uset = Uov<0.3 ? Ubd + overvoltage + Udrp : Ubd + overvoltage + Udrp*pow(overvoltage/Uov, 1.66); 594 595 // Voltage set point 596 vec[i] = Uset; 597 598 if (fDimBias.state()==BIAS::State::kVoltageOn && GetCurrentState()==Feedback::State::kInProgress && 599 fabs(Uov-overvoltage)>0.033) 600 cout << setprecision(4) << setw(3) << i << ": Uov=" << Uov << " Udrp=" << Udrp << " Iapd=" << Iapd*1e6 << endl; 601 602 603 // Calculate statistics only for channels with a valid calibration 604 //if (Uov>0) 605 { 606 const int g = hv.group(); 607 608 med[g][num[g]] = Uov; 609 avg[g] += Uov; 610 num[g]++; 611 612 if (Uov<min[g]) 613 min[g] = Uov; 614 if (Uov>max[g]) 615 max[g] = Uov; 616 617 const double iapd = Iapd*1e6; // A --> uA 618 619 data.I[i] = iapd; 620 data.Iavg += iapd; 621 data.Irms += iapd*iapd; 622 623 data.Uov[i] = Uov; 624 625 med[2][num[2]++] = iapd; 626 } 607 const int g = hv.group(); 608 609 med[g][num[g]] = Uov; 610 avg[g] += Uov; 611 num[g]++; 612 613 if (Uov<min[g]) 614 min[g] = Uov; 615 if (Uov>max[g]) 616 max[g] = Uov; 617 618 const double iapd = Iapd*1e6; // A --> uA 619 620 data.I[i] = iapd; 621 data.Iavg += iapd; 622 data.Irms += iapd*iapd; 623 624 data.Uov[i] = Uov; 625 626 med[2][num[2]++] = iapd; 627 627 } 628 628 } … … 638 638 639 639 ostringstream msg; 640 msg << setprecision(4) << "Sending new absolute offset: dU(" << fTemp << "degC)=" << fTempOffset << "V, Unom=" << overvoltage << "V, Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0);640 msg << setprecision(4) << "Sending new absolute offset: dU(" << fTemp << "degC)=" << fTempOffsetAvg << "V+-" << fTempOffsetRms << ", Unom=" << overvoltage << "V, Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0); 641 641 Info(msg); 642 642 } … … 647 647 { 648 648 ostringstream msg; 649 msg << setprecision(4) << "Current status: dU(" << fTemp << "degC)=" << fTempOffset << "V, Unom=" << overvoltage << "V, Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0);649 msg << setprecision(4) << "Current status: dU(" << fTemp << "degC)=" << fTempOffsetAvg << "V+-" << fTempOffsetRms << ", Unom=" << overvoltage << "V, Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0); 650 650 Info(msg); 651 651 } … … 687 687 data.Iavg /= num[2]; 688 688 data.Irms /= num[2]; 689 data.Irms -= data.Iavg*data.Iavg; 689 690 690 691 data.N = num[2]; 691 data.Irms = sqrt(data.Irms-data.Iavg*data.Iavg);692 data.Irms = data.Irms<0 ? 0: sqrt(data.Irms); 692 693 693 694 sort(med[2].data(), med[2].data()+num[2]); 694 695 695 data.Imed = num[2]%2 ? (med[2][num[2]/2-1]+med[2][num[2]/2])/2 : med[2][num[2]/2];696 data.Imed = num[2]%2 ? med[2][num[2]/2] : (med[2][num[2]/2-1]+med[2][num[2]/2])/2; 696 697 697 698 for (int i=0; i<num[2]; i++) … … 768 769 } 769 770 770 int EnableOldAlgorithm(const EventImp &evt)771 {772 if (!CheckEventSize(evt.GetSize(), "EnableOldAlgorithm", 1))773 return kSM_FatalError;774 775 fEnableOldAlgorithm = evt.GetBool();776 777 return GetCurrentState();778 }779 780 771 int SetVerbosity(const EventImp &evt) 781 772 { … … 795 786 fCurrentRequestInterval = evt.GetUShort(); 796 787 797 Out() << "New current request interval: " << fCurrentRequestInterval << "ms" << endl;788 Info("New current request interval: "+to_string(fCurrentRequestInterval)+"ms"); 798 789 799 790 return GetCurrentState(); … … 901 892 public: 902 893 StateMachineFeedback(ostream &out=cout) : StateMachineDim(out, "FEEDBACK"), 903 fIsVerbose(false), fEnableOldAlgorithm(true),894 fIsVerbose(false), 904 895 //--- 905 896 fDimFSC("FSC_CONTROL"), … … 953 944 Subscribe("BIAS_CONTROL/NOMINAL") 954 945 (bind(&StateMachineFeedback::HandleBiasNom, this, placeholders::_1)); 955 Subscribe("FSC_CONTROL/ TEMPERATURE")946 Subscribe("FSC_CONTROL/BIAS_TEMP") 956 947 (bind(&StateMachineFeedback::HandleCameraTemp, this, placeholders::_1)); 957 948 … … 998 989 999 990 1000 AddEvent("ENABLE_OLD_ALRGORITHM", "B:1", Feedback::State::kConnected, Feedback::State::kCalibrated)1001 (bind(&StateMachineFeedback::EnableOldAlgorithm, this, placeholders::_1));1002 1003 1004 991 AddEvent("PRINT") 1005 992 (bind(&StateMachineFeedback::Print, this)) … … 1029 1016 fNumCalibIgnore = conf.Get<uint16_t>("num-calib-ignore"); 1030 1017 fNumCalibRequests = conf.Get<uint16_t>("num-calib-average"); 1018 fTempCoefficient = conf.Get<double>("temp-coefficient"); 1031 1019 1032 1020 return -1; … … 1053 1041 ("num-calib-ignore", var<uint16_t>(30), "Number of current requests to be ignored before averaging") 1054 1042 ("num-calib-average", var<uint16_t>(300), "Number of current requests to be averaged") 1043 ("temp-coefficient", var<double>()->required(), "Temp. coefficient [V/K]") 1055 1044 ; 1056 1045
Note:
See TracChangeset
for help on using the changeset viewer.