| @@ -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) | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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<m>: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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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<m>' where <m> = 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<value1><value2>…<value n> | |||
| %#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 | |||
| @@ -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 | |||
| @@ -0,0 +1,418 @@ | |||
| <!DOCTYPE html | |||
| PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |||
| <html><head> | |||
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |||
| <!-- | |||
| This HTML was auto-generated from MATLAB code. | |||
| To make changes, update the MATLAB code and republish this document. | |||
| --><title>Channel</title><meta name="generator" content="MATLAB 9.4"><link rel="schema.DC" href="http://purl.org/dc/elements/1.1/"><meta name="DC.date" content="2018-03-24"><meta name="DC.source" content="Channel.m"><style type="text/css"> | |||
| html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}:focus{outine:0}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0} | |||
| html { min-height:100%; margin-bottom:1px; } | |||
| html body { height:100%; margin:0px; font-family:Arial, Helvetica, sans-serif; font-size:10px; color:#000; line-height:140%; background:#fff none; overflow-y:scroll; } | |||
| html body td { vertical-align:top; text-align:left; } | |||
| h1 { padding:0px; margin:0px 0px 25px; font-family:Arial, Helvetica, sans-serif; font-size:1.5em; color:#d55000; line-height:100%; font-weight:normal; } | |||
| h2 { padding:0px; margin:0px 0px 8px; font-family:Arial, Helvetica, sans-serif; font-size:1.2em; color:#000; font-weight:bold; line-height:140%; border-bottom:1px solid #d6d4d4; display:block; } | |||
| h3 { padding:0px; margin:0px 0px 5px; font-family:Arial, Helvetica, sans-serif; font-size:1.1em; color:#000; font-weight:bold; line-height:140%; } | |||
| a { color:#005fce; text-decoration:none; } | |||
| a:hover { color:#005fce; text-decoration:underline; } | |||
| a:visited { color:#004aa0; text-decoration:none; } | |||
| p { padding:0px; margin:0px 0px 20px; } | |||
| img { padding:0px; margin:0px 0px 20px; border:none; } | |||
| p img, pre img, tt img, li img, h1 img, h2 img { margin-bottom:0px; } | |||
| ul { padding:0px; margin:0px 0px 20px 23px; list-style:square; } | |||
| ul li { padding:0px; margin:0px 0px 7px 0px; } | |||
| ul li ul { padding:5px 0px 0px; margin:0px 0px 7px 23px; } | |||
| ul li ol li { list-style:decimal; } | |||
| ol { padding:0px; margin:0px 0px 20px 0px; list-style:decimal; } | |||
| ol li { padding:0px; margin:0px 0px 7px 23px; list-style-type:decimal; } | |||
| ol li ol { padding:5px 0px 0px; margin:0px 0px 7px 0px; } | |||
| ol li ol li { list-style-type:lower-alpha; } | |||
| ol li ul { padding-top:7px; } | |||
| ol li ul li { list-style:square; } | |||
| .content { font-size:1.2em; line-height:140%; padding: 20px; } | |||
| pre, code { font-size:12px; } | |||
| tt { font-size: 1.2em; } | |||
| pre { margin:0px 0px 20px; } | |||
| pre.codeinput { padding:10px; border:1px solid #d3d3d3; background:#f7f7f7; } | |||
| pre.codeoutput { padding:10px 11px; margin:0px 0px 20px; color:#4c4c4c; } | |||
| pre.error { color:red; } | |||
| @media print { pre.codeinput, pre.codeoutput { word-wrap:break-word; width:100%; } } | |||
| span.keyword { color:#0000FF } | |||
| span.comment { color:#228B22 } | |||
| span.string { color:#A020F0 } | |||
| span.untermstring { color:#B20000 } | |||
| span.syscmd { color:#B28C00 } | |||
| .footer { width:auto; padding:10px 0px; margin:25px 0px 0px; border-top:1px dotted #878787; font-size:0.8em; line-height:140%; font-style:italic; color:#878787; text-align:left; float:none; } | |||
| .footer p { margin:0px; } | |||
| .footer a { color:#878787; } | |||
| .footer a:hover { color:#878787; text-decoration:underline; } | |||
| .footer a:visited { color:#878787; } | |||
| table th { padding:7px 5px; text-align:left; vertical-align:middle; border: 1px solid #d6d4d4; font-weight:bold; } | |||
| table td { padding:7px 5px; text-align:left; vertical-align:top; border:1px solid #d6d4d4; } | |||
| </style></head><body><div class="content"><pre class="codeinput"><span class="keyword">classdef</span> Channel | |||
| <span class="comment">% CHANNEL is the class for one channel of the oscilloscope. Multiple</span> | |||
| <span class="comment">% settings for the different channels of the oscilloscope can be changed</span> | |||
| <span class="comment">% via this class definition</span> | |||
| <span class="keyword">properties</span> (Hidden, Access = private) | |||
| scope <span class="comment">% Contains the class of the scope that is parent of this channel.</span> | |||
| channelnumber <span class="comment">% is the number of the channel on the scope.</span> | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">properties</span> (Dependent) | |||
| state | |||
| coupling | |||
| bandwidth | |||
| scale | |||
| offset | |||
| probe | |||
| label | |||
| type | |||
| probeunit | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">methods</span> | |||
| <span class="keyword">function</span> ch = Channel(scope,channelnumber) | |||
| ch.channelnumber = channelnumber; | |||
| ch.scope = scope; | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> s = get.state(ch) | |||
| s = ch.CHAN(<span class="string">'state?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.coupling(ch) | |||
| out = ch.CHAN(<span class="string">'coup?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.bandwidth(ch) | |||
| out = ch.CHAN(<span class="string">'band?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.offset(ch) | |||
| out = ch.CHAN(<span class="string">'offs?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.scale(ch) | |||
| out = ch.CHAN(<span class="string">'scal?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.label(ch) | |||
| out = ch.CHAN(<span class="string">'lab?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.type(ch) | |||
| out = ch.CHAN(<span class="string">'type?'</span>); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.probeunit(ch) | |||
| out = ch.scope.query([<span class="string">'PROB'</span>,num2str(ch.channelnumber),<span class="string">':SET:ATT:UNIT?'</span>]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = get.probe(ch) | |||
| out = ch.scope.query([<span class="string">'PROB'</span>,num2str(ch.channelnumber),<span class="string">':SET:ATT:MAN?'</span>]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.state(ch,in) | |||
| ch.CHAN(<span class="string">'state'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.coupling(ch,in) | |||
| ch.CHAN(<span class="string">'coup'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.bandwidth(ch,in) | |||
| ch.CHAN(<span class="string">'band'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.offset(ch,in) | |||
| ch.CHAN(<span class="string">'offs'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.scale(ch,in) | |||
| ch.CHAN(<span class="string">'scal'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.label(ch,in) | |||
| ch.CHAN(<span class="string">'lab'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.type(ch,in) | |||
| ch.CHAN(<span class="string">'type'</span>,in); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = frequency(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'freq'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = peak2peak(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'peak'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = period(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'per'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = amplitude(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'ampl'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = mean(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'mean'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = rms(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'rms'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> out = phase(ch) | |||
| out = str2double(ch.MEAS(<span class="string">'phas'</span>)); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.probeunit(ch,unit) | |||
| ch.scope.write([<span class="string">'PROB'</span>,num2str(ch.channelnumber),<span class="string">':SET:ATT:UNIT '</span>, unit]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> ch = set.probe(ch,man) | |||
| ch.scope.write([<span class="string">'PROB'</span>,num2str(ch.channelnumber),<span class="string">':SET:ATT:MAN '</span>, man]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> data = waveform(ch,window) | |||
| ch.scope.single; | |||
| <span class="keyword">if</span> nargin < 2 | |||
| window = <span class="string">'DEF'</span>; | |||
| <span class="keyword">end</span> | |||
| ch.scope.setWaveformSettings(window,<span class="string">'REAL'</span>) | |||
| data = ch.getWaveform; | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> data = getWaveform(ch) | |||
| header = str2num(ch.CHAN(<span class="string">'DATA:HEAD?'</span>)); | |||
| data.length = header(3); | |||
| data.start = header(1); | |||
| data.stop = header(2); | |||
| data.sampletime = str2double(ch.CHAN(<span class="string">'DATA:XINC?'</span>)); | |||
| ch.scope.opc; | |||
| ch.scope.write_unsafe([<span class="string">'CHAN'</span>,num2str(ch.channelnumber),<span class="string">':DATA?'</span>]); | |||
| data.data = ch.scope.readWaveform(data.length); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">methods</span> (Hidden, Access = private) | |||
| <span class="keyword">function</span> c = CHAN(ch,string,in) | |||
| <span class="keyword">if</span> nargin == 2 | |||
| <span class="keyword">if</span> strcmp(string(end),<span class="string">'?'</span>) | |||
| c = ch.scope.query([<span class="string">'CHAN'</span>,num2str(ch.channelnumber),<span class="string">':'</span>,string]); | |||
| <span class="keyword">else</span> | |||
| ch.scope.write([<span class="string">'CHAN'</span>,num2str(ch.channelnumber),<span class="string">':'</span>,string]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">else</span> | |||
| ch.scope.write([<span class="string">'CHAN'</span>,num2str(ch.channelnumber),<span class="string">':'</span>,string,<span class="string">' '</span>,in]); | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">function</span> c = MEAS(ch,string) | |||
| c = ch.scope.query([<span class="string">'MEAS'</span>,num2str(ch.channelnumber),<span class="string">':RES:ACT?'</span>,string]); | |||
| <span class="keyword">end</span> | |||
| <span class="comment">% function c = CHANsend(ch,string,in)</span> | |||
| <span class="comment">% c = ['CHAN',num2str(ch.channelnumber),':',string,' ',in];</span> | |||
| <span class="comment">% end</span> | |||
| <span class="keyword">end</span> | |||
| <span class="keyword">end</span> | |||
| </pre><pre class="codeoutput error">Not enough input arguments. | |||
| Error in Channel (line 24) | |||
| ch.channelnumber = channelnumber; | |||
| </pre><p class="footer"><br><a href="https://www.mathworks.com/products/matlab/">Published with MATLAB® R2018a</a><br></p></div><!-- | |||
| ##### SOURCE BEGIN ##### | |||
| 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 | |||
| ##### SOURCE END ##### | |||
| --></body></html> | |||