Changeset 13453
- Timestamp:
- 04/26/12 10:51:16 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/feedback.cc
r13255 r13453 90 90 91 91 DimStampedInfo fBiasData; 92 DimStampedInfo fBiasNom; 92 93 DimStampedInfo fCameraTemp; 93 94 … … 100 101 101 102 vector<float> fCalibration; 103 vector<float> fVoltGapd; 102 104 103 105 vector<vector<float>> fData; … … 122 124 123 125 double fBiasOffset; 126 double fCalibrationOffset; 127 double fAppliedOffset; 124 128 125 129 uint16_t fCurrentRequestInterval; … … 160 164 return; 161 165 162 avgt /= numt; 163 164 165 const float diff = (avgt-25)*4./70 + fBiasOffset; 166 avgt /= numt; // [deg C] 167 168 const double dUt = (avgt-25)*4./70; // [V] 169 170 if (GetCurrentState()==kStateCalibrating && fBiasOffset>dUt-1.2) 171 { 172 ostringstream msg; 173 msg << " (applied calibration offset " << fBiasOffset << "V exceeds temperature correction " << avgt << "V - 1.2V."; 174 Warn("Trying to calibrate above G-APD breakdown volatge!"); 175 Warn(msg); 176 return; 177 } 178 179 // FIXME: If calibrating do not wait for the temperature! 180 fAppliedOffset = fBiasOffset; 181 if (GetCurrentState()!=kStateCalibrating) 182 fAppliedOffset += dUt; 166 183 167 184 vector<float> vec(2*BIAS::kNumChannels); 168 185 for (int i=0; i<BIAS::kNumChannels; i++) 169 vec[i+BIAS::kNumChannels] = diff;186 vec[i+BIAS::kNumChannels] = fAppliedOffset; 170 187 171 188 double avg[2] = { 0, 0 }; … … 186 203 } 187 204 188 // Pixel 583: 5 31 == 191 (5)189 // Pixel 830: 2 2 == 66 (4)190 // Pixel 1401: 6 1 == 193 (5)191 192 205 // Convert from DAC counts to uA 193 206 const double conv = 5000e-6/4096; … … 195 208 // 3900 Ohm/n + 1000 Ohm + 1100 Ohm (with n=4 or n=5) 196 209 const double R[2] = { 3075, 2870 }; 210 211 const float *Iavg = fCalibration.data(); // Offset at U=fCalibrationOffset 212 const float *Ravg = fCalibration.data()+BIAS::kNumChannels*2; // Measured resistance 213 214 // U0 = fCalibrationOffset 215 // dT = fAppliedVoltage 216 217 // Ifeedback = Im[i] - (U[i]-U0)/Ravg[i] - Iavg[i]; 218 // dUapplied[i] + dUneu[i] = R[g] * (Im[i] - (dUapplied[i]+dUneu[i]-U0+dT)/Ravg[i] - Iavg[i]) 219 220 // The assumption here is that the offset calculated from the temperature 221 // does not significanly change within a single step 222 223 // dU[i] := dUtotal[i] = dUapplied[i] + dUneu[i] 224 // dU[i] / R[g] = Im[i] - (dU[i]+dT-U0)/Ravg[i] - Iavg[i] 225 // dU[i]/R[g] + dU[i]/Ravg[i] = Im[i] + U0/Ravg[i] - dT/Ravg[i] - Iavg[i] 226 // dU[i]*(1/R[g]+1/Ravg[i]) = Im[i] - Iavg[i] + U0/Ravg[i] - dT/Ravg[i] 227 // dU[i] = (Im[i] - Iavg[i] + U0/Ravg[i] - dT/Ravg[i]) / (1/R[g]+1/Ravg[i]) 228 // dU[i] = { Im[i] - Iavg[i] + (U0-dT)/Ravg[i] } * r with r := 1 / (1/R[g]+1/Ravg[i]) 229 230 const double U0 = fCalibrationOffset-fAppliedOffset; 197 231 198 232 for (int i=0; i<BIAS::kNumChannels; i++) … … 202 236 continue; 203 237 238 // Average measured current 239 const double Im = double(fCurrentsAvg[i])/fCursorCur; // [dac] 240 241 // Group index (0 or 1) of the of the pixel (4 or 5 pixel patch) 204 242 const int g = hv.group(); 205 243 206 const double Im = double(fCurrentsAvg[i])/fCursorCur; 207 const double I = Im>fCalibration[i] ? Im-fCalibration[i] : 0; 208 209 double U = R[g] * I*conv; 210 211 // 510 / 390 1.30 ^1.66 = 1.55 212 // 470 / 380 1.23 = 1.41 213 // 450 / 360 1.25 = 1.45 214 215 // This is assuming that the broken pixels 216 // have a 1kOhm instead of 390 Ohm serial resistor 217 if (i==66) 218 U *= 2400./R[0]; // (1k)2665 / (390)2400 / (~0)2100 219 if (i==191) 220 U *= 2320./R[1]; // (1k)2794 / (390)2320 / (~0)2100 221 if (i==193) 222 U *= 2320./R[1]; // (1k)2665 / (390)2400 / (~0)2100 223 224 vec[i+BIAS::kNumChannels] += U; 225 226 if (fCalibration[i]>0) 244 // Serial resistors in front of the G-APD 245 double Rg = R[g]; 246 247 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor 248 if (i==66) // Pixel 830(66) 249 Rg = 2400; // 2400 = (3/3900 + 1/390) + 1000 + 1100 250 if (i==191 || i==193) // Pixel 583(191) / Pixel 1401(193) 251 Rg = 2379; // 2379 = (4/3900 + 1/390) + 1000 + 1100 252 253 const double r = 1./(1./Rg + 1./Ravg[i]); // [Ohm] 254 255 // Offset induced by the voltage above the calibration point 256 const double dI = U0/Ravg[i]; // [V/Ohm] 257 258 // Offset at the calibration point (make sure that the calibration is 259 // valid (Im[i]>Iavg[i]) and we operate above the calibration point) 260 const double I = Im>Iavg[i] ? (Im - Iavg[i])*conv : 0; // [A] 261 262 // Make sure that the averaged resistor is valid 263 const double dU = Ravg[i]>0 ? r*(I+dI) : 0; 264 265 vec[i+BIAS::kNumChannels] += dU; 266 267 // Calculate statistics only for channels with a valid calibration 268 if (Iavg[i]>0) 227 269 { 228 med[g][num[g]] = U;229 avg[g] += U;270 med[g][num[g]] = dU; 271 avg[g] += dU; 230 272 num[g]++; 231 273 232 if ( U<min[g])233 min[g] = U;234 if ( U>max[g])235 max[g] = U;274 if (dU<min[g]) 275 min[g] = dU; 276 if (dU>max[g]) 277 max[g] = dU; 236 278 } 237 279 } … … 258 300 259 301 ostringstream msg; 260 msg << setprecision(4) << "Sending new absolute offset (" << diff<< "V+" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << "V) to biasctrl.";302 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."; 261 303 Info(msg); 262 304 … … 325 367 return; 326 368 327 fCalibration.resize(BIAS::kNumChannels*2); 369 fCalibration.resize(BIAS::kNumChannels*3); 370 371 float *avg = fCalibration.data(); 372 float *rms = fCalibration.data()+BIAS::kNumChannels; 373 float *res = fCalibration.data()+BIAS::kNumChannels*2; 374 328 375 for (int i=0; i<BIAS::kNumChannels; i++) 329 376 { 330 fCalibration[i] = double(fCurrentsAvg[i])/fCursorCur; 331 fCalibration[i+BIAS::kNumChannels] = sqrt(double(fCurrentsRms[i])/fCursorCur-fCalibration[i]*fCalibration[i]); 377 const double I = double(fCurrentsAvg[i])/fCursorCur; 378 379 res[i] = fVoltGapd[i]/I * 4096/5000e-6; 380 avg[i] = I; 381 rms[i] = sqrt(double(fCurrentsRms[i])/fCursorCur-I*I); 332 382 } 333 383 … … 720 770 } 721 771 772 if (curr==&fBiasNom) 773 { 774 const float *ptr = reinterpret_cast<float*>(fBiasNom.getData()); 775 fVoltGapd.assign(ptr, ptr+416); 776 return; 777 } 778 722 779 if (curr==&fCameraTemp && (fControlType==kTemp || fControlType==kCurrents)) 723 780 HandleCameraTemp(); … … 781 838 } 782 839 840 const float *avg = fCalibration.data(); 841 const float *rms = fCalibration.data()+BIAS::kNumChannels; 842 const float *res = fCalibration.data()+BIAS::kNumChannels*2; 843 844 Out() << "Average current at " << fCalibrationOffset << "V below G-APD operation voltage:\n"; 845 783 846 for (int k=0; k<13; k++) 784 847 for (int j=0; j<8; j++) … … 786 849 Out() << setw(2) << k << "|" << setw(2) << j*4 << "|"; 787 850 for (int i=0; i<4; i++) 788 Out() << Tools::Form(" %6.1f+-%4.1f", fCalibration[k*32+j*4+i], fCalibration[k*32+j*4+i+BIAS::kNumChannels]);789 Out() << endl;851 Out() << Tools::Form(" %6.1f+-%4.1f", avg[k*32+j*4+i], rms[k*32+j*4+i]); 852 Out() << '\n'; 790 853 } 854 Out() << '\n'; 855 856 Out() << "Measured calibration resistor:\n"; 857 for (int k=0; k<13; k++) 858 for (int j=0; j<4; j++) 859 { 860 Out() << setw(2) << k << "|" << setw(2) << j*8 << "|"; 861 for (int i=0; i<8; i++) 862 Out() << Tools::Form(" %5.0f", res[k*32+j*8+i]); 863 Out() << '\n'; 864 } 865 866 Out() << flush; 791 867 792 868 return GetCurrentState(); … … 982 1058 } 983 1059 1060 if (fVoltGapd.size()==0) 1061 { 1062 Error("No G-APD reference voltages received yet (BIAS_CONTROL/NOMINAL)."); 1063 return GetCurrentState(); 1064 } 1065 984 1066 ostringstream out; 985 1067 out << "Starting temperature feedback for calibration with an offset of -2V"; 986 1068 Message(out); 987 1069 988 fBiasOffset = -2;1070 fBiasOffset = fCalibrationOffset; 989 1071 fControlType = kTemp; 990 1072 fCursorCur = -fNumCalibIgnore; … … 1134 1216 "|DeltaAmpl[mV]:Amplitude offset measures" 1135 1217 "|DeltaBias[mV]:Correction value calculated"), 1136 fDimCalibration("FEEDBACK/CALIBRATION", "F:416;F:416 ",1218 fDimCalibration("FEEDBACK/CALIBRATION", "F:416;F:416;F:416", 1137 1219 "Current offsets" 1138 1220 "|Avg[dac]:Average offset (5000uA/4096dac)" 1139 1221 "|Rms[dac]:Rms of offset (5000uA/4096dac)"), 1222 "|R[Ohm]:Measured calibration resistor", 1140 1223 fSP(BIAS::kNumChannels), 1141 1224 fKp(0), fKi(0), fKd(0), fT(-1), 1225 fCalibrationOffset(-3), 1142 1226 fCurrentRequestInterval(0), 1143 1227 fNumCalibIgnore(30), … … 1300 1384 1301 1385 fCurrentRequestInterval = conf.Get<uint16_t>("current-request-interval"); 1302 fNumCalibIgnore = conf.Get<uint16_t>("num-calib-ignore"); 1303 fNumCalibRequests = conf.Get<uint16_t>("num-calib-average"); 1386 fNumCalibIgnore = conf.Get<uint16_t>("num-calib-ignore"); 1387 fNumCalibRequests = conf.Get<uint16_t>("num-calib-average"); 1388 fCalibrationOffset = conf.Get<float>("calibration-offset"); 1304 1389 1305 1390 return -1; … … 1321 1406 po::options_description control("Feedback options"); 1322 1407 control.add_options() 1323 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.")1408 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.") 1324 1409 ("current-request-interval", var<uint16_t>(1000), "Interval between two current requests.") 1325 ("num-calib-ignore", var<uint16_t>(30), "Number of current requests to be ignored before averaging") 1326 ("num-calib-average", var<uint16_t>(300), "Number of current requests to be averaged") 1410 ("num-calib-ignore", var<uint16_t>(30), "Number of current requests to be ignored before averaging") 1411 ("num-calib-average", var<uint16_t>(300), "Number of current requests to be averaged") 1412 ("calibration-offset", var<float>(-3), "Absolute offset relative to the G-APD operation voltage when calibrating") 1327 1413 ; 1328 1414
Note:
See TracChangeset
for help on using the changeset viewer.