diff --git a/Componenten Fourierkastjes.txt b/Componenten Fourierkastjes.txt new file mode 100644 index 0000000..58ce327 --- /dev/null +++ b/Componenten Fourierkastjes.txt @@ -0,0 +1,23 @@ +Aantallen zijn per kastje. D = verkrijgbaar bij Digi-Key; M = verkrijgbaar bij Mouser. + +Condensatoren (4x): 100nF 2.5% Siemens MKP Axiaal 14x19mm +M Vervanger: Vishay MKP1839410163 +Weerstanden (4x): 20kOhm 1% 50ppm/k 2.5x6.2mm +D/M Vervanger: Vishay RN55C2002FB14 +Spoelen (4x): +D Kern, onderhelft: B65701T1000A48 (levertijd één maand) +- Kern, bovenhelft: B65701D1000A48 (slecht verkrijgbaar; mogelijkkan de schroefdraad die in de B65701T1000A48 geplakt zit verwijderd worden om een B65701D1000A48 te maken. B65701T1000A48 lijkt bij Digi-Key beide helften te bevatten.) +D/M Stelschroef: B65679E0002X022 (B65679E0003X022 bestaat ook, maar het kernmateriaal hierop is iets dunner. De air-gap kan dan dus niet volledig gesloten worden, en aangezien de originele spoel met 485 windingen een zelfinductie van maximaal 237mH heeft, moet deze, met een kern met een A_L van 1000nH, wel volledig gesloten kunnen worden.) +D(/M) Mount: B65705B0003X000 (Momenteel niet op voorraad bij Mouser.) +D/M Draadhouder: B65702B0000T001 +Draad: +D 0.25mm (31m): Vergelijkbaar met CNC Tech 600232 (3.5km, AWG32) +D 0.35mm (16m): Vergelijkbaar met CNC Tech 600228 (1.4km, AWG28) +D 0.45mm (11m): Vergelijkbaar met CNC Tech 600226 (0.9km, AWG26) +D 0.60mm (7m): CNC Tech 600224 (0.5km, AWG24) +BNC-Connector (2x): +D/M Vergelijkbaar met Amphenol 031-5431-10RFX +Schakelaars (4x): +D/M Vergelijkbaar met C&K 7101MD9ABE +Behuizing (1x): Niet meer te vinden +M Vervanger: Hammond 1402B of 1402BV (voorraad beperkt, levertijd daarna drie weken) \ No newline at end of file diff --git a/Equipment/prologix_discovery.m b/Equipment/prologix_discovery.m index 33458d1..d0f3fb8 100644 --- a/Equipment/prologix_discovery.m +++ b/Equipment/prologix_discovery.m @@ -25,6 +25,7 @@ remote_port = 3040; %% setup dsp to send and recieve udp packets. udpconnection = udp('255.255.255.255',3040); + udpconnection.LocalHost = '10.0.0.10'; %hudpr = dsp.UDPReceiver('LocalIPPort',local_port); % hudps = dsp.UDPSender('RemoteIPAddress','255.255.255.255','RemoteIPPort',remote_port,'LocalIPPortSource','Property','LocalIPPort',local_port); % start recieving udp packets 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/discovery.m b/OOequipment/debug/discovery.m new file mode 100644 index 0000000..6558794 --- /dev/null +++ b/OOequipment/debug/discovery.m @@ -0,0 +1,17 @@ + +ipPrefix='10.0.0'; +ipPrefixRegex = '10\.0\.0'; +if ispc() + system(['for /L %a in (1,1,254) do @start /b ping ' ipPrefix '.%a -w 100 -n 2 >nul']); + [~,arptable] = system('arp -a'); + ipaddresses = regexp(arptable,[ipPrefixRegex '\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])(?=[-a-f0-9\s]*?dynamic)'],'match'); +elseif isunix() + [~,ipaddresses] = system(['echo $(seq 254) | xargs -P255 -I% -d" " ping -W 1 -c 1 ' ipPrefix '.% | grep -P -o "[0-1].*?(?=:)"']); +elseif ismac() + [~,ipaddresses] = system(['seq 254 | xargs -n1 -P255 -I% -- sh -c "ping -W1 -c1 ' ipPrefix '.% &>/dev/null && echo ' ipPrefix '.%"']); +else + +end + + +%% find prologix \ 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/initializeEquipment.m b/OOequipment/initializeEquipment.m index 78b196d..c096c2d 100644 --- a/OOequipment/initializeEquipment.m +++ b/OOequipment/initializeEquipment.m @@ -1,9 +1,9 @@ if ~exist('theory_only','var') || theory_only == false if ~exist('functiongenerator','var') - functiongenerator = FunctionGenerator('10.0.0.3',1234,10); + functiongenerator = FunctionGeneratorClass('10.0.0.3',1234,10); end if ~exist('oscilloscope','var') - oscilloscope = Oscilloscope('10.0.0.2',5025,2); + oscilloscope = OscilloscopeClass('10.0.0.2',5025,2); 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..0c4b4b9 --- /dev/null +++ b/OOequipment/subfiles/ChannelClass.m @@ -0,0 +1,268 @@ +classdef ChannelClass +% CHANNELCLASS 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 +% See also: OSCILLOSCOPECLASS + + 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 = ChannelClass(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 ', double2str(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 OSCILLOSCOPECLASS.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 diff --git a/OOequipment/subfiles/Equipment.m b/OOequipment/subfiles/EquipmentClass.m similarity index 73% rename from OOequipment/subfiles/Equipment.m rename to OOequipment/subfiles/EquipmentClass.m index d7112ef..bea47ff 100644 --- a/OOequipment/subfiles/Equipment.m +++ b/OOequipment/subfiles/EquipmentClass.m @@ -1,12 +1,12 @@ -classdef Equipment < handle +classdef EquipmentClass < handle %EQUIPMENT Summary of this class goes here % 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 @@ -20,13 +20,13 @@ classdef Equipment < handle end methods - function ecq = Equipment(ipAddress,port,channel) + function ecq = EquipmentClass(ipAddress,port,channel) %EQUIPMENT Construct an instance of this class. % This functions opens the required TCP connection % for this device. Channel is GPIB-channel on prologix % converter if used, otherwise set channel to -1. % Name is queried from device via '*IDN?' command. - ecq.tcp = Equipment.getTCP(ipAddress,port); + ecq.tcp = EquipmentClass.getTCP(ipAddress,port); ecq.locked = false; ecq.channel = channel; ecq.name = ecq.idn(); @@ -74,8 +74,10 @@ classdef Equipment < handle ecq.write_unsafe('*OPC?'); for i = 1:10 ack = ecq.read; - if strcmp(ack(1),'1') - return + if ~isempty(ack) + if strcmp(ack(1),'1') + return + end end end error('Device is not ready'); @@ -180,7 +182,7 @@ classdef Equipment < handle %The function will pull all errors from the device error stack. %This is up to a maximum of 20 errors. If errors have occured %the function will throw a warning with all the error messages. - for i = 1:20 + for i = 1:1 output = ecq.query_unsafe('SYSTem:ERRor?'); %Query error message from device. % [msgstr, msgid] = lastwarn; % if strcmp(msgid,'instrument:fscanf:unsuccessfulRead') @@ -258,14 +260,17 @@ 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. + ecq.write_unsafe('++eoi 1'); %enable end of line character + ecq.write_unsafe('++eos 0'); %Set end of line character end function delete(ecq) %DELETE Destructs the current object. ecq.unlock; - Equipment.getTCP(ecq.tcp.RemoteHost,-ecq.tcp.RemotePort); + EquipmentClass.getTCP(ecq.tcp.RemoteHost,-ecq.tcp.RemotePort); end end @@ -287,7 +292,7 @@ classdef Equipment < handle %call) make a struct in the variable. tcpconnection = struct; end - [ipname,ipAddress] = Equipment.ip2structname(ipAddress,abs(port)); %Get a structname and a cleaned ipaddress. + [ipname,ipAddress] = EquipmentClass.ip2structname(ipAddress,abs(port)); %Get a structname and a cleaned ipaddress. if port > 0 %if port number is positive a connection is made. @@ -329,7 +334,7 @@ classdef Equipment < handle function num = forceNum(input) %FORCENUM Throws an error if the input is not numeric. - if ~Equipment.isnum(input) + if ~EquipmentClass.isnum(input) error('Input should be a (single) number.'); end num = input; @@ -344,10 +349,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 @@ -356,8 +364,71 @@ classdef Equipment < handle %structname to store stuff in struct (especially for GETTCP). %cleanip is a shortened ip without leading zeros. cleanip = regexprep(ipAddress,'(?:(?<=\.)|^)(?:0+)(?=\d)',''); - Equipment.iptest(cleanip); + EquipmentClass.iptest(cleanip); structname = matlab.lang.makeValidName(['ip',cleanip,'_',num2str(port)]); end + + function ipaddress = getInterfaceIP() + %GETINTERFACEIP gets the local ipaddresses on this machine. + if ispc + % Code to run on Windows plaform + [status,result]=system('ipconfig'); + if ~(status == 0) + error('Failed to find local IP address'); + end + ipaddress = regexp(result,'(?<=\n IPv4 Address[ \.]*: )([0-9]{1,3}\.?){4}','match'); + elseif ismac + % Code to run on Mac platform + [status,result]=system('ifconfig'); + if ~(status == 0) + error('Failed to find local IP address'); + end + ipaddress = regexp(result,'(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])(?=\/)','match'); + elseif isunix + % Code to run on Unix platform + [status,result]=system('ip addr show'); + if ~(status == 0) + error('Failed to find local IP address'); + end + ipaddress = regexp(result,'(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])(?=\/)','match'); + else + error('Platform not supported'); + end + end + + function prologixIP = discoverPrologix() + %DISCOVERPROLOGIX attemts to find the prologix on the network. + %It will broadcast on all interfaces and return the ipaddress + %of the prologix. Not build for multiple prologixs on a single + %network. + persistent storedipaddress; %store the ipaddress of the prologix + if ~isempty(storedipaddress) + prologixIP = storedipaddress; + return + end + remotehost = '255.255.255.255'; %set broadcast address + remoteport = 3040; %set remoteport that is used for the prologix discoverprotocol + timeout = 1; %set timeout on package. + % magic string to request ipaddress from prologix: ['5a' '00' '5b' 'db' 'ff' 'ff' 'ff' 'ff' 'ff' 'ff' '00' '00'] + magic_msg = uint8([90 0 91 219 255 255 255 255 255 255 00 00]); + ipaddress = EquipmentClass.getInterfaceIP(); %get all interface addresses from getInterfaceIP. + %create an UDPconnection-object for each interface. + udpconnection = cellfun(@(ip) udp(remotehost,remoteport,'LocalHost',ip,'Timeout',timeout),ipaddress,'UniformOutput',0); + cellfun(@fopen,udpconnection); %open all udpconnections + cellfun(@(udpconnection) fwrite(udpconnection,magic_msg),udpconnection); %broadcast the magic_msg via all udpconnections + for i = 1:10 + answer = cellfun(@fread,udpconnection,'UniformOutput',0); %read all udpInputBuffers for response from prologix + ack = ~cellfun(@isempty,answer); %check if prologix responded on one of the interfaces. + if sum(ack) > 0 %true if recieved response + msg = answer{ack}; %put message from answer cell in to msg variable + prologixIP = num2str(msg(21:24)','%d.%d.%d.%d'); %get ipaddress from msg. + cellfun(@fclose,udpconnection); %close all connections + storedipaddress = prologixIP; %store ip-address for next functioncall + return + end + end + cellfun(@fclose,udpconnection); %close all connections + prologixIP = ''; %nothing found, return empty chararray. + end end end \ No newline at end of file diff --git a/OOequipment/subfiles/FunctionGenerator.m b/OOequipment/subfiles/FunctionGeneratorClass.m similarity index 74% rename from OOequipment/subfiles/FunctionGenerator.m rename to OOequipment/subfiles/FunctionGeneratorClass.m index 3824268..7442d11 100644 --- a/OOequipment/subfiles/FunctionGenerator.m +++ b/OOequipment/subfiles/FunctionGeneratorClass.m @@ -1,41 +1,39 @@ -classdef FunctionGenerator < Equipment -% FUNCTION_GENERATOR Control a function generator. -% fg = FUNCTION_GENERATOR('IP', PORT, GPIB_CHAN) connects +classdef FunctionGeneratorClass < EquipmentClass +% FUNCTIONGENERATORCLASS Control a function generator. +% fg = FUNCTIONGENERATORCLASS('IP', PORT, GPIB_CHAN) connects % to a function generator on IPv4 address 'IP', on port % 'PORT' and GPIO channel 'GPIB_CHAN', using the Equipment % class. % -% See also EQUIPMENT, OSCILLOSCOPE, DIGITALMULTIMETER. +% See also EQUIPMENTCLASS, OSCILLOSCOPECLASS, DIGITALMULTIMETERCLASS. properties (Dependent) - %Dependent properties; stored on function generator, - % read from or written to function generator when required. - waveform - frequency - voltage - unit - offset - load - output + waveform %Waveform shape + frequency %Frequency setting in hertz + voltage %Amplitude setting as defined by FUNCTIONGENERATORCLASS.UNIT + unit %unit of amplitude: VPP|VRMS|DBM|DEFault + offset %Offset setting in volt + load %output impedence setting 50|inf + output %output enable setting. Only available on 332xx and newer. end methods - function fg = FunctionGenerator(ipAddress,port,channel) - % FUNCTION_GENERATOR Control a function generator. - % fg = FUNCTION_GENERATOR('IP', PORT, GPIB_CHAN) connects + function fg = FunctionGeneratorClass(ipAddress,port,channel) + % FUNCTIONGENERATORCLASS Control a function generator. + % fg = FUNCTIONGENERATORCLASS('IP', PORT, GPIB_CHAN) connects % to a function generator on IPv4 address 'IP', on port % 'PORT' and GPIO channel 'GPIB_CHAN', using the Equipment % class. % - % See also EQUIPMENT, OSCILLOSCOPE, DIGITALMULTIMETER. - fg@Equipment(ipAddress,port,channel); + % See also EQUIPMENTCLASS, OSCILLOSCOPECLASS, DIGITALMULTIMETERCLASS. + fg@EquipmentClass(ipAddress,port,channel); end function w = get.waveform(fg) %Get the function generator waveform setting on waveform % variable access, using the corresponding SCPI command. - w = FunctionGenerator.getWave(fg.query('FUNCtion:SHAPe?')); + w = FunctionGeneratorClass.getWave(fg.query('FUNCtion:SHAPe?')); end function f = get.frequency(fg) @@ -53,7 +51,7 @@ classdef FunctionGenerator < Equipment function u = get.unit(fg) %Get function generator output voltage unit setting on offset % variable access, using the corresponding SCPI command. - u = FunctionGenerator.getUnit(fg.query('VOLTage:UNIT?')); + u = FunctionGeneratorClass.getUnit(fg.query('VOLTage:UNIT?')); end function o = get.offset(fg) @@ -65,7 +63,7 @@ classdef FunctionGenerator < Equipment function l = get.load(fg) %Get function generator load setting on load variable % access, using the corresponding SCPI command. - l = FunctionGenerator.getLoad(fg.query('OUTPut:LOAD?')); + l = FunctionGeneratorClass.getLoad(fg.query('OUTPut:LOAD?')); end function out = get.output(fg) @@ -79,7 +77,7 @@ classdef FunctionGenerator < Equipment function fg = set.waveform(fg,w) %Set function generator waveform setting on waveform variable % access, using the corresponding SCPI command. - fg.write(['FUNCtion:SHAPe ' FunctionGenerator.getWave(w)]); + fg.write(['FUNCtion:SHAPe ' FunctionGeneratorClass.getWave(w)]); end function fg = set.frequency(fg,f) @@ -99,7 +97,7 @@ classdef FunctionGenerator < Equipment function fg = set.unit(fg,u) %Set function generator output voltage unit setting on unit % variable access, using the corresponding SCPI command. - fg.write(['VOLTage:UNIT ' FunctionGenerator.getUnit(u)]); + fg.write(['VOLTage:UNIT ' FunctionGeneratorClass.getUnit(u)]); end function fg = set.offset(fg,o) @@ -112,16 +110,37 @@ classdef FunctionGenerator < Equipment function fg = set.load(fg,l) %Set function generator load setting on load variable access, % using the corresponding SCPI command. - fg.write(['OUTPut:LOAD ' FunctionGenerator.getLoad(l)]); + fg.write(['OUTPut:LOAD ' FunctionGeneratorClass.getLoad(l)]); end function fg = set.output(fg,out) if strcmp(fg.model(1:3),'335') || strcmp(fg.model(1:3),'332') - fg.write(['OUTP ' Equipment.optionnum2str(out)]) + fg.write(['OUTP ' EquipmentClass.optionnum2str(out)]) end end function downloadwaveform(fg,waveform,name) + switch fg.model + case '33120A' + downloadwaveform_legacy(fg,waveform,name); + otherwise + downloadwaveform_new(fg,waveform,name); + end + end + + function downloadwaveform_legacy(fg,waveform,name) + name_trunc = name(1:min(length(name),8)); + fg.opc; + fg.write_noerror(['data volatile' num2str(waveform,',%0.4f')]); + fg.opc; + fg.error; + fg.write_noerror(['data:copy ' name_trunc]); + fg.opc; + fg.error; + fg.write(['func:user' name_trunc]); + end + + function downloadwaveform_new(fg,waveform,name) fg.disableEOI; fg.write_unsafe(['data:arb ' name ',']); fg.enableEOI; @@ -136,7 +155,6 @@ classdef FunctionGenerator < Equipment x = linspace(-periods*pi,periods*pi,1600); y = exp(-abs(x./6)).*sin(x)./0.8; fg.downloadwaveform(y,'scintilla'); - end end diff --git a/OOequipment/subfiles/Oscilloscope.m b/OOequipment/subfiles/Oscilloscope.m deleted file mode 100644 index 319c111..0000000 --- a/OOequipment/subfiles/Oscilloscope.m +++ /dev/null @@ -1,161 +0,0 @@ -classdef Oscilloscope < Equipment - %OSCILLOSCOPE Summary of this class goes here - % Detailed explanation goes here - - properties - nchannels - horizontalPosition - timescale - ch1 - ch2 - ch3 - ch4 - trigger - acquisition - 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); - end - end - - function clear(sc) - sc.messageclose; - sc.write_unsafe('*cls'); - flushinput(sc.tcp); - end - - function s = get.acquisition(sc) - s = sc.query('ACQ:STAT?'); - end - - function run(sc) - sc.write_noerror('RUN'); - end - - function single(sc) - sc.write_noerror('SING'); - end - - function stop(sc) - sc.write_noerror('STOP'); - end - - function auto(sc) - sc.write_noerror('AUT'); - end - - function enable_channels(sc) - sc.write('CHAN:AON') - end - - function disable_channels(sc) - sc.write('CHAN:AOFF') - end - - function setMeasurement(sc,measurement,type,source1,source2) - prefix = ['MEAS',num2str(measurement),':']; - fprintf(num2str(nargin)) - 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]); - end - - function m = getMeasurement(sc,measurement) - m = str2double(sc.query(['MEAS',num2str(measurement),':RES:ACT?'])); - end - - function setWaveformSettings(sc,window,format,type) - if nargin < 4 - type = 'HRES'; - if nargin < 3 - format = 'REAL'; - if nargin < 2 - window = 'DEF'; - end - 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); - end - - - function data = waveform(sc,channels,window,type) - if nargin < 4 - type = 'HRES'; - if nargin < 3 - window = 'DEF'; - if nargin < 2 - channels = 1:sc.nchannels; - end - end - end - sc.enable_channels; - sc.setWaveformSettings(window,'REAL',type); - for i = channels - curcha = ['ch',num2str(i)]; - wave = sc.(curcha).getWaveform; - data.(curcha) = wave.data; - end - data.sampletime = wave.sampletime; - data.length = wave.length; - end - - function message(sc,msg) - sc.messageclose; - sc.write(['DISP:DIAL:MESS ''',msg,'''']) - end - - function messageclose(sc) - sc.opc; - sc.write_unsafe('DISP:DIAL:CLOS'); - 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/OscilloscopeClass.m b/OOequipment/subfiles/OscilloscopeClass.m new file mode 100644 index 0000000..e1f177a --- /dev/null +++ b/OOequipment/subfiles/OscilloscopeClass.m @@ -0,0 +1,238 @@ +classdef OscilloscopeClass < EquipmentClass + %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 %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 = OscilloscopeClass(ipAddress,port,nchannels) + %OSCILLOSCOPE Construct an instance of this class + % This constructor creates a new scope object. + sc@EquipmentClass(ipAddress,port,-1); %make this object a child of the EQUIPMENT class + sc.trigger = TriggerClass(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,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,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) + %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]; %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 + format = 'REAL'; + if nargin < 2 + window = 'DEF'; + end + end + end + sc.clear; + 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) + %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'; %default windowsize is DEFault + if nargin < 2 + channels = 1:sc.nchannels; %default selection channels is all channels + end + end + end + 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)]; %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; %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,''''])%send message + end + + function messageclose(sc) + %MESSAGECLOSE Close message on the screen of oscillscope. + sc.opc; %wait on ready from scope. + sc.write_unsafe('DISP:DIAL:CLOS'); %clear message + end + end +end + + + + + diff --git a/OOequipment/subfiles/Trigger.m b/OOequipment/subfiles/TriggerClass.m similarity index 97% rename from OOequipment/subfiles/Trigger.m rename to OOequipment/subfiles/TriggerClass.m index 03be68c..109391e 100644 --- a/OOequipment/subfiles/Trigger.m +++ b/OOequipment/subfiles/TriggerClass.m @@ -1,4 +1,4 @@ -classdef Trigger +classdef TriggerClass %TRIGGER Summary of this class goes here % Detailed explanation goes here @@ -17,7 +17,7 @@ classdef Trigger end methods - function tr = Trigger(scope) + function tr = TriggerClass(scope) tr.scope = scope; 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