export const MODEL_VERSION='1.0.0',EXPERIMENT_ID='course-03/photosensor',DEFAULTS=Object.freeze({irradiance_mw_cm2:.5,feedback_kohm:50,zero_current_ua:0,wavelength_nm:950,reverse_bias_v:5,temperature_c:25,linear_output_limit_v:4.5}); export function validateParameters(p){for(const[k,l,h]of[['irradiance_mw_cm2',0,1],['feedback_kohm',1,200],['zero_current_ua',-.1,.1]])if(!Number.isFinite(p[k])||p[k]h)throw new RangeError(`${k}须在${l}–${h}`);if(p.wavelength_nm!==950||p.reverse_bias_v!==5||p.temperature_c!==25||p.linear_output_limit_v!==4.5)throw new RangeError('BPW34模型固定950nm、5V、25℃与教学线性限4.5V');return{...p};} export function workingPoint(p,light_off=false){validateParameters(p);const irradiance=light_off?0:p.irradiance_mw_cm2,photo_current_ua=50*irradiance,total_current_ua=photo_current_ua+p.zero_current_ua,ideal_output_v=-total_current_ua*p.feedback_kohm*.001,valid=Math.abs(ideal_output_v)<=p.linear_output_limit_v;return{irradiance_mw_cm2:irradiance,photo_current_ua,total_current_ua,ideal_output_v,output_v:valid?ideal_output_v:null,linear_valid:valid,incident_power_uw:irradiance*.075*1000};} export function zeroCalibration(p,source='manual-operation'){const w=workingPoint(p,true);if(!['manual-operation','ideal-model'].includes(source))throw new RangeError('校准身份无效');if(!w.linear_valid)throw new RangeError('零点超出线性范围');return{experiment_id:EXPERIMENT_ID,model_version:MODEL_VERSION,source,kind:'zero',parameters:{...p},raw:{output_v:w.output_v,irradiance_mw_cm2:0},derived:{zero_output_v:w.output_v}};} export function measurement(p,zero,source='manual-operation'){validateParameters(p);if(!zero||zero.kind!=='zero'||zero.source!==source||zero.parameters.feedback_kohm!==p.feedback_kohm||zero.parameters.zero_current_ua!==p.zero_current_ua)throw new RangeError('先在同一反馈电阻、零点与来源下保存暗读数');const w=workingPoint(p);if(!w.linear_valid)throw new RangeError('输出超出线性范围,不能把5V光电流条件作为实际饱和工作点保存');const photo=(zero.raw.output_v-w.output_v)/(p.feedback_kohm*.001);return{experiment_id:EXPERIMENT_ID,model_version:MODEL_VERSION,source,kind:'light',parameters:{...p},raw:{irradiance_mw_cm2:p.irradiance_mw_cm2,output_v:w.output_v,zero_output_v:zero.raw.output_v},derived:{corrected_photo_current_ua:photo,incident_power_uw:w.incident_power_uw,responsivity_a_w:w.incident_power_uw>0?photo/w.incident_power_uw:null}};}