classdef OptPowerMeter8153A < handle % Code for HEWLETT-PACKARD 8153A Optical Power Meter (2-channel). % https://www.artisantg.com/info/Agilent_8153A_Manual.pdf?srsltid=AfmBOoqTe38sbGRNHUFXjw5uO6Br7I7aSfgAdRpx-hVvM4sTIhFYyD5x % PAGE 166++ % Typical usage: % pm = HPPowerMeter8153A( ... % 'active', [false true], ... % 'wavelength_nm', [1550 1310] ); % % pm.setWavelength([1550 1310]); % only CH2 is modified % p = pm.readPower(); % reads only active channels properties (Access = public) active logical = [true true] % channel enable wavelength_nm double = [1550 1550] % per-channel wavelength [nm] power_dBm double = [NaN NaN] % last read power offset_dB double = [0 0] % per-channel power offset [dB] avgTime_s double = [0.2 0.2]; end properties (Constant) avgTime_min_s = 0.02 % 20 ms avgTime_max_s = 3600 % 1 hour end properties (Access = protected) visaAddress string = "GPIB1::22::INSTR" numChannels double = 2 end methods function obj = OptPowerMeter8153A(options) arguments options.visaAddress string = "GPIB1::22::INSTR" options.active logical = [true true] options.wavelength_nm double = [1550 1550] end fn = fieldnames(options); for k = 1:numel(fn) obj.(fn{k}) = options.(fn{k}); end assert(numel(obj.active)==obj.numChannels) assert(numel(obj.wavelength_nm)==obj.numChannels) v = obj.connect(); writeline(v,"*IDN?"); disp(readline(v)); pause(0.1); delete(v); pause(0.1); obj.setWavelength(obj.wavelength_nm); end function setWavelength(obj, lambda_nm) if nargin > 1 obj.wavelength_nm = lambda_nm; end v = obj.connect(); for ch = 1:obj.numChannels if obj.active(ch) writeline(v, ... sprintf("SENS%d:POW:WAVE %gNM", ch, obj.wavelength_nm(ch))); end end pause(0.1); delete(v); pause(0.1); end function p = readPower(obj) v = obj.connect(); for ch = 1:obj.numChannels if obj.active(ch) writeline(v, sprintf("READ%d:POW?", ch)); obj.power_dBm(ch) = str2double(readline(v)); else obj.power_dBm(ch) = NaN; end end delete(v); p = obj.power_dBm; end function setOffsetCorrection(obj, offset_dB) obj.offset_dB = offset_dB; v = obj.connect(); for ch = 1:obj.numChannels if obj.active(ch) writeline(v, ... sprintf("SENS%d:CORR:LOSS:INP:MAGN %gDB", ch, obj.offset_dB(ch))); end end delete(v); end function offset_dB = getOffsetCorrection(obj) v = obj.connect(); offset_dB = NaN(1,obj.numChannels); for ch = 1:obj.numChannels if obj.active(ch) writeline(v, sprintf("SENS%d:CORR:LOSS:INP:MAGN?", ch)); offset_dB(ch) = str2double(readline(v)); end end delete(v); obj.offset_dB = offset_dB; end function setAvgTime(obj, avgTime_s) if any(avgTime_s < obj.avgTime_min_s) || any(avgTime_s > obj.avgTime_max_s) oldv = avgTime_s; avgTime_s = max(avgTime_s, obj.avgTime_min_s); avgTime_s = min(avgTime_s, obj.avgTime_max_s); fprintf('[HPPowerMeter8153A] Averaging time clipped:\n'); for ch = 1:obj.numChannels if oldv(ch) ~= avgTime_s(ch) fprintf(' CH%d: %.3g s → %.3g s (allowed %.3g … %.3g s)\n', ... ch, oldv(ch), avgTime_s(ch), ... obj.avgTime_min_s, obj.avgTime_max_s); end end end obj.avgTime_s = avgTime_s; v = obj.connect(); for ch = 1:obj.numChannels if obj.active(ch) && ~isnan(obj.avgTime_s(ch)) writeline(v, ... sprintf("SENS%d:POW:ATIME %g", ch, obj.avgTime_s(ch))); end end delete(v); end function avgTime_s = getAvgTime(obj) v = obj.connect(); avgTime_s = NaN(1,obj.numChannels); for ch = 1:obj.numChannels if obj.active(ch) writeline(v, sprintf("SENS%d:POW:ATIME?", ch)); avgTime_s(ch) = str2double(readline(v)); end end delete(v); obj.avgTime_s = avgTime_s; end end methods (Access = protected) function v = connect(obj) v = visadev(obj.visaAddress); end end end