Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

281 linhas
12KB

  1. classdef Equipment < handle
  2. %EQUIPMENT Summary of this class goes here
  3. % Detailed explanation goes here
  4. properties (SetAccess=protected)
  5. name
  6. tcp
  7. channel
  8. locked
  9. end
  10. properties (Dependent, SetAccess=private)
  11. error
  12. end
  13. methods
  14. function ecq = Equipment(ipAddress,port,channel)
  15. %EQUIPMENT Construct an instance of this class.
  16. % This functions opens the required TCP connection
  17. % for this device. Channel is GPIB-channel on prologix
  18. % converter if used, otherwise set channel to -1.
  19. % Name is queried from device via '*IDN?' command.
  20. ecq.tcp = Equipment.getTCP(ipAddress,port);
  21. ecq.locked = false;
  22. ecq.channel = channel;
  23. ecq.name = ecq.idn();
  24. if channel >= 0
  25. ecq.setPrologix;
  26. end
  27. end
  28. function id = idn(ecq)
  29. %IDN Queries identificantion from device via '*IDN?'.
  30. id = ecq.query_unsafe('*idn?');
  31. end
  32. function clear(ecq)
  33. %CLEAR Sends clear command to device via '*CLS'.
  34. %This function also clears the TCP inputbuffer;
  35. ecq.write_unsafe('*cls');
  36. flushinput(ecq.tcp);
  37. end
  38. function reset(ecq)
  39. %RESET Sends reset command to device via '*RST'.
  40. ecq.write_unsafe('*rst');
  41. end
  42. function opc(ecq)
  43. %OPC executes 'operation complete query' to device.
  44. %Function holds untill device returns '1'. Must be
  45. %used to avoid interrupting busy device.
  46. ecq.write_unsafe('*OPC?');
  47. for i = 1:10
  48. ack = ecq.read;
  49. if strcmp(ack(1),'1')
  50. return
  51. end
  52. end
  53. error('Device is not ready');
  54. end
  55. function unlock(ecq)
  56. %UNLOCK Sets the device back to 'local control'
  57. %This function only supports devices via the Prologix.
  58. if ecq.channel >= 0
  59. fprintf(ecq.tcp,'++loc');
  60. ecq.locked = false;
  61. end
  62. end
  63. function lock(ecq)
  64. %UNLOCK Sets the device back to 'remote control'
  65. %This function only supports devices via the Prologix.
  66. if ecq.channel >= 0
  67. fprintf(ecq.tcp,'++llo');
  68. ecq.locked = true;
  69. else
  70. warning('Device does not support locking')
  71. end
  72. end
  73. function beep(ecq)
  74. %BEEP Sends the beep command to the device
  75. ecq.write('SYST:BEEP')
  76. end
  77. function write(ecq,message)
  78. %WRITE Sends a command to the channel.
  79. %The function will first check if the device is ready to
  80. %recieve a command via the OPC function. Then send the command
  81. %and eventually check if the device has thrown an error via
  82. %the ERROR function.
  83. %
  84. %See also QUERY
  85. ecq.opc;
  86. ecq.write_unsafe(message);
  87. ecq.error;
  88. end
  89. function output = read(ecq)
  90. %READ Extracts recieved data from the TCP-buffer.
  91. %This function sends the '++read'-command to the Prologix if
  92. %needed. Will always read the TCP-buffer in matlab.
  93. if ecq.channel >= 0
  94. ecq.write_unsafe('++read');
  95. end
  96. output = fscanf(ecq.tcp);
  97. fprintf(['<< ',output]);
  98. end
  99. function output = query(ecq,message)
  100. %QUERY Sends command to the device and read the respond.
  101. %The command is send via the WRITE and the respond is collected
  102. %from the device.
  103. %
  104. %See also WRITE, READ
  105. ecq.opc;
  106. output = ecq.query_unsafe(message);
  107. ecq.error;
  108. end
  109. function errorlist = get.error(ecq)
  110. %ERROR Checks for errors on device. If any, throws a warning.
  111. %The function will pull all errors from the device error stack.
  112. %This is up to a maximum of 20 errors. If errors have occured
  113. %the function will throw a warning with all the error messages.
  114. for i = 1:20
  115. output = ecq.query_unsafe('SYSTem:ERRor?'); %Query error message from device.
  116. % [msgstr, msgid] = lastwarn;
  117. % if strcmp(msgid,'instrument:fscanf:unsuccessfulRead')
  118. % error(['Lost connection with ' ecq.name]);
  119. % end
  120. errorlist(i,1:(length(output))) = output; %Store the error message in the errorlist array.
  121. %GPIB protocol states that the error code '0' means no
  122. %error. The for loop will break if the last recieved error
  123. %code is zero.
  124. if str2double(regexp(output,'\d*','match','once'))==0 %Check if last recieved error code is '0'
  125. % If the 'no error' message is the only error then no
  126. % warning will be trown. However if there is more than
  127. % one error in the list. The function gives a warning
  128. % with all error messages.
  129. if i>1 %check for more than one error message.
  130. warning('Error from device: %s %s',ecq.name,reshape(errorlist(1:i-1,:)',1,[]));
  131. end
  132. ecq.clear;
  133. break;
  134. end
  135. end
  136. end
  137. end
  138. methods% (Access = protected)
  139. function write_unsafe(ecq,message)
  140. %WRITE_UNSAFE Sends command to device.
  141. %This function does not check if device is ready or check if an
  142. %error occured after writing. If possible one should always use
  143. %the WRITE function.
  144. %
  145. %See also WRITE, QUERY
  146. if ecq.channel >= 0
  147. fprintf(ecq.tcp,['++addr ', num2str(ecq.channel)]);
  148. fprintf(['>> ++addr ', num2str(ecq.channel),'\n']);
  149. end
  150. fprintf(ecq.tcp, message);
  151. fprintf(['>> ',message,'\n']);
  152. end
  153. function write_noerror(ecq,message)
  154. %WRITE Sends a command to the channel.
  155. %The function will first check if the device is ready to
  156. %recieve a command via the OPC function. Then send the command.
  157. %
  158. %See also WRITE
  159. ecq.opc;
  160. ecq.write_unsafe(message);
  161. end
  162. function output = query_unsafe(ecq,message)
  163. %QUERY_UNSAFE Sends command to device and reads device output.
  164. %This function does not check if device is ready or check if an
  165. %error occured after writing. If possible one should always use
  166. %the QUERY function.
  167. %
  168. %See also QUERY, WRITE, READ
  169. ecq.write_unsafe(message);
  170. output = read(ecq);
  171. end
  172. end
  173. methods (Access = protected, Hidden)
  174. function setPrologix(ecq)
  175. fprintf(ecq.tcp, '++mode 1'); %set device in controller mode
  176. fprintf(ecq.tcp, '++auto 0'); %disable automatic datapull. this avoids errors on equipment.
  177. end
  178. function delete(ecq)
  179. %DELETE Destructs the current object.
  180. ecq.unlock;
  181. Equipment.getTCP(ecq.tcp.RemoteHost,-ecq.tcp.RemotePort);
  182. end
  183. end
  184. methods (Static)
  185. function tcpobject = getTCP(ipAddress,port)
  186. %GETTCP Returns TCP-object for TCP-connection.
  187. %Function makes a TCP-connection for specific ipAddress and
  188. %port. If TCP-connection already exist no new connection is
  189. %made and only existing handle is returned.
  190. %For existing connections the function will store the amount of
  191. %handles in use. Via the DELETE function the connection will be
  192. %closed if the connection is not in use anymore.
  193. %The connection will be removed if the port is negative number.
  194. persistent tcpconnection; %make variable persistent to share tcp-handles across multiple function calls.
  195. [ipname,ipAddress] = Equipment.ip2structname(ipAddress,abs(port)); %Get a structname and a cleaned ipaddress.
  196. if port > 0 %if port number is positive a connection is made.
  197. if isempty(tcpconnection)
  198. %if the tcpconnection is empty (first time function
  199. %call) make a struct in the variable.
  200. tcpconnection = struct;
  201. end
  202. if ~isfield(tcpconnection, ipname) %check if the handle is already made before.
  203. tcpconnection.(ipname).tcp = tcpip(ipAddress,port); %Make TCP-connection
  204. tcpconnection.(ipname).nopen = 1; %Set number of connections in use to 1
  205. tcpconnection.(ipname).tcp.InputBufferSize = 2^24; %make really large buffer size 64MB. To acquire complete waveforms.
  206. tcpconnection.(ipname).tcp.Timeout = 5; %set timeout to 5 seconds.
  207. fopen(tcpconnection.(ipname).tcp); %Open the TCP-connection
  208. else %If connection already exist. Increase number of connections in use by 1.
  209. tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen + 1;
  210. end
  211. tcpobject = tcpconnection.(ipname).tcp; %return the TCP-connection handle.
  212. elseif port < 0 %If the portnumber is negative the connection is removed.
  213. if tcpconnection.(ipname).nopen > 1
  214. %If more than one object uses this tcp-handle. Decrease
  215. %the number of connections in use by 1.
  216. tcpconnection.(ipname).nopen = tcpconnection.(ipname).nopen - 1; %Decrease the number by 1.
  217. else
  218. %If only one handle uses this connection. The
  219. %connection is closed and the field is removed from the
  220. %tcpconnection struct.
  221. fclose(tcpconnection.(ipname).tcp);
  222. tcpconnection = rmfield(tcpconnection,ipname);
  223. end
  224. else
  225. error([num2str(port),' is not a valid port number try a value between 1 and 65535.']);
  226. end
  227. end
  228. function bool = isnum(input)
  229. %ISNUM Tests if the input is numeric scalar
  230. bool = isnumeric(input)&&isscalar(input);
  231. end
  232. function num = forceNum(input)
  233. %FORCENUM Throws an error if the input is not numeric.
  234. if ~Equipment.isnum(input)
  235. error('Input should be a (single) number.');
  236. end
  237. num = input;
  238. end
  239. function iptest(ipAddress)
  240. %IPTEST Checks if the given IPv4-address is valid.
  241. validip = regexp(ipAddress,'^(?:(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]))$', 'once');
  242. if isempty(validip)
  243. error('Invalid IP-address');
  244. end
  245. end
  246. function [structname,cleanip] = ip2structname(ipAddress,port)
  247. %IP2STRUCTNAME Returns a structname and ip w/out leading zeros.
  248. %structname to store stuff in struct (especially for GETTCP).
  249. %cleanip is a shortened ip without leading zeros.
  250. cleanip = regexprep(ipAddress,'(?:(?<=\.)|^)(?:0+)(?=\d)','');
  251. Equipment.iptest(cleanip);
  252. structname = matlab.lang.makeValidName(['ip',cleanip,'_',num2str(port)]);
  253. end
  254. end
  255. end