0001 %TSL230_fO_to_irradiance - Converts the frequency output of the TSL230, TSL230R,
0002 %                          or TSL230RD to irradiance when given the light
0003 %                          source's spectrum.
0004 %
0005 % Syntax:  [Ee, E] = TSL230_fO_to_irradiance(lambda, X, fO, sensitivity, sensor_type, dist_type)
0006 %
0007 % Inputs:
0008 %    lambda - the spectrum's wavelength scale.
0009 %         X - the light sources spectrum. [W/(m^2)/nm] or [photon/(s*m^2)/nm]
0010 %        fO - the output of the TSL230*, TSL230*R or TSL230*RD. (small eff, big OH)
0011 %    sensitivity - the sensitivity setting of the sensor
0012 %    sensor_type - TSL230, TSL230R, or TSL230RD. default: TSL230R
0013 %    dist_type - power or quantal. if dist_type is power, then X must have units
0014 %                of [W/(m^2)/nm] and Ee will have the same units. if dist_type
0015 %                is quantal, then X must have units of [photon/(s*m^2)/nm] and
0016 %                Ee likewise. default: power
0017 %
0018 % Outputs:
0019 %    Ee - the light source's spectral irradiance (power or quantal).
0020 %     E - the light source's irradiance (power or quantal).
0021 %
0022 % Example:
0023 %    load('TSL230R_actinic.mat')
0024 %    fO = mean(fO_light) - mean(fO_dark);
0025 %    mu = 415;
0026 %    FWHM = 30;
0027 %    Xactinic = 75*exp(-2.7726*((so.lambda-mu)/FWHM).^2); % model spectrogram
0028 %    Ee_meter = fO_to_irradiance(so.lambda, Xactinic, fO, sensitivity, 'TSL230R', 'power');
0029 %
0030 %    load('TSL230R_actinic.mat')
0031 %    fO = mean(fO_light) - mean(fO_dark);
0032 %    load('actinic_spectrograph.mat'); % loads spctgrph
0033 %    Xactinic = image2spectrum(spctgrph); % spectrogram created from a picture
0034 %    Ee_meter = fO_to_irradiance(so.lambda, Xactinic, fO, sensitivity, 'TSL230R', 'power');
0035 %
0036 %
0037 % Other m-files required: none
0038 % Subfunctions: none
0039 % MAT-files required: none
0040 %
0041 % See also: NONE
0042 %
0043 % Author: Jonathan Thomson
0044 % Work:
0045 % email:
0046 % Website: http://jethomson.wordpress.com
0047 %
0048 
0049 %NOTES:
0050 % To determine a light source's irradiance and spectral irradiance this
0051 % m-file uses the shape of the light source's spectrum, the frequency
0052 % output from a sensor in the TSL230* family, TSL230*R family, TSL230*RD
0053 % family (i.e. TSL230RD, TSL230ARD, or TSL230BRD), and the sensor's
0054 % spectral responsivity.
0055 %
0056 % The following technical explanation describes how the TSL230R works. The
0057 % TSL230RD behaves the same way except Re(640 nm) = 79 [kHz/(W/m^2)],
0058 % instead of 77, when sensitivity is 100x and frequency scaler is 1x
0059 % (i.e. 0.79 [kHz/(uW/cm^2)] as given in the datasheet). The TSL230 also
0060 % behaves in a similar manner but has a different responsivity curve.
0061 %
0062 % Assuming the lamp's spotlight fills an area greater than the photodiode's
0063 % aperture then the radiant spectral power (or power spectral density) entering
0064 % the photodiode is the light's spectral irradiance [W/(m^2)/nm] multiplied
0065 % by the area of the aperture [m^2].
0066 % [m^2]*[W/(m^2)/nm] = [W/nm]
0067 %
0068 % Once a photon has entered the photodiode it has a wavelength dependent
0069 % probability of creating a electron/hole pair that produces a differential
0070 % current. This conversion from spectral radiant power to current is
0071 % represented by the photodiode's spectral responsivity [A/W]. All of the
0072 % differential currents naturally integrate to form the photodiode's total
0073 % photocurrent because they enter the same conductor.
0074 % integral{[A/W]*[W/nm]*[nm]} = [A]
0075 %
0076 % Finally the current-to-frequency converter transforms the current to the
0077 % output frequency and scales it by the programmed frequency scaler.
0078 % [kHz/A]*[A] = [kHz]
0079 %
0080 % The total transformation from spectral irradiance to frequency is represented
0081 % by: [kHz] = [kHz/A]*integral{[A/W]*[m^2]*[W/(m^2)/nm]*[nm]}
0082 %
0083 % The datasheet only gives the normalized spectral responsivity (as a plot) and
0084 % the system's responsivity at 640 nm, Re(640 nm) = 77 [kHz/(W/m^2)]
0085 % (when sensitivity is 100x and frequency scaler is 1x). The mat file
0086 % TSL230R_Re_s1.mat is the spectral responsivity of the TSL230R for a
0087 % sensitivity of 1. It was created by converting the datasheet's graph of the
0088 % normalized spectral responsivity into a point-series and multiplying it by
0089 % the system's responsivity at 640 nm with a frequency scaler of 1 and a
0090 % sensitivity of 1, which is 0.77 [kHz/(W/(m^2))].
0091 %
0092 % If the spectral irradiance incident on the TSL230R's photodiode is represented
0093 % by Ee(lambda) then fO = integral{Re(lambda)*Ee(lambda) dlambda} from 0 to inf.
0094 % However, Ee(lambda) is unknown so we must use X(lambda) which has the same
0095 % shape as Ee(lambda) but is off by an unknown multiplicative constant k
0096 % because it is an uncalibrated spectrum (i.e. Ee(lambda) = k*X(lambda)).
0097 % We can then use our mathematical model of the TSL230R to find the frequency
0098 % output that would result if a light source with a spectrum X(lambda) was
0099 % incident on the sensor: fX = integral{Re(lambda)*X(lambda) dlambda}
0100 %
0101 % Since fO is known, fX can be calculated, and the TSL230R is a linear system,
0102 % then k can be found simply: k = fO/fX
0103 % Therefore we have obtained the desired result Ee = k*X.
0104 % The accuracy of your result depends on the accuracy of the TSL230R as well
0105 % as how well your model X(lambda) matches the shape of Ee(lambda).
0106 %
0107 %
0108 % Extra Info
0109 % The detector area changes when the sensitivity is changed. The frequency
0110 % scale of fO vs. Ee changes when the frequency scaling is changed.
0111 %
0112 % Full scale frequency equals (1.1 MHz)/fscale
0113 %
0114 % lambda must be in nm and between 250 nm and 1200 nm inclusive.
0115 %
0116 
0117 function [Ee, E] = TSL230_fO_to_irradiance(lambda, X, fO, sensitivity, sensor_type, dist_type)
0118 
0119     s = filesep;
0120 
0121     if (~exist('sensor_type','var') || isempty(sensor_type))
0122         sensor_type = 'TSL230R';
0123     end
0124 
0125     if (~exist('dist_type','var') || isempty(dist_type))
0126         dist_type = 'power';
0127     end
0128 
0129     if ~strcmpi(sensor_type, 'TSL230') && ~strcmpi(sensor_type, 'TSL230R') && ~strcmpi(sensor_type, 'TSL230RD')
0130         error('TSL230_fO_to_irradiance: unsupported sensor type.');
0131     end
0132 
0133     % load lambda [nm] and
0134     % system responsivity at 1x sensitivity, Re_s1
0135     if strcmpi(sensor_type, 'TSL230')
0136         load(['data' s 'essential_data_sets' s 'TSL230_Re_s1.mat'])
0137     else
0138         % Re(640 nm) = sensitivity*0.77 [kHz/(W/m^2)]
0139         load(['data' s 'essential_data_sets' s 'TSL230R_Re_s1.mat'])
0140         if strcmpi(sensor_type, 'TSL230RD')
0141             % Re(640 nm) = sensitivity*0.79 [kHz/(W/m^2)]
0142             Re_s1 = (0.79/0.77)*Re_s1;
0143         end
0144     end
0145 
0146     if strcmpi(dist_type, 'quantal')
0147         h = 6.62606896*10^-34; % Planck constant, [J*s]
0148         c = 299792458; % speed of light, [m/s]
0149         Wp = h*c./(lambda_Re*10^-9); % [J/photon]
0150         Re_s1 = Wp.*Re_s1;
0151     end
0152 
0153     Re = sensitivity*Re_s1;
0154 
0155     % interpolate so we can use lambda [nm] instead of lambda_Re
0156     Rei = interp1(lambda_Re, Re, lambda, 'spline', 0);
0157 
0158     % fX is the frequency that would be output if the model lamp shined
0159     % light with a spectral irradiance X on the photodiode.
0160     dl = mean(diff(lambda)); % [nm]
0161     fX = trapz(Rei.*X).*dl; % [kHz]
0162 
0163     k = fO./fX; % scaling factor, [dimensionless]
0164 
0165     Ee = k.*X; % spectral irradiance of lamp, [W/(m^2)/nm] or [photon/(s*m^2)/nm]
0166     E = trapz(Ee).*dl; % irradiance of lamp, [W/(m^2)] or [photon/(s*m^2)]
0167 
0168 end
0169