classdef MicroPulse5 < handle % MicroPulse5 Control class for the Peak NDT MicroPulse 5 unit (version 0.1020140721). % Simplifies external PC control for the Peak NDT MicroPulse 5 unit. % This documentation is not complete. If adding to the documentation, please follow the format described in: % http://www.mathworks.co.uk/help/matlab/matlab_prog/create-help-for-classes.html % % MicroPulse5 Copyright: % % Copyright (c) 2014, Phillip Anthony Petcher % All rights reserved. % % Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: % % - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. % - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. % % MicroPulse5 Properties: % Message - (get only) - the last message read from the MicroPulse that wasn't discarded. % ResetInfo - (get only) - reset information. % StatusInfo - (get only) - status and axis locations. % UltrasonicParametersInfo - (get only) - the ultrasonic parameters for a specified test. % SweepParametersInfo - (get only) - the sweep parameters for a specified sweep. % TransmitLawsInfo - (get only) - the transmit focal law parameters for a specified test. % ReceiveLawsInfo - (get only) - the receive focal law parameters for a specified test. % Connected - (get only) - if a MicroPulse unit is currently connected. Connected (boolean) = true or false % Port - (get only) - the TCPIP port object for the MicroPulse connection. % % MicroPulse5 Methods: % MicroPulse5(Ip,Port) - constructs the control class, and connects to the MicroPulse on the specified IP address and Port. Ip must be a valid IPv4 address, and Port must be the associated port to connect on. % delete(obj) - destructs the control class, and disconnects the MicroPulse from the port. % Connect(Ip,Port) - connects to the MicroPulse on the specified IP address and port (it will disconnect first if already connected). Ip must be a valid IPv4 address, and Port must be the associated port to connect on. % Disconnect() - disconnects the MicroPulse from the port. % Write(Command) - writes a command to the MicroPulse. % Read(Header) - reads data received from the MicroPulse. % Reset(SoftReset,SampleFrequency) - resets the MicroPulse and optionally changes the sample frequency (the sample frequency snaps to the nearest available sample frequency). The reset information is read afterwards. % ResetParameters() - reads the reset information. % DefaultSampleFrequency(SampleFrequency,DataFormat) - sets the MicroPulse default sample frequency (the sample frequency snaps to the nearest available sample frequency) and optionally changes the output message format. % DataOutputFormat(DataFormat) - sets the MicroPulse output message format. % FrequencyFilter(TestNo,FreqFilter,Smoothing,TrueForSweep) - sets the required band-pass filter and the level of smoothing required on rectified waveforms. % Gain(TestNo,GainDecibels,TrueForSweep) - sets the absolute gain for the test/sweep specified. % PulserWidth(ChannelStart,ChannelEnd,PulseTime) - sets the pulser width for the specified range of channels. % PulserVoltage(ChannelStart,ChannelEnd,Voltage) - sets the pulser voltage for the specified range of channels. % PulseRepetitionFrequency(Rate) - changes the pulse repetition frequency. % IdleMode() - puts the MicroPulse into idle mode, with no tests being performed. % PerformTestsContinuously(TestNo,TrueForSweep) - performs the test/sweep specified continuously, at the specified pulse repetition frequency, until IdleMode is used. The data is output after a full cycle of the requested tests has been performed. % Status() - requests the MicroPulse status and axis locations. % UltrasonicParameters(TestNo) - requests the MicroPulse ultrasonic parameters for a specified test. % SweepParameters(SweepNo) - requests the MicroPulse sweep parameters for a specified sweep. % TransmitLawParameters(Law) - requests the MicroPulse transmit tests for a specified law. % ReceiveLawParameters(Law) - requests the MicroPulse receive tests for a specified law. % FullMatrixCapture(Elements,GainDecibels,FreqFilter,PulseTime,Voltage,Rate) - configures the MicroPulse for full matrix capture (FMC). % FullMatrixCaptureRead(Elements,TestNo) - reads a full matrix capture (FMC) scan acquired by the MicroPulse (the assumption of DOF 1 is made). % FullMatrixCaptureReadFast(obj,Elements,TestNo) - reads a full matrix capture (FMC) scan acquired by the MicroPulse, with some optimisation to improve the read speed. % FullMatrixCaptureSave(Directory,Header) - saves a full matrix capture (FMC) scan previously read with FullMatrixCaptureRead, with the file name YYYYMMDDhhmmsssss.dat and optionally YYYYMMDDhhmmsssss.xml for the header. %% MicroPulse5 properties - only get methods available. properties (SetAccess = private) Fmc; % (NOT USER SETTABLE - USE FullMatrixCaptureRead METHOD) The last full matrix capture (FMC) read from the MicroPulse. FmcElements; % (NOT USER SETTABLE - USE FullMatrixCapture METHOD) The number of elements forming the full matrix capture (FMC). FmcWidth; % (NOT USER SETTABLE - USE FullMatrixCapture METHOD) The pulse width when performing the full matrix capture (FMC). FmcVoltage; % (NOT USER SETTABLE - USE FullMatrixCapture METHOD) The transducer voltage when performing the full matrix capture (FMC). Message; % (NOT USER SETTABLE - USE Read METHOD) The last message read from the MicroPulse that wasn't discarded. ResetInfo; % (NOT USER SETTABLE - USE Reset METHOD) Reset information. StatusInfo; % (NOT USER SETTABLE - USE Status METHOD) Status and axis locations. UltrasonicParametersInfo; % (NOT USER SETTABLE - USE UltrasonicParameters METHOD) The ultrasonic parameters for a specified test. SweepParametersInfo; % (NOT USER SETTABLE - USE SweepParameters METHOD) The sweep parameters for a specified sweep. TransmitLawsInfo; % (NOT USER SETTABLE - USE TransmitLawParameters METHOD) The transmit focal law parameters for a specified test. ReceiveLawsInfo; % (NOT USER SETTABLE - USE ReceiveLawParameters METHOD) The receive focal law parameters for a specified test. Connected = false; % (NOT USER SETTABLE - USE CONSTRUCTOR/DESTRUCTOR OR Connect AND Disconnect METHODS) If a MicroPulse unit is currently connected. Connected (boolean) = true or false Port = []; % (NOT USER SETTABLE - USE CONSTRUCTOR/DESTRUCTOR OR Connect AND Disconnect METHODS) The TCPIP object for the MicroPulse connection. end %% MicroPulse5 properties - internal class use only. properties (SetAccess = private, GetAccess = private) Logging = false; % If command logging is enabled. LoggingFid = 1; % The file ID for command logging. end %% Public methods (accessible by users of the class) methods %% Constructor function obj = MicroPulse5(Ip,Port,Logging) % Constructs the control class, and connects to the MicroPulse on the specified IP address and port. % IP must be a valid IPv4 address, and Port must be the associated port to connect on. % Logging is true if all commands sent to the MicroPulse should be logged in the file "MicroPulse5Log.txt". if (nargin < 1) || isempty(Ip) Ip = '10.1.1.2'; end if (nargin < 2) || isempty(Port) Port = 1067; end if (nargin > 2) && ~isempty(Logging) && Logging obj.Logging = Logging; end obj.Connect(Ip,Port); end %% Destructor function delete(obj) % Destructs the control class, and disconnects the MicroPulse from the port. Disconnect(obj); delete(obj.Port); if obj.Logging && (obj.LoggingFid > 2) Status = fclose(obj.LoggingFid); if Status warning('MicroPulse5:FileOperationFailure',Status); end end end %% Public methods function Connect(obj,Ip,Port) % Connects to the MicroPulse on the specified IP address and port (it will disconnect first if already connected). % Ip must be a valid IPv4 address, and Port must be the associated port to connect on. Valid = false; Dots = find(Ip == '.'); if length(Dots) == 3 One = sscanf(Ip(1:1:(Dots(1)-1)),'%u'); Two = sscanf(Ip((Dots(1)+1):1:(Dots(2)-1)),'%u'); Three = sscanf(Ip((Dots(2)+1):1:(Dots(3)-1)),'%u'); Four = sscanf(Ip((Dots(3)+1):1:end),'%u'); if (One < 256) && (Two < 256) && (Three < 256) && (Four < 256) Ip = sprintf('%u.%u.%u.%u',One,Two,Three,Four); if (Port >= 0) && (Port <= 65536) Valid = true; end end end if obj.Connected obj.Disconnect(); obj.Connect(Ip,Port); elseif Valid obj.Port = tcpip(Ip,Port,'InputBufferSize',2^26,'Timeout',30); fopen(obj.Port); obj.Connected = true; else error('MicroPulse5:PortIncorrect','The port entered for the MicroPulse remote control is outside of valid bounds.'); end end function Disconnect(obj) % Disconnects the MicroPulse from the port. fclose(obj.Port); obj.Connected = false; end function Write(obj,Command) % Writes a command to the MicroPulse. % Command is the desired command as a string. The carriage return is added by the function. obj.ConnectedCheck; fprintf(obj.Port,'%s\r',Command); if obj.Logging if obj.LoggingFid < 3 [obj.LoggingFid, Status] = fopen('MicroPulse5Log.txt','a'); if obj.LoggingFid < 3 warning('MicroPulse5:FileOperationFailure',Status); else fprintf(obj.LoggingFid,'%s\r',Command); end else fprintf(obj.LoggingFid,'%s\r',Command); end end end function Read(obj,Header,Delay,Tries) % Reads data received from the MicroPulse. % Header (optional) is the header number being looked for, with other messages being discarded. Do not enter a value if all messages should be retained. % Delay (optional) is the time to pause for (in seconds) before checking if there are any bytes available to read. % Tries (optional) is the number of times that the system will pause with no bytes available before stopping the read. obj.ConnectedCheck; if (nargin < 3) || isempty(Delay) Delay = 0; end if (nargin < 4) || isempty(Tries) Tries = 1; end obj.Message = []; while (Tries > 0) && isempty(obj.Message) Tries = Tries - 1; if (nargin > 1) && ~isempty(Header) while (get(obj.Port,'BytesAvailable') > 0) && (isempty(obj.Message) || (obj.Message.Header ~= Header)) obj.Message = MicroPulse5Read(obj.Port); end if ~isempty(obj.Message) && (obj.Message.Header ~= Header) obj.Message = []; end else if get(obj.Port,'BytesAvailable') > 0 obj.Message = MicroPulse5Read(obj.Port); end end if (Tries > 0) && isempty(obj.Message) pause(Delay); end end end function Reset(obj,SoftReset,SampleFrequency) % Resets the MicroPulse and optionally changes the sample frequency (the sample frequency snaps to the nearest available sample frequency). The reset information is read afterwards. % SoftReset (optional) is true if only a soft reset is to be performed, set it to false or leave it blank for a hard reset. % SampleFrequency (optional) is the sampling frequency used in MHz. The available options are 10MHz, 25MHz, 50MHz, and 100MHz. Type = 'RST'; if (nargin > 1) && ~isempty(SoftReset) && SoftReset Type = 'SRST'; end Freq = []; if nargin > 2 if SampleFrequency <= 0.0 warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); elseif SampleFrequency < 17.5 Freq = ' 10'; elseif SampleFrequency < 37.5 Freq = ' 25'; elseif SampleFrequency < 75.0 Freq = ' 50'; else Freq = ' 100'; end end obj.Write([Type Freq]); obj.Read(35,1,50); obj.ResetInfo = obj.Message; end function ResetParameters(obj) % Reads the reset information. obj.Write('STS -1'); obj.Read(35,0.1,10); obj.ResetInfo = obj.Message; end function DefaultSampleFrequency(obj,SampleFrequency,DataFormat) % Sets the MicroPulse default sample frequency (the sample frequency snaps to the nearest available sample frequency) and optionally changes the output message format. % SampleFrequency is the sampling frequency used in MHz. The available options are 10MHz, 25MHz, 50MHz, and 100MHz. % DataFormat (optional) is the data output format used (see the manual). if SampleFrequency <= 0.0 Freq = '50'; warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); elseif SampleFrequency < 17.5 Freq = '10'; elseif SampleFrequency < 37.5 Freq = '25'; elseif SampleFrequency < 75.0 Freq = '50'; else Freq = '100'; end Frmt = []; if nargin > 2 switch DataFormat case 0 Frmt = ' 0'; case 1 Frmt = ' 1'; case 2 Frmt = ' 2'; case 3 Frmt = ' 3'; case 4 Frmt = ' 4'; case 5 Frmt = ' 5'; case 6 Frmt = ' 6'; otherwise warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end obj.Write(['SDS ' Freq Frmt]); end function DataOutputFormat(obj,DataFormat) % Sets the MicroPulse output message format. % DataFormat is the data output format used (see the manual). switch DataFormat case 0 Frmt = '0'; case 1 Frmt = '1'; case 2 Frmt = '2'; case 3 Frmt = '3'; case 4 Frmt = '4'; case 5 Frmt = '5'; case 6 Frmt = '6'; otherwise Frmt = []; warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end if ~isempty(Frmt) obj.Write(['DOF ' Frmt]); end end function FrequencyFilter(obj,TestNo,FreqFilter,Smoothing,TrueForSweep) % Sets the required band-pass filter and the level of smoothing required on rectified waveforms. % TestNo is the test or sweep number. % FreqFilter is the filter choice (see the manual). % Smoothing is the level of smoothing on the rectified waveform (see the manual). % TrueForSweep should be set to true if the command is to be applied to a sweep, and set to false if the command is to be applied to a test. if (nargin > 4) && ~isempty(TrueForSweep) && TrueForSweep ModeString = 'FRQS '; else ModeString = 'FRQ '; TrueForSweep = false; end if (TestNo >= 0) && ((~TrueForSweep && (TestNo <= 1279)) || (TrueForSweep && (TestNo <= 16))) TestNoString = sprintf('%u',floor(TestNo + 0.5)); if (FreqFilter >= 1) && ((~TrueForSweep && (FreqFilter <= 12)) || (TrueForSweep && (FreqFilter <= 4))) FreqFilterString = sprintf('%u',floor(FreqFilter + 0.5)); if (Smoothing >= 1) && (Smoothing <= 8) SmoothingString = sprintf('%u',floor(Smoothing + 0.5)); obj.Write([ModeString TestNoString ' ' FreqFilterString ' ' SmoothingString]); else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function Gain(obj,TestNo,GainDecibels,TrueForSweep) % Sets the absolute gain for the test/sweep specified. % TestNo is the test or sweep number, between 1 and 1279 for a test, and between 1 and 16 for a sweep. % GainDecibels is the gain (in decibels) that should be applied to the received signals, 0-70db. % TrueForSweep should be set to true if the command is to be applied to a sweep, and set to false if the command is to be applied to a test. if (nargin > 3) && ~isempty(TrueForSweep) && TrueForSweep ModeString = 'GANS '; else ModeString = 'GAN '; TrueForSweep = false; end if (TestNo >= 0) && ((~TrueForSweep && (TestNo <= 1279)) || (TrueForSweep && (TestNo <= 16))) TestNoString = sprintf('%u',floor(TestNo + 0.5)); if (GainDecibels >= 0) && (GainDecibels <= 70) GainString = sprintf('%u',floor(GainDecibels * 4.0 + 0.5)); obj.Write([ModeString TestNoString ' ' GainString]); else warning('MicroPulse:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse:ParameterIncorrect','A parameter was incorrect.'); end end function PulserWidth(obj,ChannelStart,ChannelEnd,PulseTime) % Sets the pulser width for the specified range of channels. % ChannelStart is the start channel number. % ChannelEnd is the end channel number. % PulseTime is the pulser width required, 20-500ns in 2ns steps. if (ChannelStart >= 1) && (ChannelStart <= 128) StartString = sprintf('%u',floor(ChannelStart + 0.5)); if (ChannelEnd >= ChannelStart) && (ChannelEnd <= 128) EndString = sprintf('%u',floor(ChannelEnd + 0.5)); if (PulseTime >= 20) && (PulseTime <= 500) PulseTimeString = sprintf('%u',floor(PulseTime/2 + 0.5)*2); obj.Write(['PAW ' StartString ' ' EndString ' ' PulseTimeString]); else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function PulserVoltage(obj,ChannelStart,ChannelEnd,Voltage) % Sets the pulser voltage for the specified range of channels. % ChannelStart is the start channel number. % ChannelEnd is the end channel number. % Voltage is the pulser voltage required, 50-200V in 5V steps. if (ChannelStart >= 1) && (ChannelStart <= 128) StartString = sprintf('%u',floor(ChannelStart + 0.5)); if (ChannelEnd >= ChannelStart) && (ChannelEnd <= 128) EndString = sprintf('%u',floor(ChannelEnd + 0.5)); if (Voltage >= 50) && (Voltage <= 200) VoltageString = sprintf('%u',floor(Voltage/5 + 0.5)*5); obj.Write(['PAV ' StartString ' ' EndString ' ' VoltageString]); else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function PulseRepetitionFrequency(obj,Rate) % Changes the pulse repetition frequency. % Rate is the firing rate in Hz, which is accurate provided that the rate specified is not greater than the MicroPulse can achieve or the ultrasonics will allow. if (Rate >= 1) && (Rate <= 20000) obj.Write(['PRF ' sprintf('%u',floor(Rate + 0.5))]); else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function IdleMode(obj) % Puts the MicroPulse into idle mode, with no tests being performed. obj.Write('STX'); end function PerformTestsContinuously(obj,TestNo,TrueForSweep) % Performs the test/sweep specified continuously, at the specified pulse repetition frequency, until IdleMode is used. The data is output after a full cycle of the requested tests has been performed. % TestNo is the test or sweep number, between 1 and 1279 for a test, and between 1 and 16 for a sweep. % TrueForSweep should be set to true if the command is to be applied to a sweep, and set to false if the command is to be applied to a test. if (nargin > 2) && ~isempty(TrueForSweep) && TrueForSweep ModeString = 'STPS '; else ModeString = 'STP '; TrueForSweep = false; end if (TestNo >= 0) && ((~TrueForSweep && (TestNo <= 1279)) || (TrueForSweep && (TestNo <= 16))) TestNoString = sprintf('%u',floor(TestNo + 0.5)); obj.Write([ModeString TestNoString]); else warning('MicroPulse:ParameterIncorrect','A parameter was incorrect.'); end end function Status(obj) % Requests the MicroPulse status and axis locations. obj.Write('STA'); obj.Read(21,0.1,10); obj.StatusInfo = obj.Message; end function UltrasonicParameters(obj,TestNo) % Requests the MicroPulse ultrasonic parameters for a specified test. % TestNo is the test number between 1 and 1279. if (TestNo >= 1) && (TestNo <= 1279) TestNoString = sprintf('%u',floor(TestNo + 0.5)); obj.Write(['XXA ' TestNoString]); obj.Read(32,0.1,10); obj.UltrasonicParametersInfo = obj.Message; else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function SweepParameters(obj,SweepNo) % Requests the MicroPulse sweep parameters for a specified sweep. % SweepNo is the sweep number between 1 and 16. if (SweepNo >= 1) && (SweepNo <= 16) SweepNoString = sprintf('%u',floor(SweepNo + 0.5)); obj.Write(['XXAS ' SweepNoString]); obj.Read(33,0.1,10); obj.SweepParametersInfo = obj.Message; else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function TransmitLawParameters(obj,Law) % Requests the MicroPulse transmit tests for a specified law. % Law is the test number between 1 and 1024. if (Law >= 1) && (Law <= 1024) LawString = sprintf('%u',floor(Law + 0.5)); obj.Write(['XXT ' LawString]); obj.Read(34,0.1,10); obj.TransmitLawsInfo = obj.Message; else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function ReceiveLawParameters(obj,Law) % Requests the MicroPulse receive tests for a specified law. % TestNo is the test number between 1 and 1024. if (Law >= 1) && (Law <= 1024) LawString = sprintf('%u',floor(Law + 0.5)); obj.Write(['XXR ' LawString]); obj.Read(34,0.1,10); obj.ReceiveLawsInfo = obj.Message; else warning('MicroPulse5:ParameterIncorrect','A parameter was incorrect.'); end end function FullMatrixCapture(obj,Elements,GainDecibels,FreqFilter,PulseTime,Voltage,Rate) % Configures the MicroPulse for full matrix capture (FMC). % Elements is the number of elements the transducer has. % GainDecibels is the gain (in decibels) that should be applied to the received signals, 0-70db. % FreqFilter is the filter choice (see the manual). % PulseTime is the pulser width required, 20-500ns in 2ns steps. % Voltage is the pulser voltage required, 50-200V in 5V steps. % Rate is the firing rate in Hz, which is accurate provided that the rate specified is not greater than the MicroPulse can achieve or the ultrasonics will allow. obj.FmcElements = Elements; NumberStrings(255 + Elements).String = []; for ElementT = 1:1:Elements NumberStrings(ElementT).String = sprintf('%u',ElementT); NumberStrings(255 + ElementT).String = sprintf('%u',255 + ElementT); end % Please note that it is not entirely clear which of these commands are essential for FMC operation. Those that definitely are needed include TXF, TXN, RXF, RXN, GATS, AMPS, AWFS. % TXF - Defines the element delay for a transmit focal law - for each focal law, a number of TXF commands define the transmit delays for each individual element used. % TTD - Trims the transmit focal law - corrects the transmit focal law delay to make the reference point as the array centre. % TXN - Transmit channel select - selects the transmit probe connection for a given test. % RXF - Defines the element delay for a receive focal law - for each focal law, a number of RXF commands define the receive delays for each individual element used. The gain of an individual element can also be trimmed. % RTD - Trims the receive focal law - corrects the receive focal law delay to make the reference point as the array centre. % RXN - Receiver channel select - selects the receiver probe connection for a given test. % SWP - Defines a group of focal laws - phased array tests can be grouped together to form sweeps (ultrasonic settings can be set for the whole sweep by adding an "S" to the command). % DLY(S) - Delay - offset timing measurements to compensate for travel time through the probe shoe. % TRM(S) - Trim the delay - trims the delay to correct for transit time in the wedge when different angles are generated. % GAT(S) - Search gate - defines search gate start and end positions for the specified test. % ETM(S) - Echo trigger mode - use 0 for normal triggering. % DTG(S) - DAC trigger source - use 0 to trigger DAC on initial pulse. % AMP(S) - Selects amplitude reporting mode - use 13 for FMC (the gate size is limited to 3000 sample points per channel for each transducer firing, but gates of up to 8000 samples per channel are achievable if the system fires multiple times). % AWF(S) - Analogue waveform switch - use 1 to display and process full RF signal. % SGA(S) - Phased array channel summing gain - use 0 to turn off. % ENA(S) - Enable - enables specified test. % DCM(S) - Data compression algorithm - use 0 to turn off. % OLM(S) - overload reporting mode on a phased array test - report the saturation of individual phased array elements. for ElementT = 1:1:Elements obj.Write(['TXF ' NumberStrings(ElementT).String ' 0 -1']); obj.Write(['TXF ' NumberStrings(ElementT).String ' ' NumberStrings(ElementT).String ' 0']); obj.Write(['TTD ' NumberStrings(ElementT).String ' 0']); obj.Write(['TXN ' NumberStrings(255 + ElementT).String ' ' NumberStrings(ElementT).String]); obj.Write(['RXF ' NumberStrings(ElementT).String ' 0 -1 0']); for ElementR = 1:1:Elements obj.Write(['RXF ' NumberStrings(ElementT).String ' ' NumberStrings(ElementR).String ' 0 0']); end obj.Write(['RTD ' NumberStrings(ElementT).String ' 0']); obj.Write(['RXN ' NumberStrings(255 + ElementT).String ' ' NumberStrings(ElementT).String]); end obj.Write(['SWP 1 256 - ' NumberStrings(255 + Elements).String]); obj.Write('DLYS 1 0'); obj.Write('TRMS 1 0'); obj.Write('GATS 1 0 3000'); obj.Write('ETMS 1 0'); obj.Write('DTGS 1 0'); obj.Write('AMPS 1 13'); obj.Write('AWFS 1 1'); obj.Write('SGAS 1 0'); obj.Write('ENAS 1'); obj.Write('DCMS 1 0'); obj.Write('OLMS 1 0 128'); if (nargin > 2) && ~isempty(GainDecibels) obj.Gain(1,GainDecibels,true); end if (nargin > 3) && ~isempty(FreqFilter) obj.FrequencyFilter(1,FreqFilter,1,true); end if (nargin > 4) && ~isempty(PulseTime) obj.FmcWidth = PulseTime; obj.PulserWidth(1,Elements,PulseTime); end if (nargin > 5) && ~isempty(Voltage) obj.FmcVoltage = Voltage; obj.PulserVoltage(1,Elements,Voltage); end if (nargin > 6) && ~isempty(Rate) obj.PulseRepetitionFrequency(Rate); end end function FullMatrixCaptureRead(obj,Elements,TestNo) % Reads a full matrix capture (FMC) scan acquired by the MicroPulse (the assumption of DOF 1 is made). % Elements is the number of elements the transducer has. % TestNo is the test number between 255 and 1023 that the FMC starts at (leave at the default if set up using obj.FullMatrixCapture). if (nargin > 2) && ~isempty(TestNo) TestNoCurrent = TestNo; else TestNoCurrent = 255; end Transmitter = 1; Receiver = 1; obj.Read(26,0.1,10); if isempty(obj.Message) || (obj.Message.Channel ~= Receiver) || (obj.Message.Test ~= TestNoCurrent) warning('MicroPulse5:FmcReadFailure',['Unable to read test ' sprintf('%u',TestNoCurrent) ' channel ' sprintf('%u',Receiver) '.']); return; end obj.Fmc = zeros(length(obj.Message.Amplitudes),Elements,Elements); obj.Fmc(:,Receiver,Transmitter) = obj.Message.Amplitudes - 128; for Receiver = 2:1:Elements obj.Read(26,0.1,10); if isempty(obj.Message) || (obj.Message.Channel ~= Receiver) || (obj.Message.Test ~= TestNoCurrent) warning('MicroPulse5:FmcReadFailure',['Unable to read test ' sprintf('%u',TestNoCurrent) ' channel ' sprintf('%u',Receiver) '.']); return; end obj.Fmc(:,Receiver,Transmitter) = obj.Message.Amplitudes - 128; end for Transmitter = 2:1:Elements TestNoCurrent = TestNoCurrent + 1; for Receiver = 1:1:Elements obj.Read(26,0.1,10); if isempty(obj.Message) || (obj.Message.Channel ~= Receiver) || (obj.Message.Test ~= TestNoCurrent) warning('MicroPulse5:FmcReadFailure',['Unable to read test ' sprintf('%u',TestNoCurrent) ' channel ' sprintf('%u',Receiver) '.']); return; end obj.Fmc(:,Receiver,Transmitter) = obj.Message.Amplitudes - 128; end end end function FullMatrixCaptureReadFast(obj,Elements,TestNo) % Reads a full matrix capture (FMC) scan acquired by the MicroPulse, with some optimisation to improve the read speed. % Elements is the number of elements the transducer has. % TestNo is the test number between 255 and 1023 that the FMC starts at (leave at the default if set up using obj.FullMatrixCapture). if (nargin < 3) || isempty(TestNo) TestNo = 255; end obj.Read(26,0.1,50); if isempty(obj.Message) || (obj.Message.Channel ~= 1) || (obj.Message.Test ~= TestNo) warning('MicroPulse5:FmcReadFailure',['Unable to read test ' sprintf('%u',TestNo) ' channel ' sprintf('%u',1) '.']); return; end Amplitudes = obj.Message.Amplitudes; AmplitudesMiddle = []; for Tries = 1:1:100 if get(obj.Port,'BytesAvailable') >= ((Elements * Elements - 2) * obj.Message.Count) if (obj.Message.DataFormat == 0) || (obj.Message.DataFormat == 1) || (obj.Message.DataFormat == 5) AmplitudesMiddle = reshape(fread(obj.Port,(Elements * Elements - 2) * obj.Message.Count,'uint8'),obj.Message.Count,Elements * Elements - 2); elseif (obj.Message.DataFormat == 2) || (obj.Message.DataFormat == 3) || (obj.Message.DataFormat == 4) AmplitudesMiddle = reshape(fread(obj.Port,(Elements * Elements - 2) * obj.Message.Count / 2,'int16'),obj.Message.Count / 2,Elements * Elements - 2); elseif obj.Message.DataFormat == 6 warning('MicroPulse5:IncompleteImplementation','A failure has occurred due to the incomplete implementation of the MicroPulse5 class.'); else warning('MicroPulse5:ReadFailure','Message format not as expected.'); end break; end pause(0.1); end if ~isempty(AmplitudesMiddle) obj.Read(26,0.1,50); if isempty(obj.Message) || (obj.Message.Channel ~= Elements) || (obj.Message.Test ~= (TestNo + Elements - 1)) warning('MicroPulse5:FmcReadFailure',['Unable to read test ' sprintf('%u',(TestNo + Elements - 1)) ' channel ' sprintf('%u',Elements) '.']); return; end switch obj.Message.DataFormat case 0 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(9:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements); warning('MicroPulse5:IncompleteImplementation','Reading this DOF mode has not been verified to work.'); case 1 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(9:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements) - 128; case 5 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(9:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements) - 512; warning('MicroPulse5:IncompleteImplementation','Reading this DOF mode has not been verified to work.'); case 2 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(5:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements); warning('MicroPulse5:IncompleteImplementation','Reading this DOF mode has not been verified to work.'); case 3 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(5:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements); warning('MicroPulse5:IncompleteImplementation','Reading this DOF mode has not been verified to work.'); case 4 obj.Fmc = reshape([Amplitudes AmplitudesMiddle(5:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements); warning('MicroPulse5:IncompleteImplementation','Reading this DOF mode has not been verified to work.'); case 6 warning('MicroPulse5:IncompleteImplementation','A failure has occurred due to the incomplete implementation of the MicroPulse5 class.'); otherwise warning('MicroPulse5:ReadFailure','Message format not as expected.'); end % if (obj.Message.DataFormat == 0) || (obj.Message.DataFormat == 1) || (obj.Message.DataFormat == 5) % obj.Fmc = reshape([Amplitudes AmplitudesMiddle(9:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements) - 128; % elseif (obj.Message.DataFormat == 2) || (obj.Message.DataFormat == 3) || (obj.Message.DataFormat == 4) % obj.Fmc = reshape([Amplitudes AmplitudesMiddle(5:1:end,:) obj.Message.Amplitudes],obj.Message.DataPoints,Elements,Elements) - 32768; % elseif obj.Message.DataFormat == 6 % warning('MicroPulse5:IncompleteImplementation','A failure has occurred due to the incomplete implementation of the MicroPulse5 class.'); % else % warning('MicroPulse5:ReadFailure','Message format not as expected.'); % end else warning('MicroPulse5:FmcReadFailure','Unable to read tests.'); end end function FullMatrixCaptureSave(obj,Directory) % Saves a full matrix capture (FMC) scan previously read with FullMatrixCaptureRead, with the file name format YYYYMMDDhhmmsssss.dat. if ~isempty(obj.Fmc) if (nargin < 2) || isempty(Directory) Directory = []; elseif Directory(end) ~= '\' Directory(end+1) = '\'; end DateVector = datevec(now); [Fid, Status] = fopen([Directory sprintf('%04u%02u%02u%02u%02u',DateVector(1:1:5)) sprintf('%06u',floor(DateVector(6)*10000.0+0.5)) '.dat'],'w'); if Fid < 3 warning('MicroPulse5:FileOperationFailure',Status); return; end fwrite(Fid,floor(obj.Fmc+0.5),'int16'); Status = fclose(Fid); if Status warning('MicroPulse5:FileOperationFailure',Status); return; end end end function FullMatrixCaptureHeader(obj,SweepNo,Directory) % Saves a header file for the current full matrix capture (FMC) settings, with the file name format YYYYMMDDhhmmsssss_Settings.xml. % SweepNo is the sweep number between 1 and 16. if (nargin < 3) || isempty(Directory) Directory = []; elseif Directory(end) ~= '\' Directory(end+1) = '\'; end obj.SweepParameters(SweepNo); obj.UltrasonicParameters(obj.SweepParametersInfo.Test(2)); switch obj.UltrasonicParametersInfo.Filter case 1 FilterStart = '5.00'; FilterEnd = '10.0'; case 2 FilterStart = '2.00'; FilterEnd = '10.0'; case 3 FilterStart = '0.75'; FilterEnd = '5.00'; case 4 FilterStart = '0.75'; FilterEnd = '20.0'; otherwise FilterStart = 'Unknown'; FilterEnd = 'Unknown'; end FmcTimePoints = (obj.UltrasonicParametersInfo.GateEnd - obj.UltrasonicParametersInfo.GateStart); TotalBytes = obj.FmcElements * obj.FmcElements * FmcTimePoints * 2; FirstLine = '\n'; OpenLine = '\n'; CloseLine = ''; DateVector = datevec(now); DateString = [ '\t\n' ... '\t\t' sprintf('%u',DateVector(1)) '\n' ... '\t\t' sprintf('%u',DateVector(2)) '\n' ... '\t\t' sprintf('%u',DateVector(3)) '\n' ... '\t\t' sprintf('%u',DateVector(4)) '\n' ... '\t\t' sprintf('%u',DateVector(5)) '\n' ... '\t\t' sprintf('%1.4f',DateVector(6)) '\n' ... '\t\n']; DataString = [ '\t\n' ... '\t\t' 'int' '\n' ... '\t\t' '16' '\n' ... '\t\t' 'little endian' '\n' ... '\t\t' sprintf('%u',obj.FmcElements) '\n' ... '\t\t' sprintf('%u',FmcTimePoints) '\n' ... '\t\t' sprintf('%u',TotalBytes) '\n' ... '\t\t' 'Receivers 1 to ' sprintf('%u',obj.FmcElements) ' for Transmitter 1, repeated for Transmitter 2 to ' sprintf('%u',obj.FmcElements) '. Stored as 16 bit ints. Total of ' sprintf('%u',TotalBytes) ' bytes.' '\n' ... '\t\n']; ReceiveParametersString = [ '\t\n' ... '\t\t\n' ... '\t\t\t' sprintf('%u',obj.UltrasonicParametersInfo.SampleFrequency) '\n' ... '\t\t\t' 'MHz' '\n' ... '\t\t\n' ... '\t\t\n' ... '\t\t\t' FilterStart '\n' ... '\t\t\t' FilterEnd '\n' ... '\t\t\t' 'MHz' '\n' ... '\t\t\n' ... '\t\t\n' ... '\t\t\t' sprintf('%1.2f',obj.UltrasonicParametersInfo.GainDecibels) '\n' ... '\t\t\t' 'dB' '\n' ... '\t\t\n' ... '\t\t\n' ... '\t\t\t' sprintf('%1.2f',obj.UltrasonicParametersInfo.GateStart / obj.UltrasonicParametersInfo.SampleFrequency) '\n' ... '\t\t\t' sprintf('%1.2f',obj.UltrasonicParametersInfo.GateEnd / obj.UltrasonicParametersInfo.SampleFrequency) '\n' ... '\t\t\t' 'mus' '\n' ... '\t\t\n' ... '\t\n']; TransmitParametersString = ['\t\n' ... '\t\t\n' ... '\t\t\t' sprintf('%u',obj.FmcWidth) '\n' ... '\t\t\t' 'ns' '\n' ... '\t\t\n' ... '\t\t\n' ... '\t\t\t' sprintf('%u',obj.FmcVoltage) '\n' ... '\t\t\t' 'V' '\n' ... '\t\t\n' ... '\t\n']; EntireString = [FirstLine OpenLine DateString DataString ReceiveParametersString TransmitParametersString CloseLine]; [Fid, Status] = fopen([Directory sprintf('%04u%02u%02u%02u%02u',DateVector(1:1:5)) sprintf('%06u',floor(DateVector(6)*10000.0+0.5)) '_Settings.xml'],'w'); if Fid<3 warning('MicroPulse5:FileOperationFailure',Status); return; end fprintf(Fid,EntireString); Status = fclose(Fid); if Status warning('MicroPulse5:FileOperationFailure',Status); return; end end end %% Helper methods methods (Access = private, Hidden = true) function ConnectedCheck(obj) % Checks if a MicroPulse unit is connected, and sends an error if it is not. if ~obj.Connected error('MicroPulse5:NotConnected','A MicroPulse unit must be connected.'); end end end end