diff --git a/@MyTpg/MyTpg.m b/@MyTpg/MyTpg.m index 060404c..5e2b014 100644 --- a/@MyTpg/MyTpg.m +++ b/@MyTpg/MyTpg.m @@ -1,161 +1,173 @@ % Class for communication with Pfeiffer TPG single and dual pressure gauge % controllers. % Use 'serial' communication objects instead of 'visa' with this instrument % Tested with TPG 262 and 362. classdef MyTpg < MyInstrument & MyCommCont properties (Constant = true, Access = protected) % Named constants for communication ETX = char(3); % end of text CR = char(13); % carriage return \r LF = char(10); %#ok line feed \n ENQ = char(5); % enquiry ACK = char(6); % acknowledge NAK = char(21); % negative acknowledge end properties (SetAccess = protected, GetAccess = public, ... SetObservable = true) % Last measurement status gauge_stat = {'', ''}; end methods (Access = public) function this = MyTpg(varargin) this@MyCommCont(varargin{:}); end % read pressure from a single channel or both channels at a time function p_arr = readPressure(this) queryString(this, ['PRX', this.CR, this.LF]); str = queryString(this, this.ENQ); % Extract pressure and gauge status from reading. arr = sscanf(str,'%i,%e,%i,%e'); p_arr = transpose(arr(2:2:end)); % Status codes: % 0 –> Measurement data okay % 1 –> Underrange % 2 –> Overrange % 3 –> Sensor error % 4 –> Sensor off (IKR, PKR, IMR, PBR) % 5 –> No sensor (output: 5,2.0000E-2 [hPa]) % 6 –> Identification error this.gauge_stat{1} = gaugeStatusFromCode(this, arr(1)); this.gauge_stat{2} = gaugeStatusFromCode(this, arr(3)); end function pu = readPressureUnit(this) queryString(this, ['UNI',this.CR,this.LF]); str = queryString(this, this.ENQ); % Pressure units correspondence table: % 0 –> mbar/bar % 1 –> Torr % 2 –> Pascal % 3 –> Micron % 4 –> hPascal (default) % 5 –> Volt pu_code = sscanf(str,'%i'); pu = pressureUnitFromCode(this, pu_code); end function id_list = readGaugeId(this) queryString(this, ['TID',this.CR,this.LF]); str = queryString(this, this.ENQ); id_list = deblank(strsplit(str,{','})); end function code_list = turnGauge(this) queryString(this, ['SEN',char(1,1),this.CR,this.LF]); str = queryString(this, this.ENQ); code_list = deblank(strsplit(str,{','})); end % Attempt communication and identification of the device function [str, msg] = idn(this) try queryString(['AYT', this.CR, this.LF]); str = queryString(this.ENQ); catch ME str = ''; msg = ME.message; end this.idn_str = toSingleLine(str); end + + % Create pressure logger + function Lg = createLogger(this, varargin) + + Lg = MyLogger('MeasFcn', @this.readPressure, varargin{:}); + + pu = this.pressure_unit; + if isempty(Lg.Record.data_headers) && ~isempty(pu) + this.Lg.Record.data_headers = ... + {['P ch1 (' pu ')'], ['P ch2 (' pu ')']}; + end + end end methods (Access = protected) function createCommandList(this) addCommand(this, 'pressure', ... 'readFcn', @this.readPressure, ... 'default', [0, 0]); addCommand(this, 'pressure_unit', ... 'readFcn', @this.readPressureUnit, ... 'default', 'mBar'); addCommand(this, 'gauge_id', ... 'readFcn', @this.readGaugeId, ... 'default', {'', ''}); end function createMetadata(this) createMetadata@MyInstrument(this); addObjProp(this.Metadata, this, 'gauge_stat', ... 'comment', 'Last measurement status'); end % Convert numerical code for gauge status to a string function str = gaugeStatusFromCode(~, code) switch int8(code) case 0 str = 'Measurement data ok'; case 1 str = 'Underrange'; case 2 str = 'Overrange'; case 3 str = 'Sensor error'; case 4 str = 'Sensor off'; case 5 str = 'No sensor'; case 6 str = 'Identification error'; otherwise str = ''; warning('Unknown gauge status code %i', code); end end % Convert numerical code for pressure unit to a string function str = pressureUnitFromCode(~, code) switch int8(code) case 0 str = 'mBar'; case 1 str = 'Torr'; case 2 str = 'Pa'; case 3 str = 'Micron'; case 4 str = 'hPa'; case 5 str = 'Volt'; otherwise str = ''; warning('unknown pressure unit, code=%i',pu_num) end end end end diff --git a/Utility functions/readRunFiles.m b/Utility functions/readRunFiles.m index debf8e5..5a3b335 100644 --- a/Utility functions/readRunFiles.m +++ b/Utility functions/readRunFiles.m @@ -1,69 +1,73 @@ % Read all the files which names start from 'run' from the local base -% directory and add entries, autometically generated from the -% InstrumentList -function RunFiles = readRunFiles(varargin) - if ~isempty(varargin) && ischar(varargin{1}) - % The directory to search in can be supplied as varargin{1} - dir = varargin{1}; - else - % Otherwise use the local base directory +% directory and add entries, automatically generated from InstrumentList + +function RunFiles = readRunFiles(dir) + if ~exist('dir', 'var') + + % Search in the local base directory if directory name is not + % supplied explicitly dir = getLocalBaseDir(); - end + end + % Find all the names of .m files that start with 'run' all_names = what(dir); is_run = startsWith(all_names.m,'run','IgnoreCase',false); run_names = all_names.m(is_run); RunFiles = struct(); % Read headers of all the run*.m files for i=1:length(run_names) name_match = regexp(run_names{i},'run(.*)\.m','tokens'); nm = name_match{1}{1}; fname = fullfile(dir, run_names{i}); + % Read the run file comment header RunFiles.(nm) = readCommentHeader(fname); if isfield(RunFiles.(nm),'show_in_daq') RunFiles.(nm).show_in_daq = eval(... lower(RunFiles.(nm).show_in_daq)); end + % Add information about file name RunFiles.(nm).name = nm; + % Expression that needs to be evaluated to run the program. In this % case full name of the file RunFiles.(nm).fullname = fname; [~, run_name, ~] = fileparts(fname); RunFiles.(nm).run_expr = run_name; end % Add entries, automatically generated from the InstrumentList InstrumentList = getLocalSettings('InstrumentList'); instr_names = fieldnames(InstrumentList); for i=1:length(instr_names) nm = instr_names{i}; + % If run file for instrument was not specified explicitly and if % all the required fields in InstrList are filled, add an entry to % RunFiles try add_entry = ~isfield(RunFiles, nm) &&... ~isempty(InstrumentList.(nm).control_class); catch end if add_entry RunFiles.(nm) = InstrumentList.(nm); % Command for running an instrument without gui RunFiles.(nm).run_bg_expr = ... sprintf('runInstrument(''%s'');',nm); % Command for running an instrument with gui, added only if gui % is specified if ~isempty(InstrumentList.(nm).gui) RunFiles.(nm).run_expr = ... sprintf('runInstrumentWithGui(''%s'');',nm); end RunFiles.(nm).header = ['% This entry is automatically ',... 'generated from InstrumentList']; end end end