diff --git a/Manuals/GPIB-protocol/ab48_11.pdf b/Manuals/GPIB-protocol/ab48_11.pdf new file mode 100644 index 0000000..e1a4d16 Binary files /dev/null and b/Manuals/GPIB-protocol/ab48_11.pdf differ diff --git a/OOequipment/Experiment6.zip b/OOequipment/Experiment6.zip new file mode 100644 index 0000000..aea1b1e Binary files /dev/null and b/OOequipment/Experiment6.zip differ diff --git a/OOequipment/FourierHarmonics.mlx b/OOequipment/FourierHarmonics.mlx index 6421023..9ece8f5 100644 Binary files a/OOequipment/FourierHarmonics.mlx and b/OOequipment/FourierHarmonics.mlx differ diff --git a/OOequipment/RC_TransferFunction_solution.mlx b/OOequipment/RC_TransferFunction_solution.mlx index 8c32111..f648e3d 100644 Binary files a/OOequipment/RC_TransferFunction_solution.mlx and b/OOequipment/RC_TransferFunction_solution.mlx differ diff --git a/OOequipment/debug/RC_TransferFunction_sub.m b/OOequipment/debug/RC_TransferFunction_sub.m new file mode 100644 index 0000000..adcde04 --- /dev/null +++ b/OOequipment/debug/RC_TransferFunction_sub.m @@ -0,0 +1,39 @@ +%% Transfer function of a RC-network +% This script will run automated measurements for you. Note that all frequencies +% are given in Hertz. +%% Component Values +% Fill in the measured values in the following code box. +%% +R = 3.2942e3; %Ohm +C = 315.82e-9;%Farad +%% +% Give the desired begin and end frequency as well as number of steps: + +f_start = 10; %Hz +f_stop = 1e3; %Hz +%% +% Do not edit the following code box. + +f = 10.^linspace(log10(f_start),log10(f_stop),500); +%% Theoratical Curves +% Give the equations for the magnitude: +%% +A = -10*log10(1+(2*pi*f*R*C).^2); +%% +% For the phase: + +P = -atan(2*pi*f*R*C); +%% +% For the cut-off frequency: + +Fc = 1/(2*pi*R*C); +%% +% And both asymptotes where $f >> f_c$ and $f << f_c$: + +S_smaller = 0*f; %smaller than cut-off frequency +S_larger = -20*log10(2*pi*f*R*C); %larger than cut-off frequency +%% Running the Measurement +%% +n_steps = 5; +amplitude = 10; +RC_TransferFunction_script; \ No newline at end of file diff --git a/OOequipment/debug/errorlist.mat b/OOequipment/debug/errorlist.mat new file mode 100644 index 0000000..6f5261e Binary files /dev/null and b/OOequipment/debug/errorlist.mat differ diff --git a/OOequipment/debug/test.m b/OOequipment/debug/test.m new file mode 100644 index 0000000..4e053b8 --- /dev/null +++ b/OOequipment/debug/test.m @@ -0,0 +1,57 @@ +for i = 1:5e6:15e6 + fg.write_unsafe(['apply:sin ', num2str(i)]) + fg.opc + fg.write_unsafe('func:shape ramp') + fg.opc +end +fg.error + +%% +% plot y=11*exp(-|x/6|)*sin(x) from x= -12.5 to x=9.4 +x = linspace(-10*pi,10*pi,8000); +y = 11.*exp(-abs(x./6)).*sin(x); +plot(x,y,x+20*pi,y) + +%% +tic +fg.frequency = 2000; +fg.waveform = 'sinus'; +fg.unit = 'Vrms'; +fg.frequency = 1e6; +toc + +%% + + + +a=-10*log(1+(2*pi*f*r*c)^2); +s=step(2*pi*f-1/(r*c))*(-20*log(2*pi*f*r*c)); +p=-atan(2*pi*f*r*c); + +%% +f1=100; +phase_diff1 = 0.5; +tp=((1:1000)./1000); +tp2=tp-((phase_diff1*1000/(f1*360))./1000); +% normalizing - 360 is 1 complete phase shift + +x=0.8*exp(2*pi*i*signal_freq*tp)+0.4*exp(2*pi*i*20*tp); +y=0.8*exp(2*pi*i*signal_freq*tp2)+0.4*exp(2*pi*i*20*tp); +%% +Fs = (wave1.stop-wave1.start)/wave1.length; +p1=(fft(real(wave1.waveform),1024)); +p2=(fft(real(wave2.waveform),1024)); + +phase_diff=(angle(p1(f1)))-(angle(p2(f1))); + + +%% +tic + +[data,raw] = transferFunction(sc,fg,500,5000,50,10); +figure; +subplot(2,1,1) +semilogx(data.frequency,data.magnitude) +subplot(2,1,2) +semilogx(data.frequency,data.phase); +toc \ No newline at end of file diff --git a/OOequipment/subfiles/Channel.m b/OOequipment/subfiles/Channel.m deleted file mode 100644 index 9cd7a32..0000000 --- a/OOequipment/subfiles/Channel.m +++ /dev/null @@ -1,170 +0,0 @@ -classdef Channel - %CHANNEL Summary of this class goes here - % Detailed explanation goes here - - properties (Hidden, Access = private) - scope - channelnumber - end - properties (Dependent) - state - coupling - bandwidth - scale - offset - probe - label - type - probeunit - end - - methods - function ch = Channel(scope,channelnumber) - ch.channelnumber = channelnumber; - ch.scope = scope; - end - - function s = get.state(ch) - s = ch.CHAN('state?'); - end - - function out = get.coupling(ch) - out = ch.CHAN('coup?'); - end - - function out = get.bandwidth(ch) - out = ch.CHAN('band?'); - end - - function out = get.offset(ch) - out = ch.CHAN('offs?'); - end - - function out = get.scale(ch) - out = ch.CHAN('scal?'); - end - - function out = get.label(ch) - out = ch.CHAN('lab?'); - end - - function out = get.type(ch) - out = ch.CHAN('type?'); - end - - function out = get.probeunit(ch) - out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT?']); - end - - function out = get.probe(ch) - out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN?']); - end - - function ch = set.state(ch,in) - ch.CHAN('state',in); - end - - function ch = set.coupling(ch,in) - ch.CHAN('coup',in); - end - - function ch = set.bandwidth(ch,in) - ch.CHAN('band',in); - end - - function ch = set.offset(ch,in) - ch.CHAN('offs',in); - end - - function ch = set.scale(ch,in) - ch.CHAN('scal',in); - end - - function ch = set.label(ch,in) - ch.CHAN('lab',in); - end - - function ch = set.type(ch,in) - ch.CHAN('type',in); - end - - function out = frequency(ch) - out = str2double(ch.MEAS('freq')); - end - - function out = peak2peak(ch) - out = str2double(ch.MEAS('peak')); - end - - function out = period(ch) - out = str2double(ch.MEAS('per')); - end - - function out = amplitude(ch) - out = str2double(ch.MEAS('ampl')); - end - - function out = mean(ch) - out = str2double(ch.MEAS('mean')); - end - - function out = rms(ch) - out = str2double(ch.MEAS('rms')); - end - - function out = phase(ch) - out = str2double(ch.MEAS('phas')); - end - - function ch = set.probeunit(ch,unit) - ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT ', unit]); - end - - function ch = set.probe(ch,man) - ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN ', man]); - end - - function data = waveform(ch,window) - ch.scope.single; - if nargin < 2 - window = 'DEF'; - end - ch.scope.setWaveformSettings(window,'REAL') - data = ch.getWaveform; - end - - function data = getWaveform(ch) - header = str2num(ch.CHAN('DATA:HEAD?')); - data.length = header(3); - data.start = header(1); - data.stop = header(2); - data.sampletime = str2double(ch.CHAN('DATA:XINC?')); - ch.scope.opc; - ch.scope.write_unsafe(['CHAN',num2str(ch.channelnumber),':DATA?']); - data.data = ch.scope.readWaveform(data.length); - end - - end - - methods (Hidden, Access = private) - function c = CHAN(ch,string,in) - if nargin == 2 - if strcmp(string(end),'?') - c = ch.scope.query(['CHAN',num2str(ch.channelnumber),':',string]); - else - ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string]); - end - else - ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string,' ',in]); - end - end - - function c = MEAS(ch,string) - c = ch.scope.query(['MEAS',num2str(ch.channelnumber),':RES:ACT?',string]); - end - -% function c = CHANsend(ch,string,in) -% c = ['CHAN',num2str(ch.channelnumber),':',string,' ',in]; -% end - end -end \ No newline at end of file diff --git a/OOequipment/subfiles/ChannelClass.m b/OOequipment/subfiles/ChannelClass.m new file mode 100644 index 0000000..126911f --- /dev/null +++ b/OOequipment/subfiles/ChannelClass.m @@ -0,0 +1,267 @@ +classdef ChannelClass +% CHANNEL is the class for one channel of the oscilloscope. Multiple +% settings for the different channels of the oscilloscope can be changed +% via this class definition + + properties (Hidden, Access = private) + scope % Contains the class of the scope that is parent of this channel. + channelnumber % is the number of the channel on the scope. + end + properties (Dependent) + state %is channel enabled or not + coupling %DC or AC + bandwidth %inputfilter bandwidth + scale %Voltage scale in volt/div + offset %DC offset + probe %probesetting + label %name for channel on scope + type %set decimation mode + probeunit %Define current or voltage probe + end + + methods + %Constructor of class + function ch = Channel(scope,channelnumber) + ch.channelnumber = channelnumber; + ch.scope = scope; + end + + %% Get.function section + %all get functions pull information from equipment to update + %properties. + function s = get.state(ch) + s = ch.CHAN('state?'); + end + + function out = get.coupling(ch) + out = ch.CHAN('coup?'); + end + + function out = get.bandwidth(ch) + out = ch.CHAN('band?'); + end + + function out = get.offset(ch) + out = ch.CHAN('offs?'); + end + + function out = get.scale(ch) + out = ch.CHAN('scal?'); + end + + function out = get.label(ch) + out = ch.CHAN('lab?'); + end + + function out = get.type(ch) + out = ch.CHAN('type?'); + end + + function out = get.probeunit(ch) + out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT?']); + end + + function out = get.probe(ch) + out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN?']); + end + + %% Set.function section + % This section contains all functions to change settings of a + % channel + + + function ch = set.state(ch,in) + %STATE Set the channel on or off. + %Options: ON | OFF + ch.CHAN('state',in); + end + + + function ch = set.coupling(ch,in) + %COUPLING Set coupling to one of the following settings: + %Options: DCLimit | ACLimit | GND + ch.CHAN('coup',in); + end + + + function ch = set.bandwidth(ch,in) + %BANDWIDTH Set bandwidthlimit. Enable lowpass 20MHz filter + %Options: FULL|B20 + ch.CHAN('band',in); + end + + function ch = set.offset(ch,in) + %OFFSET Sets the DC offset for channel + %Range: Depend on vertical scale and probe attenuation. + %Increment: Depends on vertical scale and probe attenuation. + %On reset: 0 + %Default unit: V + ch.CHAN('offs',in); + end + + function ch = set.scale(ch,in) + %SCALE Sets the scale for the channel + % Scale value, given in Volts per division. + % Range: 1e-3 to 10 (without probe attenuation) + % *RST: 5e-3 + % Default unit: V/div + ch.CHAN('scal',in); + end + + function ch = set.label(ch,in) + %LABEL Sets label of the channel on the scope + ch.CHAN('lab',in); + end + + function ch = set.type(ch,in) + %Sets the type of the channel + ch.CHAN('type',in); + end + + function ch = set.probeunit(ch,unit) + ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT ', unit]); + end + + function ch = set.probe(ch,man) + ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN ', man]); + end + +%% not set or get function + + function enable(ch) + %ENABLE channel + ch.state('ON'); + end + + function disable(ch) + %DISABLE channel + ch.state('OFF'); + end + + function out = frequency(ch) + %FREQUENCY gets the measured frequency of current signal. + %Equal to one over the period. + % See also PERIOD + out = str2double(ch.MEAS('freq')); + end + + function out = peak2peak(ch) + %PEAK2PEAK gets the peak2peak value of current signal. + %Equal to AMPLITUDE times two. + out = str2double(ch.MEAS('peak')); + end + + function out = period(ch) + %PERIOD Gets the period of the current signal. + %Equal to one over the frequency. + out = str2double(ch.MEAS('per')); + end + + function out = amplitude(ch) + %AMPLITUDE Gets the amplitude of the current signal. + %Equal to half the PEAK2PEAK value. + %See also PEAK2PEAK + out = str2double(ch.MEAS('ampl')); + end + + function out = mean(ch) + %MEAN Gets the mean value of the current signal. + out = str2double(ch.MEAS('mean')); + end + + function out = rms(ch) + %RMS Gets the rms value of the current signal. + out = str2double(ch.MEAS('rms')); + end + + function out = phase(ch) + %PHASE gets the phase shift between two signals. + %Cannot be done on a single channel. + out = str2double(ch.MEAS('phas')); + end + + function data = waveform(ch,window) + %WAVEFORM allows for the waveform to be downloaded to matlab + % data = WAVEFORM(ch,window) gets the waveform from the scope and + % returns a array of the waveform. + % + % WINDOW can be one of the following options: + % + %*DEFault* (Default option) + % Waveform points that are visible on the screen. At maximum + % waveform rate, the instrument stores more samples than visible + % on the screen, and DEF returns less values than acquired. + % + %*MAXimum* + % All waveform samples that are stored in the memory. Only available + % if acquisition is stopped. + % + %*DMAXimum* + % Display maximum: Waveform samples stored in the current + % waveform record but only for the displayed time range. At maximum + % waveform rate, the instrument stores more samples than + % visible on the screen, and DMAX returns more values than DEF. + % Only available if acquisition is stopped. + % + % See also OSCILLOSCOPE.SETWAVEFORMSETTINGS + ch.scope.single; + if nargin < 2 + window = 'DEF'; + end + ch.scope.setWaveformSettings(window,'REAL') + data = ch.getWaveform; + end + + + + end + + methods (Hidden, Access = private) + function c = CHAN(ch,string,in) + % CHAN checks if the string corresponds with a query or write + % c = CHAN(ch, string, in) Where 'ch' is the channel-object, + % 'string' is a part of the SCPI-command and 'in' is the actual + % value is to be set. 'in' is optional. + + if nargin == 2 %If only ch and string are given it can be a query + if strcmp(string(end),'?') %If the string ends with a '?' then it is a query. + c = ch.scope.query(['CHAN',num2str(ch.channelnumber),':',string]); + else %Without 'in' and no string it is a event. + ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string]); + end + else %If there is a third argument then the setting should be uploaded to the scope. + ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string,' ',in]); + end + end + end + + + methods (Hidden) + + function data = getWaveform(ch) + %GETWAVEFORM Downloads and processes the waveform from scope. + header = str2double(ch.CHAN('DATA:HEAD?')); %downloads the dataheader of the waveform that is stored on the scope. + data.start = header(1); %First position in header is starttime in seconds + data.stop = header(2); %Second position in header is stoptime in seconds + data.length = header(3); %Thirth position in header is record length of the waveform in samples. + data.sampletime = str2double(ch.CHAN('DATA:XINC?')); %Sample time is downloaded from scope. + ch.scope.opc; %Wait for scope. + ch.scope.write_unsafe(['CHAN',num2str(ch.channelnumber),':DATA?']); %Send command to download the data. + %NOTE! Must be done with write_unsafe. Normal WRITE would also + %check if there are errors but this will interfere with the + %datastream. + data.data = ch.scope.readWaveform(data.length); %Read data from buffer. + end + + function c = MEAS(ch,string) + %MEAS makes all the measurement-functions easier. + %Most of the measurements queries start with + %MEAS:RESult:ACT? Thus goes automatic right now. + c = ch.scope.query(['MEAS',num2str(ch.channelnumber),':RES:ACT?',string]); + end + +% function c = CHANsend(ch,string,in) +% c = ['CHAN',num2str(ch.channelnumber),':',string,' ',in]; +% end + end +end \ No newline at end of file diff --git a/OOequipment/subfiles/Equipment.m b/OOequipment/subfiles/Equipment.m index d7112ef..5b71892 100644 --- a/OOequipment/subfiles/Equipment.m +++ b/OOequipment/subfiles/Equipment.m @@ -3,10 +3,10 @@ classdef Equipment < handle % Detailed explanation goes here properties (SetAccess=protected) - name - tcp - channel - locked + name %name of equipment + tcp %TCP-object with connection to equipment + channel %GPIB-channel if equipment is connected via prologix + locked %lock frontpanel manufacturer model serialnumber @@ -258,6 +258,7 @@ classdef Equipment < handle methods (Access = protected, Hidden) function setPrologix(ecq) + %SETPROLOGIX Set the correct default settings ecq.write_unsafe('++mode 1'); %set device in controller mode ecq.write_unsafe('++auto 0'); %disable automatic datapull. this avoids errors on equipment. end @@ -344,10 +345,13 @@ classdef Equipment < handle end function output = optionnum2str(input) + %OPTIONNUM2STR Change numeric or string input to string output if isnum(input) - output = num2str(input); - else + output = num2str(real(input)); + elseif ischar(input) output = input; + else + error("Expected a character array or numeric value as input"); end end diff --git a/OOequipment/subfiles/Oscilloscope.m b/OOequipment/subfiles/Oscilloscope.m index 319c111..309d8ec 100644 --- a/OOequipment/subfiles/Oscilloscope.m +++ b/OOequipment/subfiles/Oscilloscope.m @@ -1,84 +1,158 @@ classdef Oscilloscope < Equipment - %OSCILLOSCOPE Summary of this class goes here - % Detailed explanation goes here + %OSCILLOSCOPE is the classdef for a Oscilloscope + % This oscilloscope object can contain multiple channels and trigger + % settings. + % EQUIPMENT is the parent class of OSCILLOSCOPE + % This class contains objects for each channel and the trigger. + % See also: TRIGGER, CHANNEL properties - nchannels - horizontalPosition - timescale - ch1 - ch2 - ch3 - ch4 - trigger - acquisition + nchannels %number of channels the scope has + horizontalPosition %horizontal position in seconds + timescale %horizontal scale in seconds/div + ch1 %channel 1 object + ch2 %channel 2 object (empty if NCHANNELS < 2) + ch3 %channel 3 object (empty if NCHANNELS < 3) + ch4 %channel 4 object (empty if NCHANNELS < 4) + trigger %trigger object + end + properties (Dependent) + acquisition %acquisition setting (stop|run|single) end methods function sc = Oscilloscope(ipAddress,port,nchannels) %OSCILLOSCOPE Construct an instance of this class - % Detailed explanation goes here - sc@Equipment(ipAddress,port,-1); - sc.trigger = Trigger(sc); - sc.nchannels = nchannels; - for i = 1:nchannels - sc.(['ch',num2str(i)]) = Channel(sc,i); + % This constructor creates a new scope object. + sc@Equipment(ipAddress,port,-1); %make this object a child of the EQUIPMENT class + sc.trigger = Trigger(sc); %create a trigger object + sc.nchannels = min(nchannels,4); %Set number of channels with a maximum of 4. + %more channels is possible but this requires more properties. + for i = 1:nchannels %create a channel object for each channel + sc.(['ch',num2str(i)]) = ChannelClass(sc,i); end end function clear(sc) + %CLEAR is used to clear the oscilloscope. + % closes the message on screen + % sends the clear command to the scope and flushes the + % TCP-buffer. sc.messageclose; sc.write_unsafe('*cls'); flushinput(sc.tcp); end function s = get.acquisition(sc) + %ACQUISITION returns the acquisition state from the scope. s = sc.query('ACQ:STAT?'); end function run(sc) + %RUN sets the ACQUISITION state to run. sc.write_noerror('RUN'); end function single(sc) + %SINGLE sets the ACQUISITION state to single + %After running a single acquisition the scope will go to STOP sc.write_noerror('SING'); end function stop(sc) + %STOP sets the ACQUISITION state to stop. + %Stops the signal acquisition imidiatly. Use SINGLE to run one + %single waveform acquisition before stopping. + %See also RUN, SINGLE sc.write_noerror('STOP'); end function auto(sc) + %AUTO sends the autoset command to the scope. + %It should be noted that this function can result in aliassing + %of the wave acquisition. sc.write_noerror('AUT'); end - function enable_channels(sc) - sc.write('CHAN:AON') + function enable_channels(sc,channels) + %ENABLE_CHANNELS enables all available channels on scope. + if nargin < 2 + sc.write('CHAN:AON'); + else + for i = channels + sc.(['ch' num2str(i)]).enable; + end + end end - function disable_channels(sc) - sc.write('CHAN:AOFF') + function disable_channels(sc,channels) + %DISABLE_CHANNELS disables all available channels on scope. + if nargin < 2 + sc.write('CHAN:AOFF'); + else + for i = channels + sc.(['ch' num2str(i)]).disable; + end + end end function setMeasurement(sc,measurement,type,source1,source2) - prefix = ['MEAS',num2str(measurement),':']; - fprintf(num2str(nargin)) + %SETMEASUREMENT sets the measurement slots on the scope. + %SETMEASUREMENT(sc, measurement, type, source1 [,source2]); + %sets one of the measurement place with 'measurement', this can + %be a value in the range 1 till 4. 'source1' and 'source2' give + %on what channel the measurement should be applied. This should + %be done in de form of 'CH' where = 1..4. The default + %settings are: source1 = 'CH1' and source2 = 'CH2' + %With 'type' a measurement type can be selected. Some of the + %measurements require at least 2 channels. + % + %SINGLE CHANNEL: + % FREQuency | PERiod | PEAK | UPEakvalue | LPEakvalue | + % PPCount | NPCount | RECount | FECount | HIGH | LOW | + % AMPLitude | MEAN | RMS | RTIMe | FTIMe | PDCYcle | + % NDCYcle | PPWidth | NPWidth | CYCMean | CYCRms | + % STDDev | CYCStddev | BWIDth | POVershoot | NOVershoot + % + %DOUBLE CHANNEL: + % DELay | PHASe + prefix = ['MEAS',num2str(measurement),':']; %define the prefix for the SCPI command. + %fprintf(num2str(nargin)) + %set the default values. if nargin < 5 source2 = 'CH2'; if nargin < 4 source1 = 'CH1'; end end - source = [source1,', ',source2]; - sc.write([prefix,'SOUR ',source]); - sc.write([prefix,'MAIN ',type]); + source = [source1,', ',source2]; %set the sources suffix + sc.write([prefix,'SOUR ',source]); %set the sources for the measurementposition + sc.write([prefix,'MAIN ',type]); %set the measurementtype for the measurementposition end function m = getMeasurement(sc,measurement) + %GETMEASUREMENT pulls the value from measurementposition. + %m = GETMEASUREMENT(sc,measurement) will return the value that + %was acquired from the measurementslot (given as + %'measurement') as a double. m = str2double(sc.query(['MEAS',num2str(measurement),':RES:ACT?'])); end function setWaveformSettings(sc,window,format,type) + %SETWAVEFORMSETTINGS sets the settings to acquire the waveform + %Before the waveform can be downloaded the aquisition settings + %for the channels and/or scope must be set: + %SETWAVEFORMSETTINGS(sc,window,format,type) where: + %'window' + % Set the acquisition window of the waveform. Possible settings + % are: DEF (default option) | MAX | DMAX + % See also CHANNELCLASS.WAVEFORM + % + %'format' + % Set the dataformat of the data. ASCii|REAL (default option)|UINTeger + % + %'type' + % Set resolution mode. SAMPle (default option)| PDETect | HRESolution if nargin < 4 type = 'HRES'; if nargin < 3 @@ -89,69 +163,72 @@ classdef Oscilloscope < Equipment end end sc.clear; - sc.write(['CHAN:TYPE ',type]); - sc.write(['FORM ',format]); - sc.write('FORM:BORD MSBF'); - sc.write(['CHAN:DATA:POIN ',window]); - sc.single; - end - - function data = readWaveform(sc,datalength) - prefixstring = fscanf(sc.tcp,'%c',2); - prefixlength = str2double(prefixstring(2)); - fscanf(sc.tcp,'%c',prefixlength); - data = sc.bin_read_float(datalength); - flushinput(sc.tcp); + sc.write(['CHAN:TYPE ',type]); %set resolution + sc.write(['FORM ',format]); %set dataformat + sc.write('FORM:BORD MSBF'); %set bitorder to Most Significant Bit First + sc.write(['CHAN:DATA:POIN ',window]); %set window length + sc.single; %run sigle acquisition + end + + function data = readWaveform(sc,datalength) + %READWAVEFORM download waveform from oscilloscope + %Downloads the data from oscilloscope with BIN_READ_FLOAT. + %Datastream is constructed as follows: + % #41024 + %#4 = number of digits of the following number (= 4 in the example) + %in the code these two are stored as 'prefixstring'. + %1024 = number of following data bytes. + %This breaks if there the TCP-buffer was not cleared before the + %SCPI-command 'CHAN:DATA?' was send. + prefixstring = fscanf(sc.tcp,'%c',2);%read the first 2 characters of the tcp-buffer and store in prefixstring. + prefixlength = str2double(prefixstring(2));%change the second character of prefixstring to double. (this leaves the # behind) + fscanf(sc.tcp,'%c',prefixlength);%read the number of characters equal to the number from the prefixlength. + data = sc.bin_read_float(datalength); %run the function from the EQUIPMENTCLASS to download all the data. + flushinput(sc.tcp);%after the download make sure that nothing is left behind in the tcpbuffer. end function data = waveform(sc,channels,window,type) - if nargin < 4 - type = 'HRES'; + %WAVEFORM downloads waveform of one or more channels. + %data = WAVEFORM(sc,channels,window,type) returns a struct with + %all waveformdata from the scope. This includes the sampletime + %and data length. + %'channels' is an array of all the channels that the function + %should acquire. + %'window' is the width of the data acquisition. + %'type' is the resolution mode. + %See also: SETWAVEFORMSETTINGS + if nargin < 4 + type = 'HRES'; %default resolution is high resolution if nargin < 3 - window = 'DEF'; + window = 'DEF'; %default windowsize is DEFault if nargin < 2 - channels = 1:sc.nchannels; + channels = 1:sc.nchannels; %default selection channels is all channels end end end - sc.enable_channels; - sc.setWaveformSettings(window,'REAL',type); + sc.enable_channels(channels);%enable the channels for the acquisition + sc.setWaveformSettings(window,'REAL',type);%Set the correct settings for i = channels - curcha = ['ch',num2str(i)]; - wave = sc.(curcha).getWaveform; - data.(curcha) = wave.data; + curcha = ['ch',num2str(i)]; %make string for current channel + wave = sc.(curcha).getWaveform; %get waveformdata from current channel + data.(curcha) = wave.data; %store wavefromdata from wave-struct into data-struct. end - data.sampletime = wave.sampletime; + data.sampletime = wave.sampletime; %together with the waveforms add sampletime and datalength to data-struct. data.length = wave.length; end function message(sc,msg) + %MESSAGE Print message on screen of oscilloscope. sc.messageclose; - sc.write(['DISP:DIAL:MESS ''',msg,'''']) + sc.write(['DISP:DIAL:MESS ''',msg,''''])%send message end function messageclose(sc) - sc.opc; - sc.write_unsafe('DISP:DIAL:CLOS'); + %MESSAGECLOSE Close message on the screen of oscillscope. + sc.opc; %wait on ready from scope. + sc.write_unsafe('DISP:DIAL:CLOS'); %clear message end - - -% function data = waveform(ch,cha) -% ch.scope.clear; -% ch.scope.write('CHAN1:TYPE HRES'); -% ch.scope.write('FORM REAL'); -% ch.scope.write('FORM:BORD MSBF'); -% ch.scope.write('CHAN1:DATA:POIN DEF'); -% ch.scope.write('SING'); -% header = str2num(ch.scope.query('CHAN1:DATA:HEAD?')); -% ch.scope.write_unsafe('CHAN1:DATA?'); -% prefixstring = fscanf(ch.scope.tcp,'%c',2); -% prefixlength = str2double(prefixstring(2)); -% datalength = fscanf(ch.scope.tcp,'%c',prefixlength); -% data = fread(ch.scope.tcp,header(3),'float'); -% flushinput(ch.scope.tcp); -% end end end diff --git a/OOequipment/subfiles/html/Channel.html b/OOequipment/subfiles/html/Channel.html new file mode 100644 index 0000000..8af1438 --- /dev/null +++ b/OOequipment/subfiles/html/Channel.html @@ -0,0 +1,418 @@ + + + + + Channel
classdef Channel
+% CHANNEL is the class for one channel of the oscilloscope. Multiple
+% settings for the different channels of the oscilloscope can be changed
+% via this class definition
+
+    properties (Hidden, Access = private)
+        scope % Contains the class of the scope that is parent of this channel.
+        channelnumber % is the number of the channel on the scope.
+    end
+    properties (Dependent)
+        state
+        coupling
+        bandwidth
+        scale
+        offset
+        probe
+        label
+        type
+        probeunit
+    end
+
+    methods
+        function ch = Channel(scope,channelnumber)
+            ch.channelnumber = channelnumber;
+            ch.scope = scope;
+        end
+
+        function s = get.state(ch)
+            s = ch.CHAN('state?');
+        end
+
+        function out = get.coupling(ch)
+            out = ch.CHAN('coup?');
+        end
+
+        function out = get.bandwidth(ch)
+            out = ch.CHAN('band?');
+        end
+
+        function out = get.offset(ch)
+            out = ch.CHAN('offs?');
+        end
+
+        function out = get.scale(ch)
+            out = ch.CHAN('scal?');
+        end
+
+        function out = get.label(ch)
+            out = ch.CHAN('lab?');
+        end
+
+        function out = get.type(ch)
+            out = ch.CHAN('type?');
+        end
+
+        function out = get.probeunit(ch)
+            out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT?']);
+        end
+
+        function out = get.probe(ch)
+            out = ch.scope.query(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN?']);
+        end
+
+        function ch = set.state(ch,in)
+            ch.CHAN('state',in);
+        end
+
+        function ch = set.coupling(ch,in)
+            ch.CHAN('coup',in);
+        end
+
+        function ch = set.bandwidth(ch,in)
+            ch.CHAN('band',in);
+        end
+
+        function ch = set.offset(ch,in)
+            ch.CHAN('offs',in);
+        end
+
+        function ch = set.scale(ch,in)
+            ch.CHAN('scal',in);
+        end
+
+        function ch = set.label(ch,in)
+            ch.CHAN('lab',in);
+        end
+
+        function ch = set.type(ch,in)
+            ch.CHAN('type',in);
+        end
+
+        function out = frequency(ch)
+            out = str2double(ch.MEAS('freq'));
+        end
+
+        function out = peak2peak(ch)
+            out = str2double(ch.MEAS('peak'));
+        end
+
+        function out = period(ch)
+            out = str2double(ch.MEAS('per'));
+        end
+
+        function out = amplitude(ch)
+            out = str2double(ch.MEAS('ampl'));
+        end
+
+        function out = mean(ch)
+            out = str2double(ch.MEAS('mean'));
+        end
+
+        function out = rms(ch)
+            out = str2double(ch.MEAS('rms'));
+        end
+
+        function out = phase(ch)
+            out = str2double(ch.MEAS('phas'));
+        end
+
+        function ch = set.probeunit(ch,unit)
+            ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:UNIT ', unit]);
+        end
+
+        function ch = set.probe(ch,man)
+            ch.scope.write(['PROB',num2str(ch.channelnumber),':SET:ATT:MAN ', man]);
+        end
+
+        function data = waveform(ch,window)
+            ch.scope.single;
+            if nargin < 2
+                window = 'DEF';
+            end
+            ch.scope.setWaveformSettings(window,'REAL')
+            data = ch.getWaveform;
+        end
+
+        function data = getWaveform(ch)
+            header = str2num(ch.CHAN('DATA:HEAD?'));
+            data.length = header(3);
+            data.start = header(1);
+            data.stop = header(2);
+            data.sampletime = str2double(ch.CHAN('DATA:XINC?'));
+            ch.scope.opc;
+            ch.scope.write_unsafe(['CHAN',num2str(ch.channelnumber),':DATA?']);
+            data.data = ch.scope.readWaveform(data.length);
+        end
+
+    end
+
+    methods (Hidden, Access = private)
+        function c = CHAN(ch,string,in)
+            if nargin == 2
+                if strcmp(string(end),'?')
+                    c = ch.scope.query(['CHAN',num2str(ch.channelnumber),':',string]);
+                else
+                    ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string]);
+                end
+            else
+                ch.scope.write(['CHAN',num2str(ch.channelnumber),':',string,' ',in]);
+            end
+        end
+
+        function c = MEAS(ch,string)
+            c = ch.scope.query(['MEAS',num2str(ch.channelnumber),':RES:ACT?',string]);
+        end
+
+%         function c = CHANsend(ch,string,in)
+%             c = ['CHAN',num2str(ch.channelnumber),':',string,' ',in];
+%         end
+    end
+end
+
Not enough input arguments.
+
+Error in Channel (line 24)
+            ch.channelnumber = channelnumber;
+
\ No newline at end of file